# OpenGL Calculate normals for a polygon - faces problem

This topic is 3341 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi, I'm trying to calculate the normals for a set of polygons... but I got a problem. I calculate the normals and when I display theses normals they sounds correct :-( You can see this on the first picture here : http://picasaweb.google.com/viewon01/OpenGL#5391730635084390018 I don't know why my model sounds so "faceted" and that sometimes I got a face that looks strange !! Take a look at : http://picasaweb.google.com/viewon01/OpenGL#5391730633418058914 or http://picasaweb.google.com/viewon01/OpenGL#5380203925050881714 Can you help me please ? You can find my application at http://rs.codeplex.com or ... here is the source code for the normals calculation :
        override public void CalculateNormals()
{
base.CalculateNormals();

if (Indices.Count == 0)
return;

Normals.Clear();

Vector3[] sum = new Vector3[Vertices.Count];
Vector3 surfaceNormal;
Vector3 e1;
Vector3 e2;

int posInIndices = 0;
for (int index = 0; index < VerticesPerPolygon.Count; index++)
{
int verticesCount = VerticesPerPolygon[index];
for (int index0 = 0; index0 < verticesCount; index0++)
{
Vector3 vertex = Vector3.Invalid.Clone();
Vector3 previousVertex = Vector3.Invalid.Clone();
Vector3 nextVertex = Vector3.Invalid.Clone();

int indice = Indices[posInIndices];
vertex = Vertices[indice];

if (index0 == 0)
{
int previousIndice = Indices[posInIndices + verticesCount - 1];
previousVertex = Vertices[previousIndice];

int nextIndice = Indices[posInIndices + 1];
nextVertex = Vertices[nextIndice];
}
else if (index0 > 0 && index0 < verticesCount - 1)
{
int previousIndice = Indices[posInIndices - 1];
previousVertex = Vertices[previousIndice];

int nextIndice = Indices[posInIndices + 1];
nextVertex = Vertices[nextIndice];
}
else if (index0 == verticesCount - 1)
{
int previousIndice = Indices[posInIndices - 1];
previousVertex = Vertices[previousIndice];

int nextIndice = Indices[posInIndices - verticesCount + 1];
nextVertex = Vertices[nextIndice];
}

//---- Calculate the surface normal
e1 = previousVertex - vertex;
e2 = vertex - nextVertex;

surfaceNormal = e1.Cross(e2);
surfaceNormal.Normalize();

// Sum it at the vertex index
sum[indice] += surfaceNormal;

//---- next
posInIndices++;
}
}

for (int index = 0; index < Vertices.Count; index++)
{
sum[index].Normalize();
}
}



##### Share on other sites
Avoid crossposting. It's only been 15 hours since your last post.

A guess is that perhaps your polygons have bad vertices in them or something. Make sure not to use 3 vertices in a straight line, or 2 vertices with the exact same coordinates, when calculating the normal.

##### Share on other sites
Okay, I will...

I have this problem with other models...

Also, I have load theses models with 2 other applications and they sounds correct, but not in my version :-(

##### Share on other sites
I'm not 100% sure about what you're doing for non-triangular polygons. Could you try rendering a model that only has triangular faces?

Also, if the problem persists could you post a close up screenshot?

##### Share on other sites
Thanks,

This one is composed of triangles only :

I don't know what is happening, even not sure it is due to the normals !
I have try to play with back-face culling too... but I got no result too :-(

Here is the code for the triangles (based on same concept):

        override public void CalculateNormals()        {            base.CalculateNormals();            if (Indices.Count == 0)                return;            Normals.Clear();            //----            Vector3[] sum = new Vector3[Vertices.Count];            for (int jj = 0; jj < Indices.Count / 3; jj++)            {                int indice1 = Indices[jj * 3];                int indice2 = Indices[jj * 3 + 1];                int indice3 = Indices[jj * 3 + 2];                Vector3 v1 = Vertices[indice1];                Vector3 v2 = Vertices[indice2];                Vector3 v3 = Vertices[indice3];                // Calculate the surface normal                Vector3 e1 = Vertices[indice1] - Vertices[indice2];                Vector3 e2 = Vertices[indice2] - Vertices[indice3];                Vector3 surfaceNormal = e1.Cross(e2);                surfaceNormal.Normalize();                // Sum it at the vertex index                sum[indice1] += surfaceNormal;                sum[indice2] += surfaceNormal;                sum[indice3] += surfaceNormal;            }            for (int index = 0; index < Vertices.Count; index++)            {                sum[index].Normalize();                Normals.Add(sum[index]);            }        }

##### Share on other sites
It looks like maybe the normals are correct, but are being applied to the wrong vertices on each triangle.

##### Share on other sites
Ohh,

To the wrong vertice ... how do you see this ?

How can I check that ?

Thanks

##### Share on other sites
Could you post the code where the models are displayed?

##### Share on other sites
Of course,

http://rs.codeplex.com

Here is the OpenGL code to display the polygon (class OGLRenderer.cs):
        private void RenderPolygonGeometry(PolygonGeometry polygon)        {            int indiceIndex = 0;            for (int index0 = 0; index0 < polygon.VerticesPerPolygon.Count; index0++)            {                int count = polygon.VerticesPerPolygon[index0];                Gl.glBegin(Gl.GL_POLYGON);                for (int index = 0; index < count; index++)                {                    int indice = polygon.Indices[indiceIndex];                    Vector3 vertex = polygon.Vertices[indice];                    Vector3 normal = polygon.Normals[indice];                    Gl.glVertex3d(vertex.x, vertex.y, vertex.z);                    Gl.glNormal3d(normal.x, normal.y, normal.z);                    indiceIndex++;                }                Gl.glEnd();            }        }

Here is the code that calculate the normals of the polygon (class PolygonGeometry.cs)
        override public void UpdateNormals()        {            base.UpdateNormals();            if (Indices.Count == 0 ||                Normals.Count > 0) // Already calculated                return;            Normals.Clear();            Vector3[] sum = new Vector3[Vertices.Count];            int posInIndices = 0;            for (int index = 0; index < VerticesPerPolygon.Count; index++)            {                int verticesCount = VerticesPerPolygon[index];                for (int index0 = 0; index0 < verticesCount; index0++)                {                    Vector3 vertex = Vector3.Invalid.Clone();                    Vector3 previousVertex = Vector3.Invalid.Clone();                    Vector3 nextVertex = Vector3.Invalid.Clone();                    int indice = Indices[posInIndices];                    vertex = Vertices[indice];                    if (index0 == 0)                    {                        int previousIndice = Indices[posInIndices + verticesCount - 1];                        previousVertex = Vertices[previousIndice];                        int nextIndice = Indices[posInIndices + 1];                        nextVertex = Vertices[nextIndice];                    }                    else if (index0 > 0 && index0 < verticesCount - 1)                    {                        int previousIndice = Indices[posInIndices - 1];                        previousVertex = Vertices[previousIndice];                        int nextIndice = Indices[posInIndices + 1];                        nextVertex = Vertices[nextIndice];                    }                    else if (index0 == verticesCount - 1)                    {                        int previousIndice = Indices[posInIndices - 1];                        previousVertex = Vertices[previousIndice];                        int nextIndice = Indices[posInIndices - verticesCount + 1];                        nextVertex = Vertices[nextIndice];                    }                    //---- Calculate the surface normal                    Vector3 surfaceNormal = CalculateNormal(previousVertex, vertex, nextVertex);                    // Sum it at the vertex index                    if (!surfaceNormal.IsInvalid)                    {                        sum[indice] += surfaceNormal;                    }                    //---- next                    posInIndices++;                }            }            for (int index = 0; index < Vertices.Count; index++)            {                sum[index].Normalize();                Normals.Add(sum[index]);            }        }

Thanks

##### Share on other sites
I can't see anything wrong with your code. I think the way forward is to check your assumptions and try to narrow down the problem. A few ideas:

1. make sure it really is the normals that cause the 'faceted' appearence. To do this, I'd try rendering with all the normals set to (1, 0, 0), or something like that, which ought to appear evenly lit.

2. try turning off lighting and textures, and instead colouring the vertices according to some function of 'indice', for example ((indice % 2) * 255, ((indice / 2) % 2) * 255, ((indice / 4) % 2) * 255). We should be able to see if the vertices are being shared correctly.

Does anybody have any other suggestions?

1. 1
2. 2
3. 3
Rutin
23
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 10
• ### Forum Statistics

• Total Topics
633651
• Total Posts
3013134
×