Help with lighting on my terrain
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 on 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 one from point[0] to point[1] and one 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>
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]
normal[x,z]: normal[x-1,z], normal[x+1,z],normal[x+1,z],normal[x,z+1]
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:
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:
Or at least I THINK he meant that.
[edited by - biovenger on April 12, 2004 6:54:24 AM]
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]
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]
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.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement