#### Archived

This topic is now archived and is closed to further replies.

# Lighting up terrain...

## Recommended Posts

I am creating a terrain engine generated from a heightmap, and I just finished the code to calculate all the vertex normals. But I am fairly inexperienced with OpenGL Lighting, and when I enable a GL_LIGHT, and set up the diffuse and ambient properties, it just doesn't look right at all... I basically want the terrain, to look like terrain, with light coming from a particular spot(a sun). When I tried it, it was either all white, or the tops of my mountains were all white, or the light didn't reach one end of the terrain. I have read the chapter on Lighting in the Red book numerous times, but I am still stuck. Please help me =) Thanks Edited by - jackthemeangiant on November 10, 2001 3:10:04 PM

##### Share on other sites
zedzeek    529
the problem sounds very much like your supplying the incorrect normals.
theres a lot of info/demos/tuts on the net on how to calculate the correct normals
if u have the red book check out appendix E.

first find the normals to all the tris/quads + NOT the vertex normals once u have that info u can work out the vertex normals later

##### Share on other sites
I am almost positive it is not the normals, they are correct.

feagle814    122

##### Share on other sites
Here is a screen shot:

I can post some code if you like, but I am not sure what part you would like to see...

Thanks

##### Share on other sites
ATronic    122
For starters, just post the light initialization code.

A-Tronic Software & Design
-----
"if you fail in life, you were destined to fail. If you suceed in life, call me."

##### Share on other sites
Alright, I can post it later tonight...

My stupid computer crashed when i had VS6 open, and the file with all my normal calcualtions ans lighting in it became corrupted....and i have to re-write it....

##### Share on other sites
ATronic    122
wow.... that sux.

A-Tronic Software & Design
-----
"if you fail in life, you were destined to fail. If you suceed in life, call me."

##### Share on other sites
zedzeek    529
jack even though it still looks like the normals to me.
try making ambient light 0,0,0,0 + use a directional light not a positional one.
about the corrupt file from vc (i take it youre using win2000/XP)

right click on the harddisk select properties->hardware->properties->diskproperties and uncheck disk cache enabled.
u will need to do ths every time u reboot the machine.
ive been bitten a few times by crashes in win2000, when the current open c++ file has been turn into junk. grrrrr

##### Share on other sites
immy    122
Hi Send me the code you use to calculate normals(full code that is the one calculating the trinangular normals & then the function calculating the vertex normals) also tell me what type of light you are using. then i can do something for you. see you then Bye.

##### Share on other sites
I will post my normal calculations in a bit, i have to finish re-writing them

Should i post them all?..becuase it is kinda long. I have to calcualte for 9 different types individualy (4 corners, 4 sides, everything else)

and to zedzeek, i am using win2k, but the disk cache checkbox is disabled for me

Edited by - jackthemeangiant on November 11, 2001 7:44:39 PM

##### Share on other sites
I have uploaded a copy of my program, drawing the terrain in wireframe, and drawing the normals in red:

Press the tilde key to bring down the console, then type

To me, they look correct, but anyways, here is my code for calculating normals:

First of all, here is my map structure:
  //Map Data structuretypedef struct{ float normal[3]; //vertex normal float vertex[3]; //vertex array} c_mapData;//Map structuretypedef struct { int width; //Map width int height; //Map height c_mapData ***mapData; //Dynamic array of map data} c_map;

then it is alocated here, and map data is loaded:
  //Allocate memory for the mapmap = new c_map;map->mapData = new c_mapData **[width]; for (int i = 0; i < (int)width; i ++){ map->mapData[i] = new c_mapData *[height]; for (int t = 0; t < (int)height; t ++) { map->mapData[i][t] = new c_mapData; }}map->width = width;map->height = height;int counter = 0;for (int x = 0; x < map->width; x ++){ for (int y = 0; y < map->height; y ++) { map->mapData[y][x]->vertex[0] = y * stretchSize; map->mapData[y][x]->vertex[1] = (float)((data[counter] / 255.0) * maxHeight); map->mapData[y][x]->vertex[2] = (x * stretchSize)*(-1); map->mapData[y][x]->normal[0] = y * stretchSize; map->mapData[y][x]->normal[1] = (float)((data[counter] / 255.0) * maxHeight); map->mapData[y][x]->normal[2] = (x * stretchSize)*(-1); counter += bytesPerPixel; } }

now this is how I calculate the normals:
  vector_t normal1,normal2,normal3,normal4,normal5,normal6,a,b;a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x - 1][y - 1]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x - 1][y - 1]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x - 1][y - 1]->vertex[2];b[0] = map->mapData[x][y - 1]->vertex[0] - map->mapData[x - 1][y - 1]->vertex[0];b[1] = map->mapData[x][y - 1]->vertex[1] - map->mapData[x - 1][y - 1]->vertex[1];b[2] = map->mapData[x][y - 1]->vertex[2] - map->mapData[x - 1][y - 1]->vertex[2]; Cross(normal1,b,a);a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x][y - 1]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x][y - 1]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x][y - 1]->vertex[2];b[0] = map->mapData[x + 1][y]->vertex[0] - map->mapData[x][y - 1]->vertex[0];b[1] = map->mapData[x + 1][y]->vertex[1] - map->mapData[x][y - 1]->vertex[1];b[2] = map->mapData[x + 1][y]->vertex[2] - map->mapData[x][y - 1]->vertex[2];Cross(normal2,b,a);a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x + 1][y]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x + 1][y]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x + 1][y]->vertex[2];b[0] = map->mapData[x + 1][y + 1]->vertex[0] - map->mapData[x + 1][y]->vertex[0];b[1] = map->mapData[x + 1][y + 1]->vertex[1] - map->mapData[x + 1][y]->vertex[1];b[2] = map->mapData[x + 1][y + 1]->vertex[2] - map->mapData[x + 1][y]->vertex[2];Cross(normal3,b,a);a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x + 1][y + 1]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x + 1][y + 1]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x + 1][y + 1]->vertex[2];b[0] = map->mapData[x][y + 1]->vertex[0] - map->mapData[x + 1][y + 1]->vertex[0];b[1] = map->mapData[x][y + 1]->vertex[1] - map->mapData[x + 1][y + 1]->vertex[1];b[2] = map->mapData[x][y + 1]->vertex[2] - map->mapData[x + 1][y + 1]->vertex[2];Cross(normal4,b,a);a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x][y + 1]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x][y + 1]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x][y + 1]->vertex[2];b[0] = map->mapData[x - 1][y]->vertex[0] - map->mapData[x][y + 1]->vertex[0];b[1] = map->mapData[x - 1][y]->vertex[1] - map->mapData[x][y + 1]->vertex[1];b[2] = map->mapData[x - 1][y]->vertex[2] - map->mapData[x][y + 1]->vertex[2];Cross(normal5,b,a);a[0] = map->mapData[x][y]->vertex[0] - map->mapData[x - 1][y]->vertex[0];a[1] = map->mapData[x][y]->vertex[1] - map->mapData[x - 1][y]->vertex[1];a[2] = map->mapData[x][y]->vertex[2] - map->mapData[x - 1][y]->vertex[2];b[0] = map->mapData[x - 1][y - 1]->vertex[0] - map->mapData[x - 1][y]->vertex[0];b[1] = map->mapData[x - 1][y - 1]->vertex[1] - map->mapData[x - 1][y]->vertex[1];b[2] = map->mapData[x - 1][y - 1]->vertex[2] - map->mapData[x - 1][y]->vertex[2];Cross(normal6,b,a);//average the poly's normalsmap->mapData[x][y]->normal[0] = ((normal1[0] + normal2[0] + normal3[0] + normal4[0] + normal5[0] + normal6[0]) / 6);map->mapData[x][y]->normal[1] = ((normal1[1] + normal2[1] + normal3[1] + normal4[1] + normal5[1] + normal6[1]) / 6);map->mapData[x][y]->normal[2] = ((normal1[2] + normal2[2] + normal3[2] + normal4[2] + normal5[2] + normal6[2]) / 6);//convert to 1 unit lengthNormalize(map->mapData[x][y]->normal);//move normal to proper position by adding the value of the vertex to itmap->mapData[x][y]->normal[0] += map->mapData[x][y]->vertex[0];map->mapData[x][y]->normal[1] += map->mapData[x][y]->vertex[1];map->mapData[x][y]->normal[2] += map->mapData[x][y]->vertex[2]; Cross and Normalize are defined as: //finds the cross product of two vectorsvoid Cross(vector_t &norm,vector_t vec1,vector_t vec2){ norm[0] = vec1[1]*vec2[2]-vec2[1]*vec1[2]; norm[1] = vec1[2]*vec2[0]-vec2[2]*vec1[0]; norm[2] = vec1[0]*vec2[1]-vec2[0]*vec1[1];}void Normalize(vector_t &norm){ int magnitude; //find magnitude to normilze magnitude = sqrt((norm[0] * norm[0]) + (norm[1] * norm[1]) + (norm[2] * norm[2])); if (magnitude == 0) magnitude = 1; //divide by the magnitude to set the normal's length to 1 unit norm[0] /= magnitude; norm[1] /= magnitude; norm[2] /= magnitude;}

Edited by - jackthemeangiant on November 11, 2001 8:15:18 PM

##### Share on other sites
Guest Anonymous Poster
Alright,
zedzeek, I tried what you said to try making ambient light 0,0,0,0 + use a directional light not a positional one. and this is what is looks like

http://jackthemeangiant.l33t.ca/valley%20of%20normals.jpg

the problem is that the light isn''t reaching all of the map.

I don''t know if I am expecting the wrong thing from gl_lighting. I bascily want a very nice looking terrain engine, like the one that used to be on glVelocity''s site Xterminate i think it was called (btw what happend to that site).

##### Share on other sites
zedzeek    529
basically only the high parts are getting lit, which does suggest incorrect normals

u can also try glEnable( GL_NORMALIZE );

##### Share on other sites
immy    122
From the appearence of the normals in the newly posted screen shots it seems as if they are all not of the same magnitude(that is unit magnitude) so try this

1)Don''t normalize the normals your self.
2)Use glEnable(GL_NORMALIZE) (before drawing the terrain) to let openGL normalize the normals itself then disable it after drawing the terrain using glDisable(GL_NORMALIZE).

Try this may be this works.Good Luck :-)

manni

##### Share on other sites
Alright, now I think I am getting somewhere =)

this is using GL_NORMALIZE

http://jackthemeangiant.l33t.ca/w00t.jpg

Does this picture look more correct?

if it is, then what is wrong with my normalizing code?

  void Normalize(vector_t &norm){ int magnitude; //find magnitude to normilze magnitude = sqrt((norm[0] * norm[0]) + (norm[1] * norm[1]) + (norm[2] * norm[2])); if (magnitude == 0) magnitude = 1; //divide by the magnitude to set the normal's length to 1 unit norm[0] /= magnitude; norm[1] /= magnitude; norm[2] /= magnitude;}

Edited by - jackthemeangiant on November 11, 2001 12:30:30 AM

##### Share on other sites
immy    122
try using the same light source you are using in the first screen shot you posted. One more thing before setting the light position the Model View Matrix must be Identity so that your original light position is not get disturbed. Tope it will work Good luck

manni

##### Share on other sites
jwace81    160
Well, from the normalization code that you posted, I''d guess that your normals will most likely never have the correct length of one unit, because you are using an integer for the magnitude. An integer does not have the precision that you need for normalizing the vectors. You should use a float or a double instead. Aside from that, the code looks right, although you could probably get rid of the test for a magnitude of 0 since the only vector that would give you such a magnitude would be the 0 vector (0,0,0).

j.w.

##### Share on other sites
I caught that mistake myself, and change it to a float, but it makes no difference. It was suggested that glScale would mess it up on another message board, but i am not using it.

Anyone?

##### Share on other sites
immy    122
Go to this site

http://www.opengl.org/developers/code/features/KilgardTechniques/oglpitfall/oglpitfall.html

Here you can get info if you are going to use glScalef(sx,sy,sz);

Let me know if it helps you. bye

manni