]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/model/BoundingVolumeBuildVisitor.hxx
Merge branch 'timoore/aptsign' into next
[simgear.git] / simgear / scene / model / BoundingVolumeBuildVisitor.hxx
index fd2fb8e7e6785aead8c8aa646ac304f0b9bd3753..9155bcece2920c62405ee3af31fd675afacd1d55 100644 (file)
@@ -23,7 +23,6 @@
 #include <osg/Drawable>
 #include <osg/Geode>
 #include <osg/Group>
-#include <osg/MatrixTransform>
 #include <osg/PagedLOD>
 #include <osg/Transform>
 #include <osg/TriangleFunctor>
@@ -98,70 +97,65 @@ public:
 
         virtual void drawArrays(GLenum mode, GLint first, GLsizei count)
         {
-            if (_vertices.empty() || count==0)
+            if (_vertices.empty() || count <= 0)
                 return;
 
+            GLsizei end = first + count;
             switch(mode) {
             case (GL_TRIANGLES):
-                for (GLsizei i = first; i < first + count; i += 3) {
+                for (GLsizei i = first; i < end - 2; i += 3) {
                     addTriangle(i, i + 1, i + 2);
                 }
                 break;
 
             case (GL_TRIANGLE_STRIP):
-                for (GLsizei i = 0; i < count; i += 3) {
-                    if (i%2)
-                        addTriangle(first + i, first + i + 2, first + i + 1);
-                    else
-                        addTriangle(first + i, first + i + 1, first + i + 2);
+                for (GLsizei i = first; i < end - 2; ++i) {
+                    addTriangle(i, i + 1, i + 2);
                 }
                 break;
 
             case (GL_QUADS):
-                for (GLsizei i = first; i < first + count; i += 4) {
+                for (GLsizei i = first; i < end - 3; i += 4) {
                     addQuad(i, i + 1, i + 2, i + 3);
                 }
                 break;
 
             case (GL_QUAD_STRIP):
-                for (GLsizei i = 0; i < count - 2; i += 2) {
-                    if (i%4)
-                        addQuad(first + i + 1, first + i, i + 3, first + i + 2);
-                    else
-                        addQuad(first + i, first + i + 1, first + i + 2, first + i + 3);
+                for (GLsizei i = first; i < end - 3; i += 2) {
+                    addQuad(i, i + 1, i + 2, i + 3);
                 }
                 break;
 
             case (GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
             case (GL_TRIANGLE_FAN):
-                for (GLsizei i = first + 2; i < first + count; ++i) {
-                    addTriangle(first, i - 1, i);
+                for (GLsizei i = first; i < end - 2; ++i) {
+                    addTriangle(first, i + 1, i + 2);
                 }
                 break;
 
             case (GL_POINTS):
-                for (GLsizei i = 0; i < count; ++i) {
-                    addPoint(first + i);
+                for (GLsizei i = first; i < end; ++i) {
+                    addPoint(i);
                 }
                 break;
 
             case (GL_LINES):
-                for (GLsizei i = first; i < first + count; i += 2) {
+                for (GLsizei i = first; i < end - 1; i += 2) {
                     addLine(i, i + 1);
                 }
                 break;
 
             case (GL_LINE_STRIP):
-                for (GLsizei i = first; i < first + count; ++i) {
+                for (GLsizei i = first; i < end - 1; ++i) {
                     addLine(i, i + 1);
                 }
                 break;
 
             case (GL_LINE_LOOP):
-                for (GLsizei i = first; i < first + count; ++i) {
+                for (GLsizei i = first; i < end - 1; ++i) {
                     addLine(i, i + 1);
                 }
-                addLine(first + count - 1, first);
+                addLine(end - 1, first);
                 break;
 
             default:
@@ -226,44 +220,38 @@ public:
         void drawElementsTemplate(GLenum mode, GLsizei count,
                                   const index_type* indices)
         {
-            if (_vertices.empty() || indices == 0 || count == 0)
+            if (_vertices.empty() || indices == 0 || count <= 0)
                 return;
     
             switch(mode) {
             case (GL_TRIANGLES):
-                for (GLsizei i = 0; i < count; i += 3) {
+                for (GLsizei i = 0; i < count - 2; i += 3) {
                     addTriangle(indices[i], indices[i + 1], indices[i + 2]);
                 }
                 break;
 
             case (GL_TRIANGLE_STRIP):
-                for (GLsizei i = 2; i < count; ++i) {
-                    if (i%2)
-                        addTriangle(indices[i - 2], indices[i], indices[i - 1]);
-                    else
-                        addTriangle(indices[i - 2], indices[i - 1], indices[i]);
+                for (GLsizei i = 0; i < count - 2; ++i) {
+                    addTriangle(indices[i], indices[i + 1], indices[i + 2]);
                 }
                 break;
 
             case (GL_QUADS):
-                for (GLsizei i = 0; i < count; i += 4) {
+                for (GLsizei i = 0; i < count - 3; i += 4) {
                     addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
                 }
                 break;
 
             case (GL_QUAD_STRIP):
-                for (GLsizei i = 3; i < count; i += 2) {
-                    if (i%4)
-                        addQuad(indices[i - 2], indices[i - 3], indices[i], indices[i - 1]);
-                    else
-                        addQuad(indices[i - 3], indices[i - 2], indices[i - 1], indices[i]);
+                for (GLsizei i = 0; i < count - 3; i += 2) {
+                    addQuad(indices[i], indices[i + 1], indices[i + 2], indices[i + 3]);
                 }
                 break;
 
             case (GL_POLYGON):
             case (GL_TRIANGLE_FAN):
-                for (GLsizei i = 2; i < count; ++i) {
-                    addTriangle(indices[0], indices[i - 1], indices[i]);
+                for (GLsizei i = 0; i < count - 2; ++i) {
+                    addTriangle(indices[0], indices[i + 1], indices[i + 2]);
                 }
                 break;
 
@@ -274,19 +262,19 @@ public:
                 break;
 
             case (GL_LINES):
-                for (GLsizei i = 0; i < count; i += 2) {
+                for (GLsizei i = 0; i < count - 1; i += 2) {
                     addLine(indices[i], indices[i + 1]);
                 }
                 break;
 
             case (GL_LINE_STRIP):
-                for (GLsizei i = 0; i < count; ++i) {
+                for (GLsizei i = 0; i < count - 1; ++i) {
                     addLine(indices[i], indices[i + 1]);
                 }
                 break;
 
             case (GL_LINE_LOOP):
-                for (GLsizei i = 0; i < count; ++i) {
+                for (GLsizei i = 0; i < count - 1; ++i) {
                     addLine(indices[i], indices[i + 1]);
                 }
                 addLine(indices[count - 1], indices[0]);
@@ -386,8 +374,9 @@ public:
     //     virtual void end() = 0;
     // };
 
-    BoundingVolumeBuildVisitor() :
-        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
+    BoundingVolumeBuildVisitor(bool dumpIntoLeafs) :
+        osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+        _dumpIntoLeafs(dumpIntoLeafs)
     {
         setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
     }
@@ -395,10 +384,10 @@ public:
     {
     }
 
-    const SGMaterial* pushMaterial(osg::StateSet* stateSet)
+    const SGMaterial* pushMaterial(osg::Geode* geode)
     {
         const SGMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
-        const SGMaterial* material = SGMaterialLib::findMaterial(stateSet);
+        const SGMaterial* material = SGMaterialLib::findMaterial(geode);
         if (material)
             _primitiveFunctor.setCurrentMaterial(material);
         return oldMaterial;
@@ -406,75 +395,101 @@ public:
 
     void fillWith(osg::Drawable* drawable)
     {
-        const SGMaterial* oldMaterial = pushMaterial(drawable->getStateSet());
         drawable->accept(_primitiveFunctor);
-        _primitiveFunctor.setCurrentMaterial(oldMaterial);
     }
 
     virtual void apply(osg::Geode& geode)
     {
-        const SGMaterial* oldMaterial = pushMaterial(geode.getStateSet());
+        if (hasBoundingVolumeTree(geode))
+            return;
 
-        if (!hasBoundingVolumeTree(geode))
+        const SGMaterial* oldMaterial = pushMaterial(&geode);
+
+        bool flushHere = getNodePath().size() <= 1 || _dumpIntoLeafs;
+        if (flushHere) {
+            // push the current active primitive list
+            PFunctor previousPrimitives;
+            _primitiveFunctor.swap(previousPrimitives);
+
+            const SGMaterial* mat = previousPrimitives.getCurrentMaterial();
+            _primitiveFunctor.setCurrentMaterial(mat);
+
+            // walk the children
             for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
                 fillWith(geode.getDrawable(i));
 
-        // Flush the bounding volume tree if we reached the topmost group
-        if (getNodePath().size() <= 1)
+            // Flush the bounding volume tree if we reached the topmost group
             addBoundingVolumeTreeToNode(geode);
+
+            // pop the current active primitive list
+            _primitiveFunctor.swap(previousPrimitives);
+        } else {
+            for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
+                fillWith(geode.getDrawable(i));
+        }
+
         _primitiveFunctor.setCurrentMaterial(oldMaterial);
     }
 
     virtual void apply(osg::Group& group)
-    {
-        // Note that we do not need to push the already collected list of
-        // primitives, since we are now in the topmost node ...
-
-        const SGMaterial* oldMaterial = pushMaterial(group.getStateSet());
+    { traverseAndCollect(group); }
 
-        if (!hasBoundingVolumeTree(group))
-            traverse(group);
+    virtual void apply(osg::Transform& transform)
+    { traverseAndDump(transform); }
 
-        // Flush the bounding volume tree if we reached the topmost group
-        if (getNodePath().size() <= 1)
-            addBoundingVolumeTreeToNode(group);
+    virtual void apply(osg::PagedLOD&)
+    {
+        // Do nothing. In this case we get called by the loading process anyway
+    }
 
-        _primitiveFunctor.setCurrentMaterial(oldMaterial);
+    virtual void apply(osg::Camera& camera)
+    {
+        if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+            return;
+        traverseAndDump(camera);
     }
 
-    virtual void apply(osg::Transform& transform)
+    void traverseAndDump(osg::Node& node)
     {
+        if (hasBoundingVolumeTree(node))
+            return;
+
         // push the current active primitive list
         PFunctor previousPrimitives;
         _primitiveFunctor.swap(previousPrimitives);
 
-        const SGMaterial* oldMaterial = pushMaterial(transform.getStateSet());
+        const SGMaterial* mat = previousPrimitives.getCurrentMaterial();
+        _primitiveFunctor.setCurrentMaterial(mat);
 
         // walk the children
-        if (!hasBoundingVolumeTree(transform))
-            traverse(transform);
+        traverse(node);
 
         // We know whenever we see a transform, we need to flush the
         // collected bounding volume tree since these transforms are not
         // handled by the plain leafs.
-        addBoundingVolumeTreeToNode(transform);
-
-        _primitiveFunctor.setCurrentMaterial(oldMaterial);
+        addBoundingVolumeTreeToNode(node);
 
         // pop the current active primitive list
         _primitiveFunctor.swap(previousPrimitives);
     }
 
-    virtual void apply(osg::PagedLOD&)
+    void traverseAndCollect(osg::Node& node)
     {
-        // Do nothing. In this case we get called by the loading process anyway
-    }
+        // Already been here??
+        if (hasBoundingVolumeTree(node))
+            return;
 
-    virtual void apply(osg::Camera& camera)
-    {
-        if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+        // Force a flush of the bvtree if we are in the topmost node.
+        if (getNodePath().size() <= 1) {
+            traverseAndDump(node);
             return;
-        apply(static_cast<osg::Transform&>(camera));
+        }
+
+        // Note that we do not need to push the already collected list of
+        // primitives, since we are now in the topmost node ...
+
+        // walk the children
+        traverse(node);
     }
 
     void addBoundingVolumeTreeToNode(osg::Node& node)
@@ -504,6 +519,7 @@ public:
 
 private:
     PFunctor _primitiveFunctor;
+    bool _dumpIntoLeafs;
 };
 
 }