Jump to content
  • Advertisement
Sign in to follow this  
cozzie

Vertex normals calculation, any good?

This topic is 5125 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

Hi all. After getting very usefull reaction on other threads, I'm wondering if I did will creating a new "Vertexnormal calculation"-function. What do you think?
void GLobject::CalcNormals()
{
	int c, c2;

	for(c=0;c<nr_vertices;c++)
	{
		normals[c].x = 0.0f;
		normals[c].y = 0.0f;
		normals[c].z = 0.0f;
	}
	for(c=0;c<nr_faces;c++)
	{
		facenormals[c] = GetFaceNormal(vertices[faces[c].v1],
				   				       vertices[faces[c].v2],
								       vertices[faces[c].v3]);
	}

	for(c=0;c<nr_vertices;c++)
	{
		for(c2=0;c2<nr_faces;c2++)
		{
			if(faces[c2].v1 == (unsigned int)c)
			{
				normals[faces[c2].v1].x += facenormals[c2].x;
				normals[faces[c2].v1].y += facenormals[c2].y;
				normals[faces[c2].v1].z += facenormals[c2].z;
			}
			if(faces[c2].v2 == (unsigned int)c)
			{
				normals[faces[c2].v2].x += facenormals[c2].x;
				normals[faces[c2].v2].y += facenormals[c2].y;
				normals[faces[c2].v2].z += facenormals[c2].z;
			}
			if(faces[c2].v3 == (unsigned int)c)
			{
				normals[faces[c2].v3].x += facenormals[c2].x;
				normals[faces[c2].v3].y += facenormals[c2].y;
				normals[faces[c2].v3].z += facenormals[c2].z;
			}
		}
	}

	for(c=0;c<nr_vertices;c++)
	{
		normals[c] = Normalize(normals[c]);
	}
}

Share this post


Link to post
Share on other sites
Advertisement
If you're just averaging the normals from the faces it's not always gonna look good. For example if you have a cube with only 1 normal per-vertex, it's gonna look quite funky.

You should average the normals unless the angle between them
is too great.

Share this post


Link to post
Share on other sites
Well your function is quite inefficient. For one thing you shouldn't use a loop to fill an array with initial values. Use a memory setting function like memset. Also the copy of your face normals is not necessary. It's just "spinning your CPU's wheels" for no good reason. Instead, do something like this:


void MakeVertexNormals( void )
{
int shared = 0;
vector_t sum = { 0, 0, 0 };
const vector_t zero = { 0, 0, 0 };

for( int i = 0; i < num_verts; ++i )
{
for( int j = 0; j < num_faces; ++j )
{
if( model->faces[j].vertexIndex[0] == i ||
model->faces[j].vertexIndex[1] == i ||
model->faces[j].vertexIndex[2] == i )
{
sum = VectorAdd( sum, &GetFaceNormal( j ) );
++shared;
}
}

// divide sum by shared and normalize
model->normals = Norm( VectorDivide( sum, shared ) );
sum = zero;
shared = 0;
}
}






-SirKnight

Share this post


Link to post
Share on other sites
Thanks for the explanation sir knight.
It sounds logic that I don't need an array for all facenormals, because I don't use them anywhere else in the engine (yet).

Thanks.
I've changed the function to this, according to your exaplanation:

void GLobject::CalcNormals()
{
int c, c2, shared = 0;
Vertex facenormal = SetVector(0, 0, 0);
Vertex sum = SetVector(0, 0, 0);

for(c=0;c<nr_vertices;c++)
{
for(c2=0;c2<nr_faces;c2++)
{
if(faces[c2].v1 == (unsigned int)c ||
faces[c2].v2 == (unsigned int)c ||
faces[c2].v3 == (unsigned int)c)
{
facenormal = GetFaceNormal(vertices[faces[c2].v1],
vertices[faces[c2].v2],
vertices[faces[c2].v3]);
shared++;
sum = AddVector(sum, facenormal);
}
}
sum = DivideVector(sum, (float)shared);

normals[c] = Overtake(sum);
Normalize(normals[c]);

sum = SetVector(0, 0, 0);
shared = 0;
}
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Also you're for each vertex looping over all the faces. You should loop twice over all the vertices, and once over all the faces, like this:

int c;

for (c=0;c normals[c]=Vector(0,0,0);
}

for (c=0;c Vector normal=GetFaceNormal(c);

normals[faces[c].v1]+=normal;
normals[faces[c].v2]+=normal;
normals[faces[c].v3]+=normal;
}

for (c=0;c normals[c].normalize();
}

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Ooops, that message didn't come out right. First loop is over all vertices, second over all faces, and third over all vertices again (just to normalize them).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!