Calculate normals for a polygon - faces problem

Started by
14 comments, last by polar01 14 years, 6 months ago
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();
                Normals.Add(sum[index]);
            }
        }


--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net
Advertisement
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.
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 :-(

--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net
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?
The Trouble With Robots - www.digitalchestnut.com/trouble
Thanks,

This one is composed of triangles only :
http://picasaweb.google.com/viewon01/OpenGL#5380203925050881714

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]);            }        }
--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net
It looks like maybe the normals are correct, but are being applied to the wrong vertices on each triangle.
The Trouble With Robots - www.digitalchestnut.com/trouble
Ohh,

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

How can I check that ?

Thanks
--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net
Could you post the code where the models are displayed?
The Trouble With Robots - www.digitalchestnut.com/trouble
Of course,

You can even download the complete source code at :
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
--------------------------------------------------------------------------------Aurora Studio - PureLight - Animation & rendering software and API.http://www.polarlights.net
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?
The Trouble With Robots - www.digitalchestnut.com/trouble

This topic is closed to new replies.

Advertisement