Hello Michael,

On 11/15/2011 01:07 PM, Michael Raab wrote:
I've tried both patches. These are the results:

thanks for testing!

      1. osg::calcFaceNormals(geo) is still buggy. Indices size is still
      increasing

in general that can not be avoided. It is possible that a position is part of multiple faces, but for each a different normal must be used. This can only be achieved by having a separate index for the normal (or duplicating positions/other vertex attribs). What the code did not get right (and the patch attempted to fix) is that if there already was a separate index for normals it was not reused, this happens now.

 and result normals are still wrong.

yes, I see that now. The problem is specific to strip/fan primitives where, for the first face of the primitive, the normal was only set on the last vertex. I've fixed that in the attached patch. Please note that for non-planar fans/strips it's not really possible to have face normals, it would require splitting the fan/strip primitive into independent triangles/quads.

 Calling it twice now destroys the geometry :)

hmm, I don't see that here, pushing the button sequence 'a', '7', '3', '3', '3', ... produces only a change after the first '3' afterwards the rendering and log output remain the same. Can you give more details on how the geometry gets destroyed in your case?

      2. osg::calcVertexTangents(geo) seems to work fine now

ok, thanks.

      3. calling calcVertexNormals(geo, angle) first, then
      calcVertexNormal(geo), then calcVertexNormals(geo, angle) again
      and so on also increases the indices size

I suspect this is a similar issue with not reusing the normal index, but instead just inserting a new one.

      to make debugging easier ,please find attached our test
      application./(See attached file: main.cpp)/

great, thank you for sending this!

        Cheers,
                Carsten
Index: Source/System/NodeCores/Drawables/Geometry/OSGGeoFunctions.cpp
===================================================================
RCS file: /cvsroot/opensg/OpenSG/Source/System/NodeCores/Drawables/Geometry/OSGGeoFunctions.cpp,v
retrieving revision 1.75
diff -u -p -r1.75 OSGGeoFunctions.cpp
--- Source/System/NodeCores/Drawables/Geometry/OSGGeoFunctions.cpp	12 Oct 2011 08:57:24 -0000	1.75
+++ Source/System/NodeCores/Drawables/Geometry/OSGGeoFunctions.cpp	16 Nov 2011 00:10:47 -0000
@@ -754,8 +754,8 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcV
 
 OSG_SYSTEMLIB_DLLMAPPING void OSG::calcFaceNormals(GeometryPtr geo)
 {
-    if(geo->getPositions() == NullFC ||
-       geo->getPositions()->size() == 0)
+    if(geo->getPositions()         == NullFC ||
+       geo->getPositions()->size() == 0        )
     {
         FINFO(("Geo without positions in calcFaceNormals()\n"));
         return;
@@ -765,7 +765,6 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
     GeoNormalsPtr newNormals = GeoNormals3f::create();
     Vec3f normal;
 
-    FaceIterator faceIter = geo->beginFaces();
     GeoIndicesPtr oldIndex = geo->getIndices();
 
     if(oldIndex != NullFC)
@@ -774,10 +773,32 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
         if(geo->getMFIndexMapping()->size() > 0)
         {
             //MULTI INDEXED
-            beginEditCP(newIndex);
+            MFUInt16 &oldIndexMap = *geo->editMFIndexMapping();
+            UInt32    oldIMSize   = oldIndexMap.size();
+            UInt32    newIMSize   = oldIndexMap.size();
+            Int16     oldNIdx     =  geo->calcMappingIndex(Geometry::MapNormal);
+            Int16     newNIdx     = -1;
+
+            if(oldNIdx < 0)
+            {
+                // no pre-existing normals, add new index for normals
+                newNIdx   = oldIndexMap.size();
+                newIMSize = oldIMSize + 1;
+            }
+            else if(geo->getIndexMapping(oldNIdx) != Geometry::MapNormal)
+            {
+                // index for normal also indexes other property,
+                // add new index only for normals
+                newNIdx   = oldIndexMap.size();
+                newIMSize = oldIMSize + 1;
+            }
+            else
+            {
+                // normals indexed with unique index, reuse it
+                newNIdx = oldNIdx;
+            }
 
-            MFUInt16    &oldIndexMap = (*geo->editMFIndexMapping());
-            UInt32 oldIMSize = oldIndexMap.size();
+            beginEditCP(newIndex);
             for(UInt32 i = 0; i < oldIndex->getSize() / oldIMSize; ++i)
             {
                 for(UInt32 k = 0; k < oldIMSize; ++k)
@@ -785,13 +806,26 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
                     newIndex->push_back(oldIndex->getValue(i * oldIMSize + k));
                 }
 
-                newIndex->push_back(0);                                 //placeholder for normal index
+                if(newIMSize != oldIMSize)
+                {
+                    // placeholder for new normal
+                    newIndex->push_back(0);
+                }
             }
 
+            Int32        primIdx  = -1;
+            FaceIterator faceIter = geo->beginFaces();
+            FaceIterator faceEnd  = geo->endFaces  ();
+
             beginEditCP(newNormals);
-            for(UInt32 faceCnt = 0; faceIter != geo->endFaces();
-                            ++faceIter, ++faceCnt)
+            for(UInt32 faceCnt = 0; faceIter != faceEnd; ++faceIter, ++faceCnt)
             {
+                // for strip/fan primitives we need to set the normal on all
+                // vertices of the first face, but on subsequent faces only
+                // on the new vertices - see below where this is used
+                bool primStart = (faceIter.PrimitiveIterator::getIndex() > primIdx);
+                primIdx        = faceIter.PrimitiveIterator::getIndex();
+
                 if(faceIter.getLength() == 3)
                 {
                     //Face is a Triangle
@@ -829,23 +863,52 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
                 switch(faceIter.getType())
                 {
                 case GL_TRIANGLE_STRIP:
-                    base = faceIter.getIndexIndex(2);                   //get last point's position in index field
-                    newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
+                    if(primStart)
+                    {
+                        base = faceIter.getIndexIndex(0);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+ 
+                        base = faceIter.getIndexIndex(1);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+                    }
+                    
+                    base = faceIter.getIndexIndex(2);
+                    newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
                     break;
                 case GL_TRIANGLE_FAN:
-                    base = faceIter.getIndexIndex(2);                   //get last point's position in index field
-                    newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
+                    if(primStart)
+                    {
+                        base = faceIter.getIndexIndex(0);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+ 
+                        base = faceIter.getIndexIndex(1);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+                    }
+
+                    base = faceIter.getIndexIndex(2);
+                    newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
                     break;
                 case GL_QUAD_STRIP:
-                    base = faceIter.getIndexIndex(3);                   //get last point's position in index field
-                    newIndex->setValue(faceCnt, base + (base / oldIMSize) + oldIMSize);
+                    if(primStart)
+                    {
+                        base = faceIter.getIndexIndex(0);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+ 
+                        base = faceIter.getIndexIndex(1);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+                    }
+
+                    base = faceIter.getIndexIndex(2);
+                    newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
+
+                    base = faceIter.getIndexIndex(3);
+                    newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
                     break;
                 default:
                     for(UInt32 i = 0; i < faceIter.getLength(); ++i)
                     {
                         base = faceIter.getIndexIndex(i);
-                        newIndex->setValue(faceCnt,
-                                                                   base + (base / oldIMSize) + oldIMSize);
+                        newIndex->setValue(faceCnt, (base / oldIMSize) * newIMSize + newNIdx);
                     }
                     break;
                 }
@@ -855,17 +918,22 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
             endEditCP(newIndex);
 
             beginEditCP(geo);
+            geo->setNormals(newNormals);
+            geo->setIndices(newIndex);
 
-            Int16 ni;
-            ni = geo->calcMappingIndex(Geometry::MapNormal);
-            if(ni != -1)
+            if(oldNIdx < 0)
+            {
+                // no pre-existing normals, add new mapping
+                oldIndexMap.push_back(Geometry::MapNormal);
+            }
+            else if(oldIMSize != newIMSize)
             {
-                oldIndexMap[ni] = oldIndexMap[ni] &~Geometry::MapNormal;
+                // normal index was used to index other property as well,
+                // unshare them
+                oldIndexMap[oldNIdx] &= ~Geometry::MapNormal;
+                oldIndexMap.push_back(Geometry::MapNormal);   
             }
 
-            oldIndexMap.push_back(Geometry::MapNormal);
-            geo->setNormals(newNormals);
-            geo->setIndices(newIndex);
             endEditCP(geo);
             return;
         }
@@ -874,8 +942,20 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
     //SINGLE INDEXED or NON INDEXED
     //UInt32 pointCnt = 0;
     newNormals->resize(geo->getPositions()->getSize());
-    for(; faceIter != geo->endFaces(); ++faceIter)
+
+    Int32        primIdx  = -1;
+    FaceIterator faceIter = geo->beginFaces();
+    FaceIterator faceEnd  = geo->endFaces  ();
+
+    for(; faceIter != faceEnd; ++faceIter)
     {
+        // for strip/fan primitives we need to set the normal on all
+        // vertices of the first face, but on subsequent faces only
+        // on the new vertices - see below where this is used
+        bool primStart = (faceIter.PrimitiveIterator::getIndex() > primIdx);
+        primIdx        = faceIter.PrimitiveIterator::getIndex();
+
+
         if(faceIter.getLength() == 3)
         {
             //Face is a Triangle
@@ -902,12 +982,31 @@ OSG_SYSTEMLIB_DLLMAPPING void OSG::calcF
         switch(faceIter.getType())
         {
         case GL_TRIANGLE_STRIP:
+            if(primStart)
+            {
+                newNormals->setValue(normal, faceIter.getPositionIndex(0));
+                newNormals->setValue(normal, faceIter.getPositionIndex(1));
+            }
+
             newNormals->setValue(normal, faceIter.getPositionIndex(2));
             break;
         case GL_TRIANGLE_FAN:
+            if(primStart)
+            {
+                newNormals->setValue(normal, faceIter.getPositionIndex(0));
+                newNormals->setValue(normal, faceIter.getPositionIndex(1));
+            }
+
             newNormals->setValue(normal, faceIter.getPositionIndex(2));
             break;
         case GL_QUAD_STRIP:
+            if(primStart)
+            {
+                newNormals->setValue(normal, faceIter.getPositionIndex(0));
+                newNormals->setValue(normal, faceIter.getPositionIndex(1));
+            }
+
+            newNormals->setValue(normal, faceIter.getPositionIndex(2));
             newNormals->setValue(normal, faceIter.getPositionIndex(3));
             break;
         default:
------------------------------------------------------------------------------
RSA(R) Conference 2012
Save $700 by Nov 18
Register now
http://p.sf.net/sfu/rsa-sfdev2dev1
_______________________________________________
Opensg-users mailing list
Opensg-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensg-users

Reply via email to