Advertisement

Lighting up terrain...

Started by November 10, 2001 02:09 PM
19 comments, last by Jackthemeangiant 23 years, 3 months ago
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.
manni
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
Advertisement
I have uploaded a copy of my program, drawing the terrain in wireframe, and drawing the normals in red:

http://jackthemeangiant.l33t.ca/invaders/Invaders.rar

Press the tilde key to bring down the console, then type
"/loadmap map" without the "'s

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
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).
basically only the high parts are getting lit, which does suggest incorrect normals

u can also try glEnable( GL_NORMALIZE );
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
manni
Advertisement
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
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
manni
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.
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?

This topic is closed to new replies.

Advertisement