#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Group>
-#include <osg/MatrixTransform>
#include <osg/PagedLOD>
#include <osg/Transform>
#include <osg/TriangleFunctor>
+#include <simgear/scene/material/Effect.hxx>
+#include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/mat.hxx>
#include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx>
// virtual void end() = 0;
// };
- BoundingVolumeBuildVisitor() :
- osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN)
+ BoundingVolumeBuildVisitor(bool dumpIntoLeafs) :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+ _dumpIntoLeafs(dumpIntoLeafs)
{
setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
}
{
}
- const SGMaterial* pushMaterial(osg::StateSet* stateSet)
+ const SGMaterial* pushMaterial(Effect* effect)
{
const SGMaterial* oldMaterial = _primitiveFunctor.getCurrentMaterial();
- const SGMaterial* material = SGMaterialLib::findMaterial(stateSet);
+ const SGMaterial* material = SGMaterialLib::findMaterial(effect);
if (material)
_primitiveFunctor.setCurrentMaterial(material);
return oldMaterial;
void fillWith(osg::Drawable* drawable)
{
- const SGMaterial* oldMaterial = pushMaterial(drawable->getStateSet());
drawable->accept(_primitiveFunctor);
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
}
virtual void apply(osg::Geode& geode)
{
- const SGMaterial* oldMaterial = pushMaterial(geode.getStateSet());
+ if (hasBoundingVolumeTree(geode))
+ return;
+
+ const SGMaterial* oldMaterial = 0;
+
+ EffectGeode *eg = dynamic_cast<EffectGeode*>(&geode);
+ if (eg)
+ oldMaterial = pushMaterial(eg->getEffect());
- if (!hasBoundingVolumeTree(geode))
+ bool flushHere = getNodePath().size() <= 1 || _dumpIntoLeafs;
+ if (flushHere) {
+ // push the current active primitive list
+ PFunctor previousPrimitives;
+ _primitiveFunctor.swap(previousPrimitives);
+
+ // walk the children
for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
fillWith(geode.getDrawable(i));
- // Flush the bounding volume tree if we reached the topmost group
- if (getNodePath().size() <= 1)
+ // Flush the bounding volume tree if we reached the topmost group
addBoundingVolumeTreeToNode(geode);
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+
+ // pop the current active primitive list
+ _primitiveFunctor.swap(previousPrimitives);
+ } else {
+ for(unsigned i = 0; i < geode.getNumDrawables(); ++i)
+ fillWith(geode.getDrawable(i));
+ }
+ if (eg)
+ _primitiveFunctor.setCurrentMaterial(oldMaterial);
}
virtual void apply(osg::Group& group)
- {
- // Note that we do not need to push the already collected list of
- // primitives, since we are now in the topmost node ...
-
- const SGMaterial* oldMaterial = pushMaterial(group.getStateSet());
+ { traverseAndCollect(group); }
- if (!hasBoundingVolumeTree(group))
- traverse(group);
+ virtual void apply(osg::Transform& transform)
+ { traverseAndDump(transform); }
- // Flush the bounding volume tree if we reached the topmost group
- if (getNodePath().size() <= 1)
- addBoundingVolumeTreeToNode(group);
+ virtual void apply(osg::PagedLOD&)
+ {
+ // Do nothing. In this case we get called by the loading process anyway
+ }
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+ virtual void apply(osg::Camera& camera)
+ {
+ if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+ return;
+ traverseAndDump(camera);
}
- virtual void apply(osg::Transform& transform)
+ void traverseAndDump(osg::Node& node)
{
+ if (hasBoundingVolumeTree(node))
+ return;
+
// push the current active primitive list
PFunctor previousPrimitives;
_primitiveFunctor.swap(previousPrimitives);
- const SGMaterial* oldMaterial = pushMaterial(transform.getStateSet());
-
// walk the children
- if (!hasBoundingVolumeTree(transform))
- traverse(transform);
+ traverse(node);
// We know whenever we see a transform, we need to flush the
// collected bounding volume tree since these transforms are not
// handled by the plain leafs.
- addBoundingVolumeTreeToNode(transform);
-
- _primitiveFunctor.setCurrentMaterial(oldMaterial);
+ addBoundingVolumeTreeToNode(node);
// pop the current active primitive list
_primitiveFunctor.swap(previousPrimitives);
}
- virtual void apply(osg::PagedLOD&)
+ void traverseAndCollect(osg::Node& node)
{
- // Do nothing. In this case we get called by the loading process anyway
- }
+ // Already been here??
+ if (hasBoundingVolumeTree(node))
+ return;
- virtual void apply(osg::Camera& camera)
- {
- if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+ // Force a flush of the bvtree if we are in the topmost node.
+ if (getNodePath().size() <= 1) {
+ traverseAndDump(node);
return;
- apply(static_cast<osg::Transform&>(camera));
+ }
+
+ // Note that we do not need to push the already collected list of
+ // primitives, since we are now in the topmost node ...
+
+ // walk the children
+ traverse(node);
}
void addBoundingVolumeTreeToNode(osg::Node& node)
private:
PFunctor _primitiveFunctor;
+ bool _dumpIntoLeafs;
};
}