Help with lighting on my terrain

Started by
4 comments, last by knealeaj 20 years ago
I have written a simple terrain engine using a bitmap for the heightfield terrain. The terrain is fine but when it comes to the lighting the hills look blocky ,I think the polygon normals i am giving to glNormal3fv(I am using OpenGL) are wrong but i cant see where I have gone wrong. can you have a look .Here is the relevant code. Sorry for the mess #define TERRAIN_MAP_X 64 #define TERRAIN_MAP_Z 64 #define MAP_SCALE 20.0f float diffuseLight1[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float specularLight1[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float lightPosition1[] = { -550.0f, -250.0f, -150.0f, 1.0f }; float ambientLight1[]={ 1.0f, 1.0f, 1.0f, 1.0f }; void InitScene4(); void Scene4(); void GetFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]); void CrossProduct(float *c,float a[3],float b[3]); void Normalise(float *vect); float normals[5000][3];//normals for the faces of the terrain void InitTerrain() { terrainTex = new Texture; imageData = terrainTex->LoadBitmapFile("Terrain2.bmp",&bitmapInfoHeader); for(int z= 0;z<TERRAIN_MAP_Z;z++) { for(int x=0;x<TERRAIN_MAP_X;x++) { terrain[x][z][0] = float(x)*MAP_SCALE; terrain[x][z][1] = (float)(imageData[(z*TERRAIN_MAP_Z+x)*3]); terrain[x][z][2] = -float(z)*MAP_SCALE; } } } void InitScene4() { InitTerrain(); // LIGHT1 is the world light glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight1); glLightfv(GL_LIGHT1, GL_SPECULAR, specularLight1); glLightfv(GL_LIGHT1, GL_POSITION, lightPosition1); glLightfv(GL_LIGHT1, GL_AMBIENT, ambientLight1); } void Scene4() { static float count=0.0f,count2=0.0f; glPushMatrix(); glTranslatef(-550.0f,-250.0f,-150.0f+count); glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glEnable(GL_LIGHTING); // enable lighting // Enable the lights //glEnable(GL_LIGHT0); glEnable(GL_LIGHT1); glBindTexture(GL_TEXTURE_2D, textures[1].texID); //loop through all of the terrains data points for(int z=0;z<TERRAIN_MAP_Z-1;z++) { glBegin(GL_TRIANGLE_STRIP); for(int x=0;x<TERRAIN_MAP_X-1;x++) { GetFaceNormal(normals[x+x*z],terrain[x][z],terrain[x+1][z],terrain[x][z+1]); glNormal3fv(normals[x+x*z]); //draw vertex 0 glColor3f(terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f, terrain[x][z][1]/255.0f); glTexCoord2f(0.0,0.0); glVertex3f(terrain[x][z][0],terrain[x][z][1],terrain[x][z][2]); //draw vertex 1 glColor3f(terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f, terrain[x+1][z][1]/255.0f); glTexCoord2f(1.0,0.0); glVertex3f(terrain[x+1][z][0],terrain[x+1][z][1],terrain[x+1][z][2]); //draw vertex 2 glColor3f(terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f, terrain[x][z+1][1]/255.0f); glTexCoord2f(0.0,1.0); glVertex3f(terrain[x][z+1][0],terrain[x][z+1][1],terrain[x][z+1][2]); //draw vertex 3 glColor3f(terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f, terrain[x+1][z+1][1]/255.0f); glTexCoord2f(1.0,1.0); glVertex3f(terrain[x+1][z+1][0],terrain[x+1][z+1][1],terrain[x+1][z+1][2]); } } glEnd(); glPopMatrix(); glDisable(GL_DEPTH_TEST); count += 5.0f; count2 -= 1.0f; } void GetFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]) { float vect[2][3]; //two vectors &#111;n plane of quad int a,b; //counters float point[3][3]; //2 dimensional array for pointa pointb and pointc //put pointa pointb and pointc in the two dimensional array for(a=0;a<3;a++) { point[0]<A href='http:// = pointa[a]; point[1][a] = pointb[a]; point[2][a] = pointc[a]; } //now calculate the two vectors &#111;ne from point[0] to point[1] and &#111;ne from point[0] to point[2] for(a=0;a<2;a++) { for(b=0;b<3;b++) { vect[a]<b> = point[2-a] - point[0]; } } CrossProduct(norm,vect[0],vect[1]); //calculates vector at 90° to 2 vectors Normalise(norm); //makes the vector length 1 } void CrossProduct(float *c,float a[3],float b[3]) { //finds the cross product of two vectors c[0] = a[1]*b[2] - b[1]*a[2]; c[1] = a[2]*b[0] - b[2]*a[0]; c[2] = a[0]*b[1] - b[0]*a[1]; } void Normalise(float *vect) { float length; int a; length=sqrt( //A^2 + B^2 + C^2 = length^2 pow(vect[0],2)+ pow(vect[1],2)+ pow(vect[2],2) ); for(a=0;a<3;a++) { vect[a] /= length; //divides vector by its length to normalise } } </b> ' Target=_Blank>Link</a>
Advertisement
try to calculate the normals with more neighbors, and promediate them:

normal[x,z]: normal[x-1,z], normal[x+1,z],normal[x+1,z],normal[x,z+1]
============================== Videoman Library Project
Could you please expand on that please jaba

thanks
Normal of plane if you know two non-paralell vectors in the plane:

vector1 x vector2. That is IF they are positively oriented. (Otherwise you get the negative normal)

So, basically, here is a method:

void GetFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]){    norm[0] = (pointb[0] - pointa[0]) * (pointc[0] - pointa[0]);    norm[1] = (pointb[1] - pointa[1]) * (pointc[1] - pointa[1]);    norm[2] = (pointb[2] - pointa[2]) * (pointc[2] - pointa[2]);}   


That above can be done with a loop, but is quite unneccecary (and inefficent if this method is called 1000 times per frame).

That should calculate the plane's true normal.

Also, what jaba meant by promediating is this:

float norm[3][3]; // three different normalsfloat truenorm[3]; // True normalfor(int i = 0; i < 3; i++)   truenorm[i] = norm[0][i] + norm[1][i] + norm[2][i];


Or at least I THINK he meant that.

[edited by - biovenger on April 12, 2004 6:54:24 AM]
-----------------------------Final Frontier Trader
quote:Original post by biovenger
Normal of plane if you know two non-paralell vectors in the plane:

vector1 x vector2. That is IF they are positively oriented. (Otherwise you get the negative normal)

So, basically, here is a method:

void GetFaceNormal(float *norm,float pointa[3],float pointb[3],float pointc[3]){    norm[0] = (pointb[0] - pointa[0]) * (pointc[0] - pointa[0]);    norm[1] = (pointb[1] - pointa[1]) * (pointc[1] - pointa[1]);    norm[2] = (pointb[2] - pointa[2]) * (pointc[2] - pointa[2]);}  


Umm, but which point is pointa, which is pointb and which is pointc? Surely if you use the wrong ones then you'll get a funny normal vector?

a b
+-------+
|
|
|
+ c

would surely be different to

b c
+-------+
|
|
|
+ a

(I'm having problems doing this too...)

--
Never
My game

[edited by - Never on April 12, 2004 7:09:24 AM]
-- All outta gum
That''s what I said, you must know if the points form two positively oriented vectors or not. You can only get two versions of the normal vector with respect to 3 points in a plane:
Either the normal, or the negative normal (-n).

Choose points wisely in the plane, such as the lower left, upper right and lower right would be good as a, b, c for a quad.

Also, in the examples you drew for me, you would get exactly the same normal in both. Except in the first example you would get the negative normal.
-----------------------------Final Frontier Trader

This topic is closed to new replies.

Advertisement