#include "../../bvh/BVHPageRequest.hxx"
#include "../../bvh/BVHPager.hxx"
+#include <osg/io_utils>
#include <osg/Camera>
#include <osg/Drawable>
#include <osg/Geode>
#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 {
- public:
- PFunctor() :
- _modeCache(0)
- {
- _geometryBuilder = new BVHStaticGeometryBuilder;
- }
- virtual ~PFunctor()
+ struct _PrimitiveCollector : public PrimitiveCollector {
+ _PrimitiveCollector(_NodeVisitor& nodeVisitor) :
+ _nodeVisitor(nodeVisitor)
{ }
+ virtual ~_PrimitiveCollector()
+ { }
+ 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)
+ { _nodeVisitor.addTriangle(v1, v2, v3); }
+ private:
+ _NodeVisitor& _nodeVisitor;
+ };
- 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;
+ struct _NodeBin {
+ SGSharedPtr<BVHNode> getNode(const osg::Matrix& matrix)
+ {
+ if (_nodeVector.empty())
+ return SGSharedPtr<BVHNode>();
+
+ if (!matrix.isIdentity()) {
+ // If we have a non trivial matrix we need a
+ // transform node in any case.
+ SGSharedPtr<BVHTransform> transform = new BVHTransform;
+ transform->setToWorldTransform(SGMatrixd(matrix.ptr()));
+ for (_NodeVector::iterator i = _nodeVector.begin();
+ i != _nodeVector.end(); ++i)
+ transform->addChild(i->get());
+ return transform;
+ } else {
+ // If the matrix is an identity, return the
+ // smallest possible subtree.
+ if (_nodeVector.size() == 1)
+ return _nodeVector.front();
+ SGSharedPtr<BVHGroup> group = new BVHGroup;
+ for (_NodeVector::iterator i = _nodeVector.begin();
+ i != _nodeVector.end(); ++i)
+ group->addChild(i->get());
+ return group;
}
}
-
- 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)
+
+ void addNode(const SGSharedPtr<BVHNode>& node)
{
- _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())
+ if (!node.valid())
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)
+ if (node->getBoundingSphere().empty())
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);
- }
-
- BVHNode* buildTreeAndClear()
- {
- BVHNode* bvNode = _geometryBuilder->buildTree();
- _geometryBuilder = new BVHStaticGeometryBuilder;
- _vertices.clear();
- return bvNode;
- }
-
- void swap(PFunctor& primitiveFunctor)
- {
- _vertices.swap(primitiveFunctor._vertices);
- std::swap(_modeCache, primitiveFunctor._modeCache);
- std::swap(_geometryBuilder, primitiveFunctor._geometryBuilder);
- }
-
- void setCurrentMaterial(const BVHMaterial* material)
- {
- _geometryBuilder->setCurrentMaterial(material);
- }
- const BVHMaterial* getCurrentMaterial() const
- {
- return _geometryBuilder->getCurrentMaterial();
+ _nodeVector.push_back(node);
}
-
- std::vector<SGVec3f> _vertices;
- GLenum _modeCache;
-
- SGSharedPtr<BVHStaticGeometryBuilder> _geometryBuilder;
+
+ private:
+ typedef std::vector<SGSharedPtr<BVHNode> > _NodeVector;
+
+ // The current pending node vector.
+ _NodeVector _nodeVector;
};
-
- _NodeVisitor() :
- osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
+
+ _NodeVisitor(bool flatten, const osg::Matrix& localToWorldMatrix = osg::Matrix()) :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+ _localToWorldMatrix(localToWorldMatrix),
+ _geometryBuilder(new BVHStaticGeometryBuilder),
+ _flatten(flatten)
{
setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
}
{
}
- const BVHMaterial* pushMaterial(osg::Geode* geode)
+ void addTriangle(const osg::Vec3d& v1, const osg::Vec3d& v2, const osg::Vec3d& v3)
{
- const BVHMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
- const BVHMaterial* material = SGMaterialLib::findMaterial(geode);
- if (material)
- _primitiveFunctor.setCurrentMaterial(material);
- return oldMaterial;
+ _geometryBuilder->addTriangle(toVec3f(toSG(_localToWorldMatrix.preMult(v1))),
+ toVec3f(toSG(_localToWorldMatrix.preMult(v2))),
+ toVec3f(toSG(_localToWorldMatrix.preMult(v3))));
+ }
+
+ void setCenter(const osg::Vec3& center)
+ {
+ _centerMatrix.preMultTranslate(center);
+ _localToWorldMatrix.postMultTranslate(-center);
+ if (1e6 < center.length()) {
+ SGGeod geod = SGGeod::fromCart(toVec3d(toSG(center)));
+ SGQuatd orientation = SGQuatd::fromLonLat(geod);
+ _centerMatrix.preMultRotate(toOsg(orientation));
+ _localToWorldMatrix.postMultRotate(toOsg(inverse(orientation)));
+ }
}
virtual void apply(osg::Geode& geode)
{
- const BVHMaterial* oldMaterial = pushMaterial(&geode);
+ const BVHMaterial* oldMaterial = _geometryBuilder->getCurrentMaterial();
+ if (const BVHMaterial* material = SGMaterialLib::findMaterial(&geode))
+ _geometryBuilder->setCurrentMaterial(material);
+ _PrimitiveCollector primitiveCollector(*this);
for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
- geode.getDrawable(i)->accept(_primitiveFunctor);
+ geode.getDrawable(i)->accept(primitiveCollector);
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+ _geometryBuilder->setCurrentMaterial(oldMaterial);
}
- virtual void apply(osg::Group& group)
+ virtual void apply(osg::Node& node)
{
- // FIXME optimize this to collapse more leafs
-
- // push the current active primitive list
- PFunctor previousPrimitives;
- _primitiveFunctor.swap(previousPrimitives);
-
- const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
- _primitiveFunctor.setCurrentMaterial(mat);
-
- NodeVector nodeVector;
- _nodeVector.swap(nodeVector);
-
- // walk the children
- traverse(group);
-
- // We know whenever we see a transform, we need to flush the
- // collected bounding volume tree since these transforms are not
- // handled by the plain leafs.
- addBoundingVolumeTreeToNode();
-
- _nodeVector.swap(nodeVector);
-
- if (!nodeVector.empty()) {
- if (nodeVector.size() == 1) {
- _nodeVector.push_back(nodeVector.front());
- } else {
- SGSharedPtr<BVHGroup> group = new BVHGroup;
- for (NodeVector::iterator i = nodeVector.begin();
- i != nodeVector.end(); ++i)
- group->addChild(i->get());
- _nodeVector.push_back(group);
- }
+ if (_flatten) {
+ traverse(node);
+ } else {
+ _NodeVisitor nodeVisitor(_flatten, _localToWorldMatrix);
+ nodeVisitor.traverse(node);
+ _nodeBin.addNode(nodeVisitor.getNode(osg::Matrix::identity()));
}
-
- // pop the current active primitive list
- _primitiveFunctor.swap(previousPrimitives);
}
virtual void apply(osg::Transform& transform)
if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
return;
- osg::Matrix matrix;
- if (!transform.computeLocalToWorldMatrix(matrix, this))
- return;
-
- // push the current active primitive list
- PFunctor previousPrimitives;
- _primitiveFunctor.swap(previousPrimitives);
-
- const BVHMaterial* mat = previousPrimitives.getCurrentMaterial();
- _primitiveFunctor.setCurrentMaterial(mat);
-
- NodeVector nodeVector;
- _nodeVector.swap(nodeVector);
-
- // walk the children
- traverse(transform);
-
- // We know whenever we see a transform, we need to flush the
- // collected bounding volume tree since these transforms are not
- // handled by the plain leafs.
- addBoundingVolumeTreeToNode();
+ // FIXME identify and handle dynamic transforms
- _nodeVector.swap(nodeVector);
+ if (_flatten) {
+ // propagate the matrix further down into the nodes and
+ // build a flat leaf tree as far as possible
- // pop the current active primitive list
- _primitiveFunctor.swap(previousPrimitives);
+ // save away and accumulate the localToWorldMatrix
+ osg::Matrix localToWorldMatrix = _localToWorldMatrix;
+ if (!transform.computeLocalToWorldMatrix(_localToWorldMatrix, this))
+ return;
- if (!nodeVector.empty()) {
- SGSharedPtr<BVHTransform> bvhTransform = new BVHTransform;
- bvhTransform->setToWorldTransform(SGMatrixd(matrix.ptr()));
+ traverse(transform);
- for (NodeVector::iterator i = nodeVector.begin();
- i != nodeVector.end(); ++i)
- bvhTransform->addChild(i->get());
+ _localToWorldMatrix = localToWorldMatrix;
+ } else {
+ // accumulate the localToWorldMatrix
+ osg::Matrix localToWorldMatrix = _localToWorldMatrix;
+ if (!transform.computeLocalToWorldMatrix(localToWorldMatrix, this))
+ return;
- _nodeVector.push_back(bvhTransform);
+ // evaluate the loca to world matrix here in this group node.
+ _NodeVisitor nodeVisitor(_flatten);
+ nodeVisitor.traverse(transform);
+ _nodeBin.addNode(nodeVisitor.getNode(localToWorldMatrix));
}
}
apply(static_cast<osg::Transform&>(camera));
}
- void addBoundingVolumeTreeToNode()
- {
- // Build the flat tree.
- BVHNode* bvNode = _primitiveFunctor.buildTreeAndClear();
-
- // Nothing in there?
- if (!bvNode)
- return;
- if (bvNode->getBoundingSphere().empty())
- return;
-
- _nodeVector.push_back(bvNode);
- }
-
virtual void apply(osg::PagedLOD& pagedLOD)
{
- float range = std::numeric_limits<float>::max();
unsigned numFileNames = pagedLOD.getNumFileNames();
- for (unsigned i = 0; i < numFileNames; ++i) {
- if (range < pagedLOD.getMaxRange(i))
- continue;
- range = pagedLOD.getMaxRange(i);
- }
-
- std::vector<std::string> nameList;
- for (unsigned i = pagedLOD.getNumChildren(); i < pagedLOD.getNumFileNames(); ++i) {
- if (pagedLOD.getMaxRange(i) <= range) {
+ if (_flatten) {
+ // In flattening mode treat lod nodes as proxy nodes
+ for (unsigned i = 0; i < numFileNames; ++i) {
+ if (i < pagedLOD.getNumChildren() && pagedLOD.getChild(i))
+ continue;
+ osg::ref_ptr<osg::Node> node;
+ if (pagedLOD.getMinRange(i) <= 0) {
+ osg::ref_ptr<const osgDB::Options> options;
+ options = getOptions(pagedLOD.getDatabaseOptions(), pagedLOD.getDatabasePath());
+ node = osgDB::readRefNodeFile(pagedLOD.getFileName(i), options.get());
+ }
+ if (!node.valid())
+ node = new osg::Group;
+ if (i < pagedLOD.getNumChildren())
+ pagedLOD.setChild(i, node);
+ else
+ pagedLOD.addChild(node);
+ }
+ } else {
+ // in non flattening mode translate to bvh page nodes
+ std::vector<std::string> nameList;
+ for (unsigned i = pagedLOD.getNumChildren(); i < numFileNames; ++i) {
+ if (0 < pagedLOD.getMinRange(i))
+ continue;
nameList.push_back(pagedLOD.getFileName(i));
}
- }
- if (!nameList.empty()) {
- SGSphered boundingSphere(toVec3d(toSG(pagedLOD.getCenter())), pagedLOD.getRadius());
- _nodeVector.push_back(new BVHPageNodeOSG(nameList, boundingSphere, pagedLOD.getDatabaseOptions()));
+ _NodeBin nodeBin;
+ if (!nameList.empty()) {
+ osg::ref_ptr<const osgDB::Options> options;
+ options = getOptions(pagedLOD.getDatabaseOptions(), pagedLOD.getDatabasePath());
+ SGSphered boundingSphere(toVec3d(toSG(pagedLOD.getCenter())), pagedLOD.getRadius());
+ nodeBin.addNode(new BVHPageNodeOSG(nameList, boundingSphere, options.get()));
+ }
+ _nodeBin.addNode(nodeBin.getNode(_localToWorldMatrix));
}
-
+
// For the rest that might be already there, traverse this as lod
apply(static_cast<osg::LOD&>(pagedLOD));
}
for (unsigned i = 0; i < numFileNames; ++i) {
if (i < proxyNode.getNumChildren() && proxyNode.getChild(i))
continue;
- // FIXME evaluate proxyNode.getDatabasePath()
+ osg::ref_ptr<const osgDB::Options> options;
+ options = getOptions(proxyNode.getDatabaseOptions(), proxyNode.getDatabasePath());
osg::ref_ptr<osg::Node> node;
- node = osgDB::readNodeFile(proxyNode.getFileName(i),
- dynamic_cast<const osgDB::Options*>(proxyNode.getDatabaseOptions()));
+ node = osgDB::readRefNodeFile(proxyNode.getFileName(i), options.get());
if (!node.valid())
node = new osg::Group;
if (i < proxyNode.getNumChildren())
apply(static_cast<osg::Group&>(proxyNode));
}
- SGSharedPtr<BVHNode> getBVHNode()
+ static osg::ref_ptr<const osgDB::Options>
+ getOptions(const osg::Referenced* referenced, const std::string& databasePath)
{
- addBoundingVolumeTreeToNode();
-
- if (_nodeVector.empty())
- return SGSharedPtr<BVHNode>();
- if (_nodeVector.size() == 1)
- return _nodeVector.front();
- SGSharedPtr<BVHGroup> group = new BVHGroup;
- for (NodeVector::iterator i = _nodeVector.begin();
- i != _nodeVector.end(); ++i)
- group->addChild(i->get());
- return group;
+ osg::ref_ptr<const osgDB::Options> options = dynamic_cast<const osgDB::Options*>(referenced);
+ if (!options.valid())
+ options = osgDB::Registry::instance()->getOptions();
+ if (databasePath.empty())
+ return options;
+ osg::ref_ptr<osgDB::Options> writable;
+ if (options.valid())
+ writable = static_cast<osgDB::Options*>(options->clone(osg::CopyOp()));
+ else
+ writable = new osgDB::Options;
+ writable->getDatabasePathList().push_front(databasePath);
+ return writable;
+ }
+
+ SGSharedPtr<BVHNode> getNode(const osg::Matrix& matrix = osg::Matrix())
+ {
+ // Flush any pendig leaf nodes
+ if (_geometryBuilder.valid()) {
+ _nodeBin.addNode(_geometryBuilder->buildTree());
+ _geometryBuilder.clear();
+ }
+
+ return _nodeBin.getNode(matrix*_centerMatrix);
}
private:
- PFunctor _primitiveFunctor;
- typedef std::vector<SGSharedPtr<BVHNode> > NodeVector;
- NodeVector _nodeVector;
+ // The part of the accumulated model view matrix that
+ // is put into a BVHTransform node.
+ osg::Matrix _localToWorldMatrix;
+ // The matrix that centers and aligns the leaf.
+ osg::Matrix _centerMatrix;
+
+ // The current pending nodes.
+ _NodeBin _nodeBin;
+
+ SGSharedPtr<BVHStaticGeometryBuilder> _geometryBuilder;
+
+ bool _flatten;
};
class BVHPageNodeOSG::_Request : public BVHPageRequest {
return _pageNode.get();
}
+private:
SGSharedPtr<BVHPageNodeOSG> _pageNode;
std::vector<SGSharedPtr<BVHNode> > _nodeVector;
};
SGSharedPtr<BVHNode>
-BVHPageNodeOSG::load(const std::string& name, const osg::ref_ptr<osg::Referenced>& options)
+BVHPageNodeOSG::load(const std::string& name, const osg::ref_ptr<const osg::Referenced>& options)
{
osg::ref_ptr<osg::Node> node;
- node = osgDB::readNodeFile(name, dynamic_cast<const osgDB::Options*>(options.get()));
+ node = osgDB::readRefNodeFile(name, dynamic_cast<const osgDB::Options*>(options.get()));
if (!node.valid())
return SGSharedPtr<BVHNode>();
- _NodeVisitor nodeVisitor;
+ bool flatten = (node->getBound()._radius < 30000);
+ _NodeVisitor nodeVisitor(flatten);
+ if (flatten)
+ nodeVisitor.setCenter(node->getBound()._center);
node->accept(nodeVisitor);
- return nodeVisitor.getBVHNode();
+ return nodeVisitor.getNode();
}
BVHPageNodeOSG::BVHPageNodeOSG(const std::string& name,
const SGSphered& boundingSphere,
- const osg::ref_ptr<osg::Referenced>& options) :
+ const osg::ref_ptr<const osg::Referenced>& options) :
_boundingSphere(boundingSphere),
_options(options)
{
BVHPageNodeOSG::BVHPageNodeOSG(const std::vector<std::string>& nameList,
const SGSphered& boundingSphere,
- const osg::ref_ptr<osg::Referenced>& options) :
+ const osg::ref_ptr<const osg::Referenced>& options) :
_modelList(nameList),
_boundingSphere(boundingSphere),
_options(options)