]> git.mxchange.org Git - simgear.git/commitdiff
scene: Factor out a common primitive functor.
authorMathias Froehlich <Mathias.Froehlich@web.de>
Tue, 25 Sep 2012 21:42:14 +0000 (23:42 +0200)
committerMathias Froehlich <Mathias.Froehlich@web.de>
Thu, 27 Sep 2012 16:21:13 +0000 (18:21 +0200)
This kind of work is done two times for different
flavours of bounding volume generation. Factor
out and use this in BVHPageNodeOSG.cxx and
BoundingVolumeBuildVisitor.hxx.

simgear/scene/model/BVHPageNodeOSG.cxx
simgear/scene/model/BoundingVolumeBuildVisitor.hxx
simgear/scene/model/CMakeLists.txt
simgear/scene/model/PrimitiveCollector.cxx [new file with mode: 0644]
simgear/scene/model/PrimitiveCollector.hxx [new file with mode: 0644]

index 412fedd57264ee2691762e3e8780b64f1e61be3b..2a288ac08ecfd4a36edfe32eb2c1c953b3dab9ed 100644 (file)
@@ -31,7 +31,6 @@
 #include <osg/PagedLOD>
 #include <osg/ProxyNode>
 #include <osg/Transform>
-#include <osg/TriangleFunctor>
 #include <osgDB/ReadFile>
 
 #include <simgear/scene/material/mat.hxx>
 
 #include <simgear/bvh/BVHStaticGeometryBuilder.hxx>
 
+#include "PrimitiveCollector.hxx"
+
 namespace simgear {
 
 class BVHPageNodeOSG::_NodeVisitor : public osg::NodeVisitor {
 public:
-    class PFunctor : public osg::PrimitiveFunctor {
+    class _PrimitiveCollector : public PrimitiveCollector {
     public:
-        PFunctor() :
-            _modeCache(0)
-        {
-            _geometryBuilder = new BVHStaticGeometryBuilder;
-        }
-        virtual ~PFunctor()
+        _PrimitiveCollector() :
+            _geometryBuilder(new BVHStaticGeometryBuilder)
+        { }
+        virtual ~_PrimitiveCollector()
         { }
 
-        virtual void setVertexArray(unsigned int count, const osg::Vec2* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec3* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec4* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
-                                       vertices[i][1]/vertices[i][3],
-                                       vertices[i][2]/vertices[i][3]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec2d* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec3d* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec4d* vertices) 
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
-                                       vertices[i][1]/vertices[i][3],
-                                       vertices[i][2]/vertices[i][3]);
-        }
-
-        virtual void drawArrays(GLenum mode, GLint first, GLsizei count)
-        {
-            if (_vertices.empty() || count <= 0)
-                return;
-
-            GLsizei end = first + count;
-            switch(mode) {
-            case (GL_TRIANGLES):
-                for (GLsizei i = first; i < end - 2; i += 3) {
-                    addTriangle(i, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_TRIANGLE_STRIP):
-                for (GLsizei i = first; i < end - 2; ++i) {
-                    addTriangle(i, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_QUADS):
-                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 = 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; i < end - 2; ++i) {
-                    addTriangle(first, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_POINTS):
-                for (GLsizei i = first; i < end; ++i) {
-                    addPoint(i);
-                }
-                break;
-
-            case (GL_LINES):
-                for (GLsizei i = first; i < end - 1; i += 2) {
-                    addLine(i, i + 1);
-                }
-                break;
-
-            case (GL_LINE_STRIP):
-                for (GLsizei i = first; i < end - 1; ++i) {
-                    addLine(i, i + 1);
-                }
-                break;
-
-            case (GL_LINE_LOOP):
-                for (GLsizei i = first; i < end - 1; ++i) {
-                    addLine(i, i + 1);
-                }
-                addLine(end - 1, first);
-                break;
-
-            default:
-                break;
-            }
-        }
-  
-        virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void drawElements(GLenum mode, GLsizei count, const GLushort* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void drawElements(GLenum mode, GLsizei count, const GLuint* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void begin(GLenum mode)
-        {
-            _modeCache = mode;
-            _vertices.resize(0);
-        }
-
-        virtual void vertex(const osg::Vec2& v)
-        {
-            _vertices.push_back(SGVec3f(v[0], v[1], 0));
-        }
-        virtual void vertex(const osg::Vec3& v)
-        {
-            _vertices.push_back(SGVec3f(v[0], v[1], v[2]));
-        }
-        virtual void vertex(const osg::Vec4& v)
-        {
-            _vertices.push_back(SGVec3f(v[0]/v[3], v[1]/v[3], v[2]/v[3]));
-        }
-        virtual void vertex(float x, float y)
-        {
-            _vertices.push_back(SGVec3f(x, y, 0));
-        }
-        virtual void vertex(float x, float y, float z)
-        {
-            _vertices.push_back(SGVec3f(x, y, z));
-        }
-        virtual void vertex(float x, float y, float z, float w)
-        {
-            _vertices.push_back(SGVec3f(x/w, y/w, z/w));
-        }
-        virtual void end()
-        {
-            if (_vertices.empty())
-                return;
-
-            drawArrays(_modeCache, 0, _vertices.size());
-        }
-
-        template<typename index_type>
-        void drawElementsTemplate(GLenum mode, GLsizei count,
-                                  const index_type* indices)
-        {
-            if (_vertices.empty() || indices == 0 || count <= 0)
-                return;
-    
-            switch(mode) {
-            case (GL_TRIANGLES):
-                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 = 0; i < count - 2; ++i) {
-                    addTriangle(indices[i], indices[i + 1], indices[i + 2]);
-                }
-                break;
-
-            case (GL_QUADS):
-                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 = 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 = 0; i < count - 2; ++i) {
-                    addTriangle(indices[0], indices[i + 1], indices[i + 2]);
-                }
-                break;
-
-            case (GL_POINTS):
-                for(GLsizei i = 0; i < count; ++i) {
-                    addPoint(indices[i]);
-                }
-                break;
-
-            case (GL_LINES):
-                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 - 1; ++i) {
-                    addLine(indices[i], indices[i + 1]);
-                }
-                break;
-
-            case (GL_LINE_LOOP):
-                for (GLsizei i = 0; i < count - 1; ++i) {
-                    addLine(indices[i], indices[i + 1]);
-                }
-                addLine(indices[count - 1], indices[0]);
-                break;
-
-            default:
-                break;
-            }
-        }    
-
-        void addPoint(unsigned i1)
-        {
-            addPoint(_vertices[i1]);
-        }
-        void addLine(unsigned i1, unsigned i2)
-        {
-            addLine(_vertices[i1], _vertices[i2]);
-        }
-        void addTriangle(unsigned i1, unsigned i2, unsigned i3)
-        {
-            addTriangle(_vertices[i1], _vertices[i2], _vertices[i3]);
-        }
-        void addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4)
-        {
-            addQuad(_vertices[i1], _vertices[i2], _vertices[i3], _vertices[i4]);
-        }
-
-        void addPoint(const SGVec3f& v1)
-        {
-        }
-        void addLine(const SGVec3f& v1, const SGVec3f& v2)
-        {
-        }
-        void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
-        {
-            _geometryBuilder->addTriangle(v1, v2, v3);
-        }
-        void addQuad(const SGVec3f& v1, const SGVec3f& v2,
-                     const SGVec3f& v3, const SGVec3f& v4)
+        virtual void addPoint(const osg::Vec3d& v1)
+        { }
+        virtual void addLine(const osg::Vec3d& v1, const osg::Vec3d& v2)
+        { }
+        virtual void addTriangle(const osg::Vec3d& v1, const osg::Vec3d& v2, const osg::Vec3d& v3)
         {
-            _geometryBuilder->addTriangle(v1, v2, v3);
-            _geometryBuilder->addTriangle(v1, v3, v4);
+            _geometryBuilder->addTriangle(toVec3f(toSG(v1)), toVec3f(toSG(v2)), toVec3f(toSG(v3)));
         }
 
         BVHNode* buildTreeAndClear()
         {
             BVHNode* bvNode = _geometryBuilder->buildTree();
             _geometryBuilder = new BVHStaticGeometryBuilder;
-            _vertices.clear();
             return bvNode;
         }
 
-        void swap(PFunctor& primitiveFunctor)
+        void swap(_PrimitiveCollector& primitiveCollector)
         {
-            _vertices.swap(primitiveFunctor._vertices);
-            std::swap(_modeCache, primitiveFunctor._modeCache);
-            std::swap(_geometryBuilder, primitiveFunctor._geometryBuilder);
+            PrimitiveCollector::swap(primitiveCollector);
+            std::swap(_geometryBuilder, primitiveCollector._geometryBuilder);
         }
 
         void setCurrentMaterial(const BVHMaterial* material)
@@ -351,9 +87,6 @@ public:
             return _geometryBuilder->getCurrentMaterial();
         }
 
-        std::vector<SGVec3f> _vertices;
-        GLenum _modeCache;
-
         SGSharedPtr<BVHStaticGeometryBuilder> _geometryBuilder;
     };
 
@@ -368,10 +101,10 @@ public:
 
     const BVHMaterial* pushMaterial(osg::Geode* geode)
     {
-        const BVHMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
+        const BVHMaterial* oldMaterial = _primitiveCollector.getCurrentMaterial();
         const BVHMaterial* material = SGMaterialLib::findMaterial(geode);
         if (material)
-            _primitiveFunctor.setCurrentMaterial(material);
+            _primitiveCollector.setCurrentMaterial(material);
         return oldMaterial;
     }
 
@@ -380,9 +113,9 @@ public:
         const BVHMaterial* oldMaterial = pushMaterial(&geode);
 
         for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
-            geode.getDrawable(i)->accept(_primitiveFunctor);
+            geode.getDrawable(i)->accept(_primitiveCollector);
 
-        _primitiveFunctor.setCurrentMaterial(oldMaterial);
+        _primitiveCollector.setCurrentMaterial(oldMaterial);
     }
 
     virtual void apply(osg::Group& group)
@@ -390,11 +123,11 @@ public:
         // FIXME optimize this to collapse more leafs
 
         // push the current active primitive list
-        PFunctor previousPrimitives;
-        _primitiveFunctor.swap(previousPrimitives);
+        _PrimitiveCollector previousPrimitives;
+        _primitiveCollector.swap(previousPrimitives);
 
         const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
-        _primitiveFunctor.setCurrentMaterial(mat);
+        _primitiveCollector.setCurrentMaterial(mat);
 
         NodeVector nodeVector;
         _nodeVector.swap(nodeVector);
@@ -422,7 +155,7 @@ public:
         }
 
         // pop the current active primitive list
-        _primitiveFunctor.swap(previousPrimitives);
+        _primitiveCollector.swap(previousPrimitives);
     }
 
     virtual void apply(osg::Transform& transform)
@@ -435,11 +168,11 @@ public:
             return;
 
         // push the current active primitive list
-        PFunctor previousPrimitives;
-        _primitiveFunctor.swap(previousPrimitives);
+        _PrimitiveCollector previousPrimitives;
+        _primitiveCollector.swap(previousPrimitives);
 
         const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
-        _primitiveFunctor.setCurrentMaterial(mat);
+        _primitiveCollector.setCurrentMaterial(mat);
 
         NodeVector nodeVector;
         _nodeVector.swap(nodeVector);
@@ -455,7 +188,7 @@ public:
         _nodeVector.swap(nodeVector);
 
         // pop the current active primitive list
-        _primitiveFunctor.swap(previousPrimitives);
+        _primitiveCollector.swap(previousPrimitives);
 
         if (!nodeVector.empty()) {
             SGSharedPtr<BVHTransform> bvhTransform = new BVHTransform;
@@ -479,7 +212,7 @@ public:
     void addBoundingVolumeTreeToNode()
     {
         // Build the flat tree.
-        BVHNode* bvNode = _primitiveFunctor.buildTreeAndClear();
+        BVHNode* bvNode = _primitiveCollector.buildTreeAndClear();
 
         // Nothing in there?
         if (!bvNode)
@@ -553,7 +286,7 @@ public:
     }
 
 private:
-    PFunctor _primitiveFunctor;
+    _PrimitiveCollector _primitiveCollector;
     typedef std::vector<SGSharedPtr<BVHNode> > NodeVector;
     NodeVector _nodeVector;
 };
index 5be621bf06b4dbd7ff689d2eb77f194456fb917d..d927191785158f19545426bc7c1c57a2aeafb09d 100644 (file)
 
 #include <simgear/scene/material/mat.hxx>
 #include <simgear/scene/material/matlib.hxx>
+#include <simgear/scene/util/OsgMath.hxx>
 #include <simgear/scene/util/SGNodeMasks.hxx>
 #include <simgear/scene/util/SGSceneUserData.hxx>
 #include <simgear/math/SGGeometry.hxx>
 
 #include <simgear/bvh/BVHStaticGeometryBuilder.hxx>
 
+#include "PrimitiveCollector.hxx"
+
 namespace simgear {
 
 class BoundingVolumeBuildVisitor : public osg::NodeVisitor {
 public:
-    class PFunctor : public osg::PrimitiveFunctor {
+    class _PrimitiveCollector : public PrimitiveCollector {
     public:
-        PFunctor() :
-            _modeCache(0)
-        {
-            _geometryBuilder = new BVHStaticGeometryBuilder;
-        }
-        virtual ~PFunctor()
+        _PrimitiveCollector() :
+            _geometryBuilder(new BVHStaticGeometryBuilder)
+        { }
+        virtual ~_PrimitiveCollector()
         { }
 
-        virtual void setVertexArray(unsigned int count, const osg::Vec2* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec3* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec4* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
-                                       vertices[i][1]/vertices[i][3],
-                                       vertices[i][2]/vertices[i][3]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec2d* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], 0);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec3d* vertices)
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0], vertices[i][1], vertices[i][2]);
-        }
-
-        virtual void setVertexArray(unsigned int count, const osg::Vec4d* vertices) 
-        {
-            _vertices.resize(count);
-            for (unsigned i = 0; i < count; ++i)
-                _vertices[i] = SGVec3f(vertices[i][0]/vertices[i][3],
-                                       vertices[i][1]/vertices[i][3],
-                                       vertices[i][2]/vertices[i][3]);
-        }
-
-        virtual void drawArrays(GLenum mode, GLint first, GLsizei count)
-        {
-            if (_vertices.empty() || count <= 0)
-                return;
-
-            GLsizei end = first + count;
-            switch(mode) {
-            case (GL_TRIANGLES):
-                for (GLsizei i = first; i < end - 2; i += 3) {
-                    addTriangle(i, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_TRIANGLE_STRIP):
-                for (GLsizei i = first; i < end - 2; ++i) {
-                    addTriangle(i, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_QUADS):
-                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 = 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; i < end - 2; ++i) {
-                    addTriangle(first, i + 1, i + 2);
-                }
-                break;
-
-            case (GL_POINTS):
-                for (GLsizei i = first; i < end; ++i) {
-                    addPoint(i);
-                }
-                break;
-
-            case (GL_LINES):
-                for (GLsizei i = first; i < end - 1; i += 2) {
-                    addLine(i, i + 1);
-                }
-                break;
-
-            case (GL_LINE_STRIP):
-                for (GLsizei i = first; i < end - 1; ++i) {
-                    addLine(i, i + 1);
-                }
-                break;
-
-            case (GL_LINE_LOOP):
-                for (GLsizei i = first; i < end - 1; ++i) {
-                    addLine(i, i + 1);
-                }
-                addLine(end - 1, first);
-                break;
-
-            default:
-                break;
-            }
-        }
-  
-        virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void drawElements(GLenum mode, GLsizei count, const GLushort* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void drawElements(GLenum mode, GLsizei count, const GLuint* indices)
-        {
-            drawElementsTemplate(mode, count, indices);
-        }
-
-        virtual void begin(GLenum mode)
-        {
-            _modeCache = mode;
-            _vertices.resize(0);
-        }
-
-        virtual void vertex(const osg::Vec2& v)
-        {
-            _vertices.push_back(SGVec3f(v[0], v[1], 0));
-        }
-        virtual void vertex(const osg::Vec3& v)
-        {
-            _vertices.push_back(SGVec3f(v[0], v[1], v[2]));
-        }
-        virtual void vertex(const osg::Vec4& v)
-        {
-            _vertices.push_back(SGVec3f(v[0]/v[3], v[1]/v[3], v[2]/v[3]));
-        }
-        virtual void vertex(float x, float y)
-        {
-            _vertices.push_back(SGVec3f(x, y, 0));
-        }
-        virtual void vertex(float x, float y, float z)
-        {
-            _vertices.push_back(SGVec3f(x, y, z));
-        }
-        virtual void vertex(float x, float y, float z, float w)
-        {
-            _vertices.push_back(SGVec3f(x/w, y/w, z/w));
-        }
-        virtual void end()
-        {
-            if (_vertices.empty())
-                return;
-
-            drawArrays(_modeCache, 0, _vertices.size());
-        }
-
-        template<typename index_type>
-        void drawElementsTemplate(GLenum mode, GLsizei count,
-                                  const index_type* indices)
-        {
-            if (_vertices.empty() || indices == 0 || count <= 0)
-                return;
-    
-            switch(mode) {
-            case (GL_TRIANGLES):
-                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 = 0; i < count - 2; ++i) {
-                    addTriangle(indices[i], indices[i + 1], indices[i + 2]);
-                }
-                break;
-
-            case (GL_QUADS):
-                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 = 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 = 0; i < count - 2; ++i) {
-                    addTriangle(indices[0], indices[i + 1], indices[i + 2]);
-                }
-                break;
-
-            case (GL_POINTS):
-                for(GLsizei i = 0; i < count; ++i) {
-                    addPoint(indices[i]);
-                }
-                break;
-
-            case (GL_LINES):
-                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 - 1; ++i) {
-                    addLine(indices[i], indices[i + 1]);
-                }
-                break;
-
-            case (GL_LINE_LOOP):
-                for (GLsizei i = 0; i < count - 1; ++i) {
-                    addLine(indices[i], indices[i + 1]);
-                }
-                addLine(indices[count - 1], indices[0]);
-                break;
-
-            default:
-                break;
-            }
-        }    
-
-        void addPoint(unsigned i1)
-        {
-            addPoint(_vertices[i1]);
-        }
-        void addLine(unsigned i1, unsigned i2)
-        {
-            addLine(_vertices[i1], _vertices[i2]);
-        }
-        void addTriangle(unsigned i1, unsigned i2, unsigned i3)
-        {
-            addTriangle(_vertices[i1], _vertices[i2], _vertices[i3]);
-        }
-        void addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4)
-        {
-            addQuad(_vertices[i1], _vertices[i2], _vertices[i3], _vertices[i4]);
-        }
-
-        void addPoint(const SGVec3f& v1)
-        {
-        }
-        void addLine(const SGVec3f& v1, const SGVec3f& v2)
-        {
-        }
-        void addTriangle(const SGVec3f& v1, const SGVec3f& v2, const SGVec3f& v3)
-        {
-            _geometryBuilder->addTriangle(v1, v2, v3);
-        }
-        void addQuad(const SGVec3f& v1, const SGVec3f& v2,
-                     const SGVec3f& v3, const SGVec3f& v4)
+        virtual void addPoint(const osg::Vec3d& v1)
+        { }
+        virtual void addLine(const osg::Vec3d& v1, const osg::Vec3d& v2)
+        { }
+        virtual void addTriangle(const osg::Vec3d& v1, const osg::Vec3d& v2, const osg::Vec3d& v3)
         {
-            _geometryBuilder->addTriangle(v1, v2, v3);
-            _geometryBuilder->addTriangle(v1, v3, v4);
+            _geometryBuilder->addTriangle(toVec3f(toSG(v1)), toVec3f(toSG(v2)), toVec3f(toSG(v3)));
         }
 
         BVHNode* buildTreeAndClear()
         {
             BVHNode* bvNode = _geometryBuilder->buildTree();
             _geometryBuilder = new BVHStaticGeometryBuilder;
-            _vertices.clear();
             return bvNode;
         }
 
-        void swap(PFunctor& primitiveFunctor)
+        void swap(_PrimitiveCollector& primitiveCollector)
         {
-            _vertices.swap(primitiveFunctor._vertices);
-            std::swap(_modeCache, primitiveFunctor._modeCache);
-            std::swap(_geometryBuilder, primitiveFunctor._geometryBuilder);
+            PrimitiveCollector::swap(primitiveCollector);
+            std::swap(_geometryBuilder, primitiveCollector._geometryBuilder);
         }
 
         void setCurrentMaterial(const BVHMaterial* material)
@@ -343,37 +81,9 @@ public:
             return _geometryBuilder->getCurrentMaterial();
         }
 
-        std::vector<SGVec3f> _vertices;
-        GLenum _modeCache;
-
         SGSharedPtr<BVHStaticGeometryBuilder> _geometryBuilder;
     };
 
-
-    // class PrimitiveIndexFunctor
-    // {
-    // public:
-
-    //     virtual ~PrimitiveIndexFunctor() {}
-
-    //     virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0;
-    //     virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0;
-    //     virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0;
-
-    //     virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0;
-    //     virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0;
-    //     virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0;
-
-    //     virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0;
-    //     virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0;
-    //     virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0;
-    //     virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0;
-
-    //     virtual void begin(GLenum mode) = 0;
-    //     virtual void vertex(unsigned int pos) = 0;
-    //     virtual void end() = 0;
-    // };
-
     BoundingVolumeBuildVisitor(bool dumpIntoLeafs) :
         osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
         _dumpIntoLeafs(dumpIntoLeafs)
@@ -386,16 +96,16 @@ public:
 
     const BVHMaterial* pushMaterial(osg::Geode* geode)
     {
-        const BVHMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
+        const BVHMaterial* oldMaterial = _primitiveCollector.getCurrentMaterial();
         const BVHMaterial* material = SGMaterialLib::findMaterial(geode);
         if (material)
-            _primitiveFunctor.setCurrentMaterial(material);
+            _primitiveCollector.setCurrentMaterial(material);
         return oldMaterial;
     }
 
     void fillWith(osg::Drawable* drawable)
     {
-        drawable->accept(_primitiveFunctor);
+        drawable->accept(_primitiveCollector);
     }
 
     virtual void apply(osg::Geode& geode)
@@ -408,11 +118,11 @@ public:
         bool flushHere = getNodePath().size() <= 1 || _dumpIntoLeafs;
         if (flushHere) {
             // push the current active primitive list
-            PFunctor previousPrimitives;
-            _primitiveFunctor.swap(previousPrimitives);
+            _PrimitiveCollector previousPrimitives;
+            _primitiveCollector.swap(previousPrimitives);
 
             const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
-            _primitiveFunctor.setCurrentMaterial(mat);
+            _primitiveCollector.setCurrentMaterial(mat);
 
             // walk the children
             for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
@@ -422,13 +132,13 @@ public:
             addBoundingVolumeTreeToNode(geode);
 
             // pop the current active primitive list
-            _primitiveFunctor.swap(previousPrimitives);
+            _primitiveCollector.swap(previousPrimitives);
         } else {
             for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
                 fillWith(geode.getDrawable(i));
         }
 
-        _primitiveFunctor.setCurrentMaterial(oldMaterial);
+        _primitiveCollector.setCurrentMaterial(oldMaterial);
     }
 
     virtual void apply(osg::Group& group)
@@ -455,11 +165,11 @@ public:
             return;
 
         // push the current active primitive list
-        PFunctor previousPrimitives;
-        _primitiveFunctor.swap(previousPrimitives);
+        _PrimitiveCollector previousPrimitives;
+        _primitiveCollector.swap(previousPrimitives);
 
         const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
-        _primitiveFunctor.setCurrentMaterial(mat);
+        _primitiveCollector.setCurrentMaterial(mat);
 
         // walk the children
         traverse(node);
@@ -470,7 +180,7 @@ public:
         addBoundingVolumeTreeToNode(node);
 
         // pop the current active primitive list
-        _primitiveFunctor.swap(previousPrimitives);
+        _primitiveCollector.swap(previousPrimitives);
     }
 
     void traverseAndCollect(osg::Node& node)
@@ -495,7 +205,7 @@ public:
     void addBoundingVolumeTreeToNode(osg::Node& node)
     {
         // Build the flat tree.
-        BVHNode* bvNode = _primitiveFunctor.buildTreeAndClear();
+        BVHNode* bvNode = _primitiveCollector.buildTreeAndClear();
 
         // Nothing in there?
         if (!bvNode)
@@ -518,7 +228,7 @@ public:
     }
 
 private:
-    PFunctor _primitiveFunctor;
+    _PrimitiveCollector _primitiveCollector;
     bool _dumpIntoLeafs;
 };
 
index 31d2c042efea2a1ac8542ae69aeb282cf3119593..f3f493369c767eddce57be66345cd7c835cc084a 100644 (file)
@@ -7,6 +7,7 @@ set(HEADERS
     CheckSceneryVisitor.hxx
     ConditionNode.hxx
     ModelRegistry.hxx
+    PrimitiveCollector.hxx
     SGClipGroup.hxx
     SGInteractionAnimation.hxx
     SGMaterialAnimation.hxx
@@ -29,6 +30,7 @@ set(SOURCES
     CheckSceneryVisitor.cxx
     ConditionNode.cxx
     ModelRegistry.cxx
+    PrimitiveCollector.cxx
     SGClipGroup.cxx
     SGInteractionAnimation.cxx
     SGLightAnimation.cxx
diff --git a/simgear/scene/model/PrimitiveCollector.cxx b/simgear/scene/model/PrimitiveCollector.cxx
new file mode 100644 (file)
index 0000000..c55766d
--- /dev/null
@@ -0,0 +1,350 @@
+// Copyright (C) 2008 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
+#include "PrimitiveCollector.hxx"
+
+#include <simgear/scene/util/OsgMath.hxx>
+
+namespace simgear {
+
+PrimitiveCollector::PrimitiveCollector() :
+    _mode(0)
+{
+}
+
+PrimitiveCollector::~PrimitiveCollector()
+{
+}
+    
+void
+PrimitiveCollector::swap(PrimitiveCollector& primitiveFunctor)
+{
+    _vertices.swap(primitiveFunctor._vertices);
+    std::swap(_mode, primitiveFunctor._mode);
+}
+
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec2* vertices)
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], 0));
+}
+    
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec3* vertices)
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], vertices[i][2]));
+}
+
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec4* vertices)
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec4d(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]));
+}
+
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec2d* vertices)
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], 0));
+}
+
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec3d* vertices)
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec3d(vertices[i][0], vertices[i][1], vertices[i][2]));
+}
+
+void
+PrimitiveCollector::setVertexArray(unsigned int count, const osg::Vec4d* vertices) 
+{
+    _vertices.resize(0);
+    _vertices.reserve(count);
+    for (unsigned i = 0; i < count; ++i)
+        addVertex(osg::Vec4d(vertices[i][0], vertices[i][1], vertices[i][2], vertices[i][3]));
+}
+
+void
+PrimitiveCollector::drawArrays(GLenum mode, GLint first, GLsizei count)
+{
+    if (_vertices.empty() || count <= 0)
+        return;
+
+    GLsizei end = first + count;
+    switch(mode) {
+    case (GL_TRIANGLES):
+        for (GLsizei i = first; i < end - 2; i += 3) {
+            addTriangle(i, i + 1, i + 2);
+        }
+        break;
+
+    case (GL_TRIANGLE_STRIP):
+        for (GLsizei i = first; i < end - 2; ++i) {
+            addTriangle(i, i + 1, i + 2);
+        }
+        break;
+
+    case (GL_QUADS):
+        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 = 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; i < end - 2; ++i) {
+            addTriangle(first, i + 1, i + 2);
+        }
+    break;
+
+    case (GL_POINTS):
+        for (GLsizei i = first; i < end; ++i) {
+            addPoint(i);
+        }
+        break;
+
+    case (GL_LINES):
+        for (GLsizei i = first; i < end - 1; i += 2) {
+            addLine(i, i + 1);
+        }
+        break;
+
+    case (GL_LINE_STRIP):
+        for (GLsizei i = first; i < end - 1; ++i) {
+            addLine(i, i + 1);
+        }
+        break;
+
+    case (GL_LINE_LOOP):
+        for (GLsizei i = first; i < end - 1; ++i) {
+            addLine(i, i + 1);
+        }
+        addLine(end - 1, first);
+        break;
+
+    default:
+        break;
+    }
+}
+  
+template<typename index_type>
+void
+PrimitiveCollector::drawElementsTemplate(GLenum mode, GLsizei count, const index_type* indices)
+{
+    if (_vertices.empty() || indices == 0 || count <= 0)
+        return;
+    
+    switch(mode) {
+    case (GL_TRIANGLES):
+        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 = 0; i < count - 2; ++i) {
+            addTriangle(indices[i], indices[i + 1], indices[i + 2]);
+        }
+        break;
+
+    case (GL_QUADS):
+        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 = 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 = 0; i < count - 2; ++i) {
+            addTriangle(indices[0], indices[i + 1], indices[i + 2]);
+        }
+    break;
+
+    case (GL_POINTS):
+        for(GLsizei i = 0; i < count; ++i) {
+            addPoint(indices[i]);
+        }
+        break;
+
+    case (GL_LINES):
+        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 - 1; ++i) {
+            addLine(indices[i], indices[i + 1]);
+        }
+        break;
+
+    case (GL_LINE_LOOP):
+        for (GLsizei i = 0; i < count - 1; ++i) {
+            addLine(indices[i], indices[i + 1]);
+        }
+        addLine(indices[count - 1], indices[0]);
+        break;
+
+    default:
+        break;
+    }
+}
+
+void
+PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLubyte* indices)
+{
+    drawElementsTemplate(mode, count, indices);
+}
+
+void PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLushort* indices)
+{
+    drawElementsTemplate(mode, count, indices);
+}
+
+void
+PrimitiveCollector::drawElements(GLenum mode, GLsizei count, const GLuint* indices)
+{
+    drawElementsTemplate(mode, count, indices);
+}
+
+void
+PrimitiveCollector::begin(GLenum mode)
+{
+    _mode = mode;
+    _vertices.resize(0);
+}
+
+void
+PrimitiveCollector::vertex(const osg::Vec2& v)
+{
+    addVertex(osg::Vec3d(v[0], v[1], 0));
+}
+
+void
+PrimitiveCollector::vertex(const osg::Vec3& v)
+{
+    addVertex(osg::Vec3d(v[0], v[1], v[2]));
+}
+
+void
+PrimitiveCollector::vertex(const osg::Vec4& v)
+{
+    addVertex(osg::Vec4d(v[0], v[1], v[2], v[3]));
+}
+
+void
+PrimitiveCollector::vertex(float x, float y)
+{
+    addVertex(osg::Vec3d(x, y, 0));
+}
+
+void
+PrimitiveCollector::vertex(float x, float y, float z)
+{
+    addVertex(osg::Vec3d(x, y, z));
+}
+
+void
+PrimitiveCollector::vertex(float x, float y, float z, float w)
+{
+    addVertex(osg::Vec4d(x, y, z, w));
+}
+
+void
+PrimitiveCollector::end()
+{
+    if (_vertices.empty())
+        return;
+
+    drawArrays(_mode, 0, _vertices.size());
+}
+
+void
+PrimitiveCollector::addVertex(const osg::Vec3d& v)
+{
+    _vertices.push_back(v);
+}
+
+void
+PrimitiveCollector::addVertex(const osg::Vec4d& v)
+{
+    _vertices.push_back(osg::Vec3d(v[0]/v[3], v[1]/v[3], v[2]/v[3]));
+}
+
+void
+PrimitiveCollector::addPoint(unsigned i1)
+{
+    if (_vertices.size() <= i1)
+        return;
+    addPoint(_vertices[i1]);
+}
+
+void
+PrimitiveCollector::addLine(unsigned i1, unsigned i2)
+{
+    size_t size = _vertices.size();
+    if (size <= i1 || size <= i2)
+        return;
+    addLine(_vertices[i1], _vertices[i2]);
+}
+
+void
+PrimitiveCollector::addTriangle(unsigned i1, unsigned i2, unsigned i3)
+{
+    size_t size = _vertices.size();
+    if (size <= i1 || size <= i2 || size <= i3)
+        return;
+    addTriangle(_vertices[i1], _vertices[i2], _vertices[i3]);
+}
+
+void
+PrimitiveCollector::addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4)
+{
+    addTriangle(i1, i2, i3);
+    addTriangle(i1, i3, i4);
+}
+
+}
diff --git a/simgear/scene/model/PrimitiveCollector.hxx b/simgear/scene/model/PrimitiveCollector.hxx
new file mode 100644 (file)
index 0000000..fc014db
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2008 - 2012  Mathias Froehlich - Mathias.Froehlich@web.de
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Library General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Library General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef SIMGEAR_PRIMITIVE_COLLECTOR_HXX
+#define SIMGEAR_PRIMITIVE_COLLECTOR_HXX
+
+#include <osg/Matrix>
+#include <osg/PrimitiveSet>
+
+namespace simgear {
+
+class PrimitiveCollector : public osg::PrimitiveFunctor {
+public:
+    PrimitiveCollector();
+    virtual ~PrimitiveCollector();
+    
+    void swap(PrimitiveCollector& primitiveFunctor);
+
+    virtual void setVertexArray(unsigned int count, const osg::Vec2* vertices);
+    virtual void setVertexArray(unsigned int count, const osg::Vec3* vertices);
+    virtual void setVertexArray(unsigned int count, const osg::Vec4* vertices);
+    virtual void setVertexArray(unsigned int count, const osg::Vec2d* vertices);
+    virtual void setVertexArray(unsigned int count, const osg::Vec3d* vertices);
+    virtual void setVertexArray(unsigned int count, const osg::Vec4d* vertices);
+
+    virtual void drawArrays(GLenum mode, GLint first, GLsizei count);
+  
+    template<typename index_type>
+    void drawElementsTemplate(GLenum mode, GLsizei count, const index_type* indices);
+    virtual void drawElements(GLenum mode, GLsizei count, const GLubyte* indices);
+    virtual void drawElements(GLenum mode, GLsizei count, const GLushort* indices);
+    virtual void drawElements(GLenum mode, GLsizei count, const GLuint* indices);
+
+    virtual void begin(GLenum mode);
+    virtual void vertex(const osg::Vec2& v);
+    virtual void vertex(const osg::Vec3& v);
+    virtual void vertex(const osg::Vec4& v);
+    virtual void vertex(float x, float y);
+    virtual void vertex(float x, float y, float z);
+    virtual void vertex(float x, float y, float z, float w);
+    virtual void end();
+
+    void addVertex(const osg::Vec3d& v);
+    void addVertex(const osg::Vec4d& v);
+
+    void addPoint(unsigned i1);
+    void addLine(unsigned i1, unsigned i2);
+    void addTriangle(unsigned i1, unsigned i2, unsigned i3);
+    void addQuad(unsigned i1, unsigned i2, unsigned i3, unsigned i4);
+
+    /// The callback functions that are called on an apropriate primitive
+    virtual void addPoint(const osg::Vec3d& v1) = 0;
+    virtual void addLine(const osg::Vec3d& v1, const osg::Vec3d& v2) = 0;
+    virtual void addTriangle(const osg::Vec3d& v1, const osg::Vec3d& v2, const osg::Vec3d& v3) = 0;
+
+private:
+    std::vector<osg::Vec3d> _vertices;
+    GLenum _mode;
+};
+
+}
+
+#endif