• Advertisement

Archived

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

Terrain from a heightmap...normals

This topic is 6246 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, everybody. I''ve created a small terrain engine, that generates a terrain out of a heightmap. But when enabling lighting, everything looks blocky. Could somebody modify the source code to make it look good? The function that generates the terrain looks like this:
  
char BuildTerrain()
{
  terr=glGenLists(1);
  glNewList(terr,GL_COMPILE);

  glBegin(GL_TRIANGLE_STRIP);
  for(unsigned int x=0;x<terrain.width;x++)
  {
    for(unsigned int y=0;y<terrain.height-1;y++)
    {
      point N, P1, P2, P3, P4;

      float aa=(float)terrain.imageData[(y*terrain.width+x)*3];
      float bb=(float)terrain.imageData[(y*terrain.width+x+1)*3];
      float cc=(float)terrain.imageData[((y+1)*terrain.width+x+1)*3];
      float dd=(float)terrain.imageData[((y+1)*terrain.width+x)*3];

      P1.x=x+0.0f-(terrain.width/2);
      P1.y=y+0.0f-(terrain.height/2);
      P1.z=(float)terrain.imageData[(y*terrain.width+x)*3];
      P1.s=(x+0.0f)/terrain.width;
      P1.t=(y+0.0f)/terrain.height;

      P2.x=x+1.0f-(terrain.width/2);
      P2.y=y+0.0f-(terrain.height/2);
      P2.z=(float)terrain.imageData[(y*terrain.width+x+1)*3];
      P2.s=(x+1.0f)/terrain.width;
      P2.t=(y+0.0f)/terrain.height;

      P3.x=x+1.0f-(terrain.width/2);
      P3.y=y+1.0f-(terrain.height/2);
      P3.z=(float)terrain.imageData[((y+1)*terrain.width+x+1)*3];
      P3.s=(x+1.0f)/terrain.width;
      P3.t=(y+1.0f)/terrain.height;

      P4.x=x+0.0f-(terrain.width/2);
      P4.y=y+1.0f-(terrain.height/2);
      P4.z=(float)terrain.imageData[((y+1)*terrain.width+x)*3];
      P4.s=(x+0.0f)/terrain.width;
      P4.t=(y+1.0f)/terrain.height;

      N.x = P1.y*(P2.z - P3.z) + P2.y*(P3.z - P1.z) + P3.y*(P1.z - P2.z);
      N.y = P1.z*(P2.x - P3.x) + P2.z*(P3.x - P1.x) + P3.z*(P1.x - P2.x);
      N.z = P1.x*(P2.y - P3.y) + P2.x*(P3.y - P1.y) + P3.x*(P1.y - P2.y);

      float Mag = sqrt((N.x*N.x)+(N.y*N.y)+(N.z*N.z)); // Length of Vector

      N.x = N.x / Mag; // Normalize Vector

      N.y = N.y / Mag;
      N.z = N.z / Mag;

      glNormal3f(N.x,N.y,N.z);
      glTexCoord2f(P2.s,P2.t); glVertex3f(P2.x,P2.y,P2.z);
      glTexCoord2f(P1.s,P1.t); glVertex3f(P1.x,P1.y,P1.z);
      glTexCoord2f(P3.s,P3.t); glVertex3f(P3.x,P3.y,P3.z);
      glTexCoord2f(P4.s,P4.t); glVertex3f(P4.x,P4.y,P4.z);
    }
  }
  glEnd();
  glEndList();

  return 1;
}
  
--- marius http://fr.ee/linux

Share this post


Link to post
Share on other sites
Advertisement
Hi there,

take the normals for the four faces adjoining the vertex
and average these ie.

*---*---*
|n1 | n2|
*---p---*
|n3 | n4|
*---*---*

p.n = (n1 + n2 + n3 + n4) * .25

Hope this helps

Share this post


Link to post
Share on other sites
just one thing.

If you are using quads, do as MButcher.

If you are using triangles or triange strips, average the normals of all six surounding triangles. This will look even better.

.-o-o
|/|/|
o-O-o
|/|/|
o-o-.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
In fact there is an additional optimization that can be made. The most visually appealing way to calculate normals uses a weighted average - I think it weights the normal of each neighboring polygon based on the size of the angle at the particular vertex, but I don''t recall exactly. Does anyone know the algorithm I am thinking of?

Share this post


Link to post
Share on other sites
I''ve uploaded the entire terrain demo to:
http://www.hot.ee/marius/terrain/terrain.tar.gz

It''s compressed with tar and gz, but winzip (and possibly others) still know how to open it.

It''s created on a linux mandrake 7.2 system, but can be compiled for windows with the mingw32 compiler
it can be found at:
http://www.libsdl.org/Xmingw32/index.html

also I''m having HUGE problems with walking on the terrain. If anybody could help me here, I would be really thankful.


I''ll try the normal calculations soon...
Thanx for your ideas everybody...

---
marius
http://fr.ee/linux

Share this post


Link to post
Share on other sites
What I was doing on my orriginal terrain engine (I''m currently rewriting it to add new features and improve speed) was as pez said. calculating the normals for each of the six adjacent triangles then simply add all the values together and divide by 6. That gave excelent results in my engine.

Share this post


Link to post
Share on other sites
ok, i''ll try the method pez and avian suggested.
I''ll post back soon...


---
marius
http://fr.ee/linux

Share this post


Link to post
Share on other sites

  • Advertisement