From 63aa16b97c92f80e05e70dddd9335ac452213591 Mon Sep 17 00:00:00 2001 From: Mathias Froehlich Date: Tue, 25 Sep 2012 23:42:14 +0200 Subject: [PATCH] scene: Factor out a common primitive functor. 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 | 327 ++-------------- .../model/BoundingVolumeBuildVisitor.hxx | 352 ++---------------- simgear/scene/model/CMakeLists.txt | 2 + simgear/scene/model/PrimitiveCollector.cxx | 350 +++++++++++++++++ simgear/scene/model/PrimitiveCollector.hxx | 77 ++++ 5 files changed, 490 insertions(+), 618 deletions(-) create mode 100644 simgear/scene/model/PrimitiveCollector.cxx create mode 100644 simgear/scene/model/PrimitiveCollector.hxx diff --git a/simgear/scene/model/BVHPageNodeOSG.cxx b/simgear/scene/model/BVHPageNodeOSG.cxx index 412fedd5..2a288ac0 100644 --- a/simgear/scene/model/BVHPageNodeOSG.cxx +++ b/simgear/scene/model/BVHPageNodeOSG.cxx @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -43,303 +42,40 @@ #include +#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) + 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) { - _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 - 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) - { - _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 _vertices; - GLenum _modeCache; - SGSharedPtr _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 = 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 > NodeVector; NodeVector _nodeVector; }; diff --git a/simgear/scene/model/BoundingVolumeBuildVisitor.hxx b/simgear/scene/model/BoundingVolumeBuildVisitor.hxx index 5be621bf..d9271917 100644 --- a/simgear/scene/model/BoundingVolumeBuildVisitor.hxx +++ b/simgear/scene/model/BoundingVolumeBuildVisitor.hxx @@ -29,309 +29,47 @@ #include #include +#include #include #include #include #include +#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) + 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) { - _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 - 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) - { - _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 _vertices; - GLenum _modeCache; - SGSharedPtr _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; }; diff --git a/simgear/scene/model/CMakeLists.txt b/simgear/scene/model/CMakeLists.txt index 31d2c042..f3f49336 100644 --- a/simgear/scene/model/CMakeLists.txt +++ b/simgear/scene/model/CMakeLists.txt @@ -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 index 00000000..c55766d6 --- /dev/null +++ b/simgear/scene/model/PrimitiveCollector.cxx @@ -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 +#endif + +#include "PrimitiveCollector.hxx" + +#include + +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 +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 index 00000000..fc014dbf --- /dev/null +++ b/simgear/scene/model/PrimitiveCollector.hxx @@ -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 +#include + +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 + 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 _vertices; + GLenum _mode; +}; + +} + +#endif