Heightmap vertex normals

5267893185d8da9628691815730fb758
0
caesar4 101 Sep 23, 2004 at 23:29

When you load a heightmap in your game, some of you would want to be able to light it, but in order to have lighting, you must also have the vertex normals.
This method is simple, works by averaging the normals of all adjacent triangle normals

Vertex declaration I’m using

typedef struct _SVNormVertexIColor{
    CVector vecPosition;
    CVector vecNormal;
    unsigned int uiColor;
    static const unsigned int FVF;
}SVNormVertexIColor;
const unsigned int _SVNormVertexIColor::FVF = (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE);

Normal calualation code:

// we have 'w'-width and 'h'-lenght of the heightmap

// i am assuming that you have already read all the vertices into a linear vertex buffer, with the normal vector set to 0.f

int _h = h-1;
int _w = w-1;

// cycle through each row
for(int i = 0; i < _h; i++){
 // cycle through each column
 for(int j = 0; j < _w; j++){
  CVector p1,p2,p3,v1,v2,tmp;
  int v[4];
  // calculate the positions int the vertex buffer of the adjacent vertices
  // v[0] is current vertex
  v[0] = i*h+j; v[1] = i*h+j+1;
  v[2] = (i+1)*h+j; v[3] = (i+1)*h+j+1;

  // store the positions of first triangle into 3 usable vertices
  p1 = this->vertices[v[0]].vecPosition;
  p2 = this->vertices[v[3]].vecPosition;
  p3 = this->vertices[v[2]].vecPosition;

  // calculate the triangle sides
  v1 = p2 - p1;v2 = p3 - p1;

  // calculate normal
  tmp = v1.Cross(v2);
  // add normal to the normal of all the vertices in the triangle
  this->vertices[v[0]].vecNormal+= tmp;
  this->vertices[v[3]].vecNormal+= tmp;
  this->vertices[v[2]].vecNormal+= tmp;
 
  // store the positions of second triangle into 3 usable vertices
  p1 = this->vertices[v[1]].vecPosition;
  p2 = this->vertices[v[3]].vecPosition;
  p3 = this->vertices[v[0]].vecPosition;

  // calculate the triangle sides
  v1 = p2 - p1;v2 = p3 - p1;
  // calculate normal
  tmp = v1.Cross(v2);
  // add normal to the normal of all the vertices in the triangle
  this->vertices[v[1]].vecNormal+= tmp;
  this->vertices[v[3]].vecNormal+= tmp;
  this->vertices[v[0]].vecNormal+= tmp;
 }
}

// normalize all vertices
for(i = 0; i<this->iVertCount; i++)
 this->vertices[i].vecNormal.Normalize();

2 Replies

Please log in or register to post a reply.

2b97deded6213469bcd87b65cce5d014
0
Mihail121 102 Sep 24, 2004 at 06:07

Ok i don’t want to be rude but this is the third normal-calculating sample in a month!!!

5267893185d8da9628691815730fb758
0
caesar4 101 Oct 01, 2004 at 03:20

@Mihail121

Ok i don’t want to be rude but this is the third normal-calculating sample in a month!!! [snapback]11899[/snapback]

Sure, but none of the other samples included acurate calculations, theyll just take the normal of a triangle, give it to its 3 vertices, and move on to the next triangle
this sample averages the normals of the adjacent triangles (which is partly wy it runs a little slow) and provides more accurate data, for lighting