1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
#ifndef OPENMW_COMPONENTS_SCENEUTIL_CULLSAFEBOUNDSVISITOR_H
#define OPENMW_COMPONENTS_SCENEUTIL_CULLSAFEBOUNDSVISITOR_H
#include <vector>
#include <osg/BoundingBox>
#include <osg/Matrix>
#include <osg/NodeVisitor>
#include <osg/Drawable>
#include <osg/Transform>
namespace SceneUtil
{
// Computes bounding box of a node without dirtying it or any of its children
struct CullSafeBoundsVisitor : osg::NodeVisitor
{
CullSafeBoundsVisitor(osg::NodeVisitor::TraversalMode traversalMode = TRAVERSE_ALL_CHILDREN)
: osg::NodeVisitor(traversalMode)
{
}
void reset() override
{
mMatrixStack.clear();
mBoundingBox.init();
}
void apply(osg::Drawable& drawable)
{
osg::BoundingBox bbox = drawable.getInitialBound();
bbox.expandBy(drawable.computeBoundingBox());
applyBoundingBox(bbox);
}
void apply(osg::Transform& transform)
{
osg::Matrix matrix;
if (!mMatrixStack.empty())
matrix = mMatrixStack.back();
transform.computeLocalToWorldMatrix(matrix, this);
mMatrixStack.push_back(matrix);
traverse(transform);
mMatrixStack.pop_back();
}
void applyBoundingBox(const osg::BoundingBox& bbox)
{
if (mMatrixStack.empty())
{
mBoundingBox.expandBy(bbox);
}
else if (bbox.valid())
{
for (int i = 0; i < 8; ++i)
mBoundingBox.expandBy(bbox.corner(i) * mMatrixStack.back());
}
}
osg::BoundingBox mBoundingBox;
std::vector<osg::Matrix> mMatrixStack;
};
}
#endif // OPENMW_COMPONENTS_SCENEUTIL_CULLSAFEBOUNDSVISITOR_H
|