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.
This commit is contained in:
Mathias Froehlich 2012-09-25 23:42:14 +02:00
parent cafbf860be
commit 63aa16b97c
5 changed files with 490 additions and 618 deletions

View 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>
@ -43,303 +42,40 @@
#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)
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<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)
{
_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;
};

View File

@ -29,309 +29,47 @@
#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)
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<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)
{
_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;
};

View 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

View File

@ -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);
}
}

View File

@ -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