Normal Map Generator / No function

General FreeBASIC programming questions.
Post Reply
csde_rats
Posts: 114
Joined: Jun 02, 2007 21:13
Contact:

Normal Map Generator / No function

Post by csde_rats »

Hi!

I've translated ATIs NormalMapGen to FreeBASIC, but there are some problems:
Image
My test-heightmap

Image
Result of my Program

Image
Result of ATIs Program

http://28398labs.28.funpic.de/stuff/DOT3.bas
sourcecode

http://28398labs.28.funpic.de/stuff/TGAtoDOT3.cpp
ATIs sourcecode

And, the main loop (altough included in the sourcecode, but i post it here :D )

Code: Select all

		For y = 0 To gHeight
			For x = 0 To gWidth
				' Do Y Sobel filter
				pix = srcImage((x-1+gWidth) Mod gWidth, (y+1) Mod gHeight)
				dY = Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage(x Mod gWidth, (y+1) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * -2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y+1) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 1.0)
				
				pix = srcImage(x Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 1.0)
				
				' Do X Sobel filter
				pix = srcImage((x-1+gWidth) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dX = Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, y Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * -2.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, (y+1) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x+1) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 1.0)
				
				pix = srcImage((x+1) Mod gWidth, y Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y+1) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 1.0)
				
				' Cross Product of components of gradient reduces to
				nX = -dX
				nY = -dY
				nZ = 1
				
				' Normalize
				oolen = 1.0/Cast(Double, Sqr(nX^2 + nY^2 + nZ^2))
				nX *= oolen ' nX *= oolen; ??
				nY *= oolen ' nY *= oolen; ??
				nZ *= oolen ' nZ *= oolen; ??
				
				pix.red = PackFloatInByte(nX)
				pix.green = PackFloatInByte(nY)
				pix.blue = PackFloatInByte(nZ)
				
				dstImage(x, y) = pix
			Next x
		Next y
As you can see, the given results are not matching the results of ATIs Program!
Can anyone help me?

(by the way: Yes i changed the stupid pointer and so on to an array, but both translations give wrong results... :( )
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Normal Map Generator / No function

Post by dodicat »

csde_rats wrote:Hi!

I've translated ATIs NormalMapGen to FreeBASIC, but there are some problems:
Image
My test-heightmap

Image
Result of my Program

Image
Result of ATIs Program

http://28398labs.28.funpic.de/stuff/DOT3.bas
sourcecode

http://28398labs.28.funpic.de/stuff/TGAtoDOT3.cpp
ATIs sourcecode

And, the main loop (altough included in the sourcecode, but i post it here :D )

Code: Select all

		For y = 0 To gHeight
			For x = 0 To gWidth
				' Do Y Sobel filter
				pix = srcImage((x-1+gWidth) Mod gWidth, (y+1) Mod gHeight)
				dY = Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage(x Mod gWidth, (y+1) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * -2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y+1) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 1.0)
				
				pix = srcImage(x Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dY += Cast(Double, pix.red / 255.0 * 1.0)
				
				' Do X Sobel filter
				pix = srcImage((x-1+gWidth) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dX = Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, y Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * -2.0)
				
				pix = srcImage((x-1+gWidth) Mod gWidth, (y+1) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * -1.0)
				
				pix = srcImage((x+1) Mod gWidth, (y-1+gHeight) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 1.0)
				
				pix = srcImage((x+1) Mod gWidth, y Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 2.0)
				
				pix = srcImage((x+1) Mod gWidth, (y+1) Mod gHeight)
				dX += Cast(Double, pix.red / 255.0 * 1.0)
				
				' Cross Product of components of gradient reduces to
				nX = -dX
				nY = -dY
				nZ = 1
				
				' Normalize
				oolen = 1.0/Cast(Double, Sqr(nX^2 + nY^2 + nZ^2))
				nX *= oolen ' nX *= oolen; ??
				nY *= oolen ' nY *= oolen; ??
				nZ *= oolen ' nZ *= oolen; ??
				
				pix.red = PackFloatInByte(nX)
				pix.green = PackFloatInByte(nY)
				pix.blue = PackFloatInByte(nZ)
				
				dstImage(x, y) = pix
			Next x
		Next y
As you can see, the given results are not matching the results of ATIs Program!
Can anyone help me?

(by the way: Yes i changed the stupid pointer and so on to an array, but both translations give wrong results... :( )
I'm getting a crash.
I notice that gheight and gwidth are 0
then you ask for (something) mod gheight and gwidth which is considered division by 0
csde_rats
Posts: 114
Joined: Jun 02, 2007 21:13
Contact:

Post by csde_rats »

Ok, haven't I said that the input file must be in TARGA 24/32 BPP/Uncompressed format must be? ^^
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Perhaps you're getting thrown in the For loop translation?
Usally images loop from 0 to dimension-1, which gives you dimension elements. Your loops go from 0 to dimension, which gives you dimension+1 elements.
csde_rats
Posts: 114
Joined: Jun 02, 2007 21:13
Contact:

Post by csde_rats »

Thanks!
But after correcting it in all loops, i tested it with the same result ... :(

so i'm checking again the Sobel-Filter...

btw.
In C/C++ the statement "a % b" means in fb "a mod b", right?
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Right.
Unfortunately, I'm having trouble downloading the source code you're linking to, but I can't see any glaringly obvious problems in the code you've posted.
Perhaps you could bundle them both up and post it on MediaFire or something. You could also add an image in the appropriate format, just to remove any doubt there.
csde_rats
Posts: 114
Joined: Jun 02, 2007 21:13
Contact:

Post by csde_rats »

files in archive:
map.tga - heightmap
map_nrm.tga - result of my translation
mapDOT3.tga - result of ATIs program

All C/C++ belongs to the original program (TGAtoDOT3.cpp, TGAtoDOT3.dsp, TGAtoDOT3.dsw, TGAtoDOT3.exe, ATI.ico, resource.h and winmain.rc)
DOT3.bas and DOT3.exe = my translation

Download
wolfstar
Posts: 96
Joined: Nov 07, 2006 12:42

Post by wolfstar »

I've had those sorts of problems before, and it's usually 'cause my colours are overflowing. Especially when I change integer to byte and so on. From the pictures it looks like there's nothing wrong with your height map.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Post by counting_pine »

Yes, it is an overflow issue - looking at the original program, it looks like BYTEs are unsigned. But bytes are signed in FB - anything between 128 and 255 will be treated as in the range -128 to -1. Try ubytes there instead.

Additionally, it looks like there's an off-by-one error when you're reading and writing the image. If you look at the output image, the RGB channels are shifted out, and if you pset the pixels as you initially read them in, you can see the Red channel is out one in what should be a grayscale image.
Not sure how to fix that. Hopefully if you can though, you'll then get an identical output image. (Fingers crossed...)
csde_rats
Posts: 114
Joined: Jun 02, 2007 21:13
Contact:

Post by csde_rats »

YES!
That was it!!
Char = UByte, not Byte!!!
Thank you all!!
Now i get EXACTLY the same result!!
THANX!
Post Reply