normal calculation

Started by
8 comments, last by Dragon_Strike 18 years, 10 months ago
could someone please write me a function to calculate normals of a mesh... the function should use the value of float WaterHeight[x][y] and calculate the normals into the field float WaterNormal[x1][y1][z1][x][y] (yea i know its a bit wierd but i dont want to use vectors... i have my reasons...) thx...
Advertisement
Since it looks like you are calculating normals for planar mesh (water/terrain) this thread will help you.

If you are thinking about general meshes then tell us and we'll give you more specific answer.

PS: And you better have very good reasons for using WaterNormal[x1][y1][z1][x][y]. You probably know it requires 4 multiplications and 4 additions to get a single value from that, right?
You should never let your fears become the boundaries of your dreams.
In this thread I posted some code which has a routine I use for water - but it uses vectors. It's very straightforward, so you might be able to convert it to the calc above.

hth
F451
lol i dont understand either of those... thats the reason id like to have an alrdy finished function that uses float HeightMap[x][z] and calculates CVECTOR NormalMap[x][z].. ive programmed all the vector operators but not the crossproduct...

if somebopdy could do this for me id be very thankful... shouldnt take much time jsut reprogram some function uve alrdy got..
Quote:Original post by Anonymous Poster
lol i dont understand either of those... thats the reason id like to have an alrdy finished function that uses float HeightMap[x][z] and calculates CVECTOR NormalMap[x][z]..

People will generally not just give you the code in the form you need. First you have to show that you did put some work in it. The links posted above or a quick google search would give you more than you need to implement it yourself.

Quote:Original post by Anonymous Poster
ive programmed all the vector operators but not the crossproduct...

a) Generating terrain/water normals does not require cross product.
b) You should be able to write it yourself in 5 min with a help of math book/Google/open-source projects/.. if you actualy need it.
You should never let your fears become the boundaries of your dreams.
well the reason i want somebody else to write it is because i cant get it to work myself... here is my code if u can find whats wrong id apprecieate that also...

void CTERRAIN::SetUpNormals(int a)
{

// m_fVec[0]= x;
// m_fVec[1]= y;
// m_fVec[2]= z;

CVECT0R HeightMap[128][128];

for (int z = 0; z 0 && z 0 && x 0 && z 0 && x <
void CTERRAIN::SetUpNormals(int a)
{

// m_fVec[0]= x;
// m_fVec[1]= y;
// m_fVec[2]= z;

CVECT0R HeightMap[128][128];

for (int z = 0; z < 128; z++){
for (int x = 0; x < 128; x++){
HeightMap[z][x][a].m_fVec[0] = x;
HeightMap[z][x][a].m_fVec[1] = GetWaterHeight(x, z, a);
HeightMap[z][x][a].m_fVec[2] = z;
}
}


CVECTOR v1,v2,v3,v4,v5,v6;
CVECTOR n,n1,n2,n3,n4,n5,n6;

for (int z = 0; z < 128; z++ ) {
for (int x = 0; x < 128; x++ ) {
if ( z == 0 && x == 0 ) {
// back left corner - 1 tri 2 vertices
v1 = HeightMap[z+1][x] - HeightMap[z][x];
v2 = HeightMap[z][x+1] - HeightMap[z][x];

n = Cross(v1,v2);

} else if ( (z > 0 && z < (128-1)) && x == 0 ) {
// left edge - 3 tri 4 vertices
v1 = HeightMap[z][x+1] - HeightMap[z][x];
v2 = HeightMap[z-1][x+1] - HeightMap[z][x];
v3 = HeightMap[z-1][x] - HeightMap[z][x];
v4 = HeightMap[z][x+1] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);
n3 = Cross(v3,v4);

n = (n1+n2+n3)/3.0f;

} else if ( z == (128-1) && x == 0 ) {
// front left corner - 2 tri 3 vertices
v1 = HeightMap[z][x+1] - HeightMap[z][x];
v2 = HeightMap[z-1][x+1] - HeightMap[z][x];
v3 = HeightMap[z-1][x] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);

n = (n1+n2)/2.0f;

} else if ( z == (128-1) && (x > 0 && x < (128-1)) ) {
// front edge - 3 tri 4 vertices
v1 = HeightMap[z][x+1] - HeightMap[z][x];
v2 = HeightMap[z-1][x+1] - HeightMap[z][x];
v3 = HeightMap[z-1][x] - HeightMap[z][x];
v4 = HeightMap[z][x-1] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);
n3 = Cross(v3,v4);

n = (n1+n2+n3)/3.0f;

} else if ( z == (128-1) && x == (128-1) ) {
// front right corner - 1 tri 2 vertices
v1 = HeightMap[z-1][x] - HeightMap[z][x];
v2 = HeightMap[z][x-1] - HeightMap[z][x];

n1 = Cross(v1,v2);

n = n1;

} else if ( ( z > 0 && z < (128-1)) && x == (128-1) ) {
// right edge - 3 tri 4 vertices
v1 = HeightMap[z-1][x] - HeightMap[z][x];
v2 = HeightMap[z][x-1] - HeightMap[z][x];
v3 = HeightMap[z+1][x-1] - HeightMap[z][x];
v4 = HeightMap[z+1][x] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);
n3 = Cross(v3,v4);

n = (n1+n2+n3)/3.0f;

} else if ( z == 0 && x == (128-1) ) {
// back right corner - 2 tri 3 vertices
v1 = HeightMap[z][x-1] - HeightMap[z][x];
v2 = HeightMap[z+1][x-1] - HeightMap[z][x-1];
v3 = HeightMap[z+1][x-1] - HeightMap[z][x];
v4 = HeightMap[z+1][x] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v3,v4);

n = (n1+n2)/2.0f;

} else if ( z == 0 && ( x > 0 && x < (128-1)) ) {
// back edge - 3 tri 4 vertices
v1 = HeightMap[z][x-1] - HeightMap[z][x];
v2 = HeightMap[z+1][x-1] - HeightMap[z][x];
v3 = HeightMap[z+1][x] - HeightMap[z][x];
v4 = HeightMap[z][x+1] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);
n3 = Cross(v3,v4);

n = (n1+n2+n3)/3.0f;

} else {
// internal - 6 tri 6 vertices
v1 = HeightMap[z][x+1] - HeightMap[z][x];
v2 = HeightMap[z-1][x+1] - HeightMap[z][x];
v3 = HeightMap[z-1][x] - HeightMap[z][x];
v4 = HeightMap[z][x-1] - HeightMap[z][x];
v5 = HeightMap[z+1][x-1] - HeightMap[z][x];
v6 = HeightMap[z+1][x] - HeightMap[z][x];

n1 = Cross(v1,v2);
n2 = Cross(v2,v3);
n3 = Cross(v3,v4);
n4 = Cross(v4,v5);
n5 = Cross(v5,v6);
n6 = Cross(v6,v1);

n = (n1+n2+n3+n4+n5+n6)/6.0f;

}
Normalize(n);

/*inline void SetNormal(int x, int z, int a, float x1, float y1, float z1){

//CVECTOR NormalMap[128][128][128];
// m_fVec[0]= x;
// m_fVec[1]= y;
// m_fVec[2]= z;

NormalMap[x][y][a].m_fVec[0] = x1;
NormalMap[x][y][a].m_fVec[1] = y1;
NormalMap[x][y][a].m_fVec[2] = z1;
}
*/


SetNormal(x, z , a, n.m_fVec[0], n.m_fVec[1], n.m_fVec[2]);
}
}
}

CVECTOR CTERRAIN::Cross(const CVECTOR &vec1, const CVECTOR &vec2){

// m_fVec[0]= x;
// m_fVec[1]= y;
// m_fVec[2]= z;

return CVECTOR(vec1.m_fVec[1] * vec2.m_fVec[2] - vec1.m_fVec[2] * vec2.m_fVec[1],
vec1.m_fVec[2] * vec2.m_fVec[0] - vec1.m_fVec[0] * vec2.m_fVec[2],
vec1.m_fVec[0] * vec2.m_fVec[1] - vec1.m_fVec[1] * vec2.m_fVec[0],);
}

void CTERRAIN::Normalize(CVECTOR &vec){

// m_fVec[0]= x;
// m_fVec[1]= y;
// m_fVec[2]= z;

CVECTOR temp = vec;

float mag = sqrtf(temp.m_fVec[0] * temp.m_fVec[0] + temp.m_fVec[1] * temp.m_fVec[1] + temp.m_fVec[2] * temp.m_fVec[2]);

vec.m_fVec[0] = temp.m_fVec[0] / mag;
vec.m_fVec[1] = temp.m_fVec[1] / mag;
vec.m_fVec[2] = temp.m_fVec[2] / mag;
}

it seems to be working now (the program starts..) ... but then the next question how do i add lighting to it? right now it looks just like a flat surface although there are waves...
It seems like you are doing much more than just calculating normals in your SetNormals() routine. You should keep this routine down to just the job of traversing your heightmap and calculating and setting the normals per vertex, and not doing all of things like defining and initialising the heightmap.

Your problem of your surface being flat might be because you pass a value into your SetNormals routine, define yourheightmap (which, btw, exists only for the life of the routine and gets automatically destroyed when the routine ends), **set all vertices in your heightmap to the value passed in**, and then calculate the same normal value for each vertex (since all are the same height). If you are repeatedly calling this routine from inside the rendering code, then you could be potentially setting the heightmap to one value over and over again.

The normal calcs you are using are fine for a one-time setup of a static terrain. Do the terrain initialisation and normal calculation *before* the render routine (ie. in the InitGL() routine). Also, I wouldn't use this lengthy normal calculations for a water mesh. It's prohibitively expensive. Water needs to have the normals calculated every frame (execution of the render routine essentially). For that you should use something more optimised and/or a shortcut method that approximates the normals. I gave an example of one of those routines in the link I provided earlier. It was something like 10 lines long - compared to the 50+ lines of the static mesh routine.

hth
F451
the temporary heightmap in the routine retrives the values from the "real" heightmap.. i had to do this since the normal calculations uses another "form" of heightmap... soo the heightmap during rendering is still there...

all my waves are precalculated using perlin noise and some of my simple mods in a 3d array WaterHeight[x][z][a]... where i change the a after every rendering... it gives a long initialization but fast rendering...

and about those 10 lines... im clueless of how to use them...

but it looks like this problem wont be solved unless u see all the code which would be to much to post here... thx anyways..

This topic is closed to new replies.

Advertisement