## Recommended Posts

Hi. At the moment I use glEnableClientState for using normals in my vertex arrays, which means I'm using normals per vertex. I calculate them this way: vtxnormal.x = 0; vtxnormal.y = 0; vtxnormal.z = 0; then I calculate the facenormal and add it to the vtx normals: vtxnormal.x += facenormal.x; vtxnormal.y += facenormal.y; vtxnormal.z += facenormal.z; Now I'm wondering if this is the best way, so that my lighting turns out good. What would you advise, keep on going like this? Or should I use just facenormals, if so, how should I do that? Thanks. I studied the most vector theory today, I'm glad this is all clear to me know. It's sometimes good to stop adding feautures to your 3d engine and take a look at what you did till now, with this I mean a really good look (math etc.) [Edited by - cozzie on November 27, 2004 11:29:36 AM]

##### Share on other sites
Vertex normals including a way to calculate them from face normals.

##### Share on other sites
I do it the way you proposed; just adding all adjacent face normals to the current vertex. Just make sure you normalize at the end!

##### Share on other sites
To calculate the vetex normals, just find out all the faces that vertex belongs to, add all the X, Y and Z values of each face, then divide by he number of faces. In some cases vertex normals look better, but in other cases face normals look better.
For example, if you have a box, and the top plane is divided in many faces, then by using vertex normals the top plane will have different lighting, rather than uniform lighting. So the vertex normals work best for 'natural' objects such as stones, trees, etc. but suck for man made objects, such as houses, tables, etc.

##### Share on other sites
Quote:
 Original post by RaduprvTo calculate the vetex normals, just find out all the faces that vertex belongs to, add all the X, Y and Z values of each face, then divide by he number of faces.

If you just normalize at the end, you don't have to keep track of the number of faces. On the other hand, normalizing deals with a slow square root function that you might like to avoid.

##### Share on other sites
Quote:
 Original post by OpenGLAaronIf you just normalize at the end, you don't have to keep track of the number of faces. On the other hand, normalizing deals with a slow square root function that you might like to avoid.

Yeah, that's the idea. 3 divisions (plus some incrementation) is much faster than normalizing.

##### Share on other sites
Thanks for all the reactions guys.

I was wondering:

"To calculate the vertex normals, just find out all the faces that vertex belongs to, add all the X, Y and Z values of each face, then divide by he number of faces."

Example:
vertex3 = is used in face 3,5 and 6
facenormal face3 = 4,2,1
facenormal face5 = 2,3,2
facenormal face6 = 1,4,2

Vertex3 normal = (4+2+1)/3, 2+3+4(/3), (1+2+2)/3
Vertex3 normal = 2.33, 3, 1,67

Is this the correct way your explaining? Doesn't this take long to calculate?

I'm also wondering if there's a way to use face normals instead of vertex normals, when using vertex arrays. I think glEnableClientState(normal stuff) can only be used for vertex normals, or can it also take face normals?

Thanks again.

##### Share on other sites
cozzie - As you loop through all your vertices, for each face that it is a vertex of, add the current face normal to it and keep track of the number of faces with a counter. After you've looped through all the faces that it's a vertex of, then you divide by the counter. Unless you know beforehand how many faces there will be, as in your example, then that would be faster. Either way, it's less expensive than a square root in a normalization. (I just use the normalization because I like to think I'm clever)

To use face normals, you have to specify a given vertex the same number of times as the number of faces it is a part of. So, if a vertex is part of 3 faces, you need to explicitly set it's normal and vertex in openGL 3 times. That's because openGL only knows about normals as per-vertex attributes. At least, this is as far as I know.

##### Share on other sites
Okay, sounds clear.
You say that checking in which faces a vertex is used is quicker because then you don't need normalization. Is this true?

I would think that in your situation I have to do this:

- calculate facenormal
- per vertex: add facenormals together for all faces in which the vertex is used and divide by the number of faces
- normalize the resulting vertex normal

Or is it not necessary to normalize the resulting vertex normal?

It sounds like using facenormals during my rendering will be quite a bit slower per frame then using the vertex normals, which OpenGL supports without tricks.
Is there anyone who has experience with this?

##### Share on other sites
Quote:
 Or is it not necessary to normalize the resulting vertex normal?

It's better to normalize, as there are less innaccuracies that way. Proof:
Take 2 perpendicular vectors (1,0,0) and (0,1,0), As you can see, they're both unit vectors. Now, add those 2 together and divide by 2 and the length of the result is nowhere even near 1.(it is 1.414) Granted, it's an extreme case, but this inaccuracy can seriously screw up lighting. But unless you have GL_NORMALIZE enabled (in which case you don't even need to divide), you're going to have to normalize yourself, unless your normals are static in which case you normalize BEFORE execution of your main loop.

Yah, go for vertex normals. They're a general solution and you can always force a vertex with the same position but different normals into 2 different vertices in your vertex arrays. I'm not sure if this is obvious, but again, do that in your tool chain and not at run-time. :)

##### Share on other sites
;-)

Thanks for the explanation.
I'm gonna stay with the vertex normals, with normalization for the vertex normals.
I'm not using glNormalize, just doing it myself.

The speed improvement isn't that necessary since calculating my normals is only done once, when initializing.

Thanks again.
greets from holland

##### Share on other sites
A good way to calculate vertex normals, when u have some flat surfaces , is to set a threshold to check when add 2 normals...for example,

if DOT (normal_1, normal_2) > threshold

so u can get some parts flat and others smooth...see ya

##### Share on other sites
I don't exactly now what you mean, can you maybe give an example?

As I read your explanation it looks like that way you calculate vertexnormals in 2 different ways, one special way for calculating them for larger surfaces with flat-to-each-other-connected-faces ;-) Is this what you mean?

##### Share on other sites
I've changed my CalcNormals function (per object),
it seems to be working fine.

Although without the last Normalization the effect looks better, is this explainable?

Here's the source:

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 on other sites
No clue why it would look better without normalization... your algorithm looks spot on. Maybe there is something wierd in your Normalize function?

##### Share on other sites
this doesnt look right

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 += acenormals[c2].x;
etc

for each vertice u want a anverage normal right?, thus u loop through all the verts seeing if this vertice is a part of one of the faces, if it is, then the faces normal is added to the vertices corresponding normal, thus it should be

if(faces[c2].v1 == (unsigned int)c)
{
normals[c].x +=

##### Share on other sites
I saw that too Zedzeek, but it will lead to exactly the same results as what his current code does anyway.

if(faces[c2].v1 == (unsigned int)c)

In this case, c is equal to faces[c2].v1, so his expression remains valid.

##### Share on other sites
OK.. why nobody posted this? Your wersion runs in O(nr_vertices*nr_faces) while it can be done in O(nr_vertices+nr_faces) ...read: much faster.

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

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628401
• Total Posts
2982463

• 9
• 10
• 9
• 19
• 24