Advertisement

Terrain from a heightmap...normals

Started by January 15, 2001 07:42 AM
6 comments, last by m9 23 years, 10 months ago
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
---conehttp://cone.cz.eePS. The Dog Ate My Homework
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

Advertisement
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-.
Hi,

Can you send me the code for your engine ?

Thanks in advance.


Leyder Dylan
dylan.leyder@ibelgique.com
========================Leyder Dylan (dylan.leyder@slug-production.be.tf http://users.skynet.be/fa550206/Slug-Production/Index.htm/
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?
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
---conehttp://cone.cz.eePS. The Dog Ate My Homework
Advertisement
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.
------------------------------Piggies, I need more piggies![pig][pig][pig][pig][pig][pig]------------------------------Do not invoke the wrath of the Irken elite. [flaming]
ok, i''ll try the method pez and avian suggested.
I''ll post back soon...


---
marius
http://fr.ee/linux
---conehttp://cone.cz.eePS. The Dog Ate My Homework

This topic is closed to new replies.

Advertisement