forked from mirror/openmw-tes3mp
Place Drawables directly in the scene graph when built with OSG 3.4
OSG 3.4 adds the ability to place Drawables directly in the scene graph, without a Geode decorating them. Leveraging this should give a small performance boost, because the redundant Geodes increase culling overhead. There is still an oustanding issue with the RemoveDrawableVisitor no longer working correctly, because Drawables can have multiple parents.
This commit is contained in:
parent
35459f20d5
commit
f1ac408f35
7 changed files with 138 additions and 56 deletions
|
@ -11,6 +11,7 @@
|
|||
#include <osg/Geode>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Material>
|
||||
#include <osg/Version>
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
|
@ -196,10 +197,18 @@ namespace
|
|||
traverse(node);
|
||||
}
|
||||
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||
virtual void apply(osg::Drawable& drw)
|
||||
{
|
||||
mToRemove.push_back(&drw);
|
||||
}
|
||||
#endif
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
// FIXME: a Drawable might have more than one parent
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
|
@ -219,6 +228,18 @@ namespace
|
|||
}
|
||||
|
||||
virtual void apply(osg::Geode &node)
|
||||
{
|
||||
applyImpl(node);
|
||||
}
|
||||
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||
virtual void apply(osg::Drawable& drw)
|
||||
{
|
||||
applyImpl(drw);
|
||||
}
|
||||
#endif
|
||||
|
||||
void applyImpl(osg::Node& node)
|
||||
{
|
||||
const std::string toFind = "tri bip";
|
||||
if (Misc::StringUtils::ciCompareLen(node.getName(), toFind, toFind.size()) == 0)
|
||||
|
@ -232,6 +253,7 @@ namespace
|
|||
{
|
||||
for (std::vector<osg::Node*>::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
// FIXME: a Drawable might have more than one parent
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <osg/Geode>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osg/UserDataContainer>
|
||||
#include <osg/Version>
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
#include <osgParticle/ParticleProcessor>
|
||||
|
@ -54,11 +55,19 @@ namespace
|
|||
for (std::vector<osgParticle::ParticleSystem*>::iterator it = partsysVector.begin(); it != partsysVector.end(); ++it)
|
||||
geode.removeDrawable(*it);
|
||||
}
|
||||
#if OSG_VERSION_GREATER_OR_EQUAL(3,3,3)
|
||||
virtual void apply(osg::Drawable& drw)
|
||||
{
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||
mToRemove.push_back(partsys);
|
||||
}
|
||||
#endif
|
||||
|
||||
void remove()
|
||||
{
|
||||
for (std::vector<osg::ref_ptr<osg::Node> >::iterator it = mToRemove.begin(); it != mToRemove.end(); ++it)
|
||||
{
|
||||
// FIXME: a Drawable might have more than one parent
|
||||
osg::Node* node = *it;
|
||||
if (node->getNumParents())
|
||||
node->getParent(0)->removeChild(node);
|
||||
|
|
|
@ -351,33 +351,36 @@ public:
|
|||
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||
{
|
||||
osg::Drawable* drw = geode.getDrawable(i);
|
||||
apply(*drw);
|
||||
}
|
||||
}
|
||||
void apply(osg::Drawable& drw)
|
||||
{
|
||||
osg::Geometry* geom = drw.asGeometry();
|
||||
if (!geom)
|
||||
return;
|
||||
|
||||
osg::Geometry* geom = drw->asGeometry();
|
||||
if (!geom)
|
||||
continue;
|
||||
|
||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
|
||||
for (unsigned int i=0; i<colors->size(); ++i)
|
||||
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(geom->getVertexArray()->getNumElements());
|
||||
for (unsigned int i=0; i<colors->size(); ++i)
|
||||
{
|
||||
float alpha = 1.f;
|
||||
if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
||||
else if (mMeshType == 1)
|
||||
{
|
||||
float alpha = 1.f;
|
||||
if (mMeshType == 0) alpha = i%2 ? 0.f : 1.f; // this is a cylinder, so every second vertex belongs to the bottom-most row
|
||||
else if (mMeshType == 1)
|
||||
{
|
||||
if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row
|
||||
else if (i>= 33 && i <= 48) alpha = 0.25098; // second row
|
||||
else alpha = 1.f;
|
||||
}
|
||||
else if (mMeshType == 2)
|
||||
{
|
||||
osg::Vec4Array* origColors = static_cast<osg::Vec4Array*>(geom->getColorArray());
|
||||
alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
(*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha);
|
||||
if (i>= 49 && i <= 64) alpha = 0.f; // bottom-most row
|
||||
else if (i>= 33 && i <= 48) alpha = 0.25098; // second row
|
||||
else alpha = 1.f;
|
||||
}
|
||||
else if (mMeshType == 2)
|
||||
{
|
||||
osg::Vec4Array* origColors = static_cast<osg::Vec4Array*>(geom->getColorArray());
|
||||
alpha = ((*origColors)[i].x() == 1.f) ? 1.f : 0.f;
|
||||
}
|
||||
|
||||
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
|
||||
(*colors)[i] = osg::Vec4f(0.f, 0.f, 0.f, alpha);
|
||||
}
|
||||
|
||||
geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Array>
|
||||
#include <osg/Version>
|
||||
|
||||
// resource
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
@ -885,9 +886,6 @@ namespace NifOsg
|
|||
// localToWorldMatrix for transforming to particle space
|
||||
handleParticlePrograms(partctrl->affectors, partctrl->colliders, parentNode, partsys.get(), rf);
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(partsys);
|
||||
|
||||
std::vector<const Nif::Property*> drawableProps;
|
||||
collectDrawableProperties(nifNode, drawableProps);
|
||||
applyDrawableProperties(parentNode, drawableProps, composite, true, animflags);
|
||||
|
@ -907,13 +905,21 @@ namespace NifOsg
|
|||
updater->addParticleSystem(partsys);
|
||||
parentNode->addChild(updater);
|
||||
|
||||
#if not(OSG_MIN_VERSION_REQUIRED(3,3,3))
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(partsys);
|
||||
osg::Node* toAttach = geode.get();
|
||||
#else
|
||||
osg::Node* toAttach = partsys.get();
|
||||
#endif
|
||||
|
||||
if (rf == osgParticle::ParticleProcessor::RELATIVE_RF)
|
||||
parentNode->addChild(geode);
|
||||
parentNode->addChild(toAttach);
|
||||
else
|
||||
{
|
||||
osg::MatrixTransform* trans = new osg::MatrixTransform;
|
||||
trans->setUpdateCallback(new InverseWorldMatrix);
|
||||
trans->addChild(geode);
|
||||
trans->addChild(toAttach);
|
||||
parentNode->addChild(trans);
|
||||
}
|
||||
}
|
||||
|
@ -957,8 +963,6 @@ namespace NifOsg
|
|||
|
||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, SceneUtil::CompositeStateSetUpdater* composite, const std::vector<int>& boundTextures, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry;
|
||||
for (Nif::ControllerPtr ctrl = triShape->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||
{
|
||||
|
@ -981,21 +985,36 @@ namespace NifOsg
|
|||
|
||||
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
||||
|
||||
#if not(OSG_MIN_VERSION_REQUIRED(3,3,3))
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(geometry);
|
||||
#endif
|
||||
|
||||
if (geometry->getDataVariance() == osg::Object::DYNAMIC)
|
||||
{
|
||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
||||
geometry->setDataVariance(osg::Object::STATIC);
|
||||
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
||||
|
||||
#if not(OSG_MIN_VERSION_REQUIRED(3,3,3))
|
||||
osg::ref_ptr<osg::Geode> geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||
frameswitch->addChild(geode);
|
||||
frameswitch->addChild(geode2);
|
||||
#else
|
||||
osg::ref_ptr<osg::Geometry> geom2 = static_cast<osg::Geometry*>(osg::clone(geometry.get(), osg::CopyOp::DEEP_COPY_NODES|osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||
frameswitch->addChild(geometry);
|
||||
frameswitch->addChild(geom2);
|
||||
#endif
|
||||
|
||||
parentNode->addChild(frameswitch);
|
||||
}
|
||||
else
|
||||
#if not(OSG_MIN_VERSION_REQUIRED(3,3,3))
|
||||
parentNode->addChild(geode);
|
||||
#else
|
||||
parentNode->addChild(geometry);
|
||||
#endif
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
|
||||
|
@ -1056,8 +1075,6 @@ namespace NifOsg
|
|||
void handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, SceneUtil::CompositeStateSetUpdater* composite,
|
||||
const std::vector<int>& boundTextures, int animflags)
|
||||
{
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
|
||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||
triShapeToGeometry(triShape, geometry, parentNode, composite, boundTextures, animflags);
|
||||
|
||||
|
@ -1090,17 +1107,27 @@ namespace NifOsg
|
|||
}
|
||||
rig->setInfluenceMap(map);
|
||||
|
||||
geode->addDrawable(rig);
|
||||
|
||||
// Add a copy, we will alternate between the two copies every other frame using the FrameSwitch
|
||||
// This is so we can set the DataVariance as STATIC, giving a huge performance boost
|
||||
rig->setDataVariance(osg::Object::STATIC);
|
||||
|
||||
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
||||
|
||||
#if not(OSG_MIN_VERSION_REQUIRED(3,3,3))
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(rig);
|
||||
|
||||
osg::Geode* geode2 = static_cast<osg::Geode*>(osg::clone(geode.get(), osg::CopyOp::DEEP_COPY_NODES|
|
||||
osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||
|
||||
osg::ref_ptr<FrameSwitch> frameswitch = new FrameSwitch;
|
||||
frameswitch->addChild(geode);
|
||||
frameswitch->addChild(geode2);
|
||||
#else
|
||||
SceneUtil::RigGeometry* rig2 = static_cast<SceneUtil::RigGeometry*>(osg::clone(rig.get(), osg::CopyOp::DEEP_COPY_NODES|
|
||||
osg::CopyOp::DEEP_COPY_DRAWABLES));
|
||||
frameswitch->addChild(rig);
|
||||
frameswitch->addChild(rig2);
|
||||
#endif
|
||||
|
||||
parentNode->addChild(frameswitch);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <osg/Node>
|
||||
#include <osg/Geode>
|
||||
#include <osg/UserDataContainer>
|
||||
#include <osg/Version>
|
||||
|
||||
#include <osgParticle/ParticleSystem>
|
||||
|
||||
|
@ -32,31 +33,48 @@ namespace
|
|||
{
|
||||
}
|
||||
|
||||
void apply(osg::Node& node)
|
||||
bool isWorldSpaceParticleSystem(osgParticle::ParticleSystem* partsys)
|
||||
{
|
||||
if (osg::Geode* geode = node.asGeode())
|
||||
// HACK: ParticleSystem has no getReferenceFrame()
|
||||
return (partsys->getUserDataContainer()
|
||||
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
|
||||
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace");
|
||||
}
|
||||
|
||||
void apply(osg::Geode& geode)
|
||||
{
|
||||
for (unsigned int i=0;i<geode.getNumDrawables();++i)
|
||||
{
|
||||
for (unsigned int i=0;i<geode->getNumDrawables();++i)
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode.getDrawable(i)))
|
||||
{
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(geode->getDrawable(i)))
|
||||
if (isWorldSpaceParticleSystem(partsys))
|
||||
{
|
||||
// HACK: ParticleSystem has no getReferenceFrame()
|
||||
if (partsys->getUserDataContainer()
|
||||
&& partsys->getUserDataContainer()->getNumDescriptions() > 0
|
||||
&& partsys->getUserDataContainer()->getDescriptions()[0] == "worldspace")
|
||||
{
|
||||
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
|
||||
if (geode->getNumParents() && geode->getParent(0)->getNumParents())
|
||||
transformInitialParticles(partsys, geode->getParent(0)->getParent(0));
|
||||
}
|
||||
geode->setNodeMask(mMask);
|
||||
// HACK: Ignore the InverseWorldMatrix transform the geode is attached to
|
||||
if (geode.getNumParents() && geode.getParent(0)->getNumParents())
|
||||
transformInitialParticles(partsys, geode.getParent(0)->getParent(0));
|
||||
}
|
||||
geode.setNodeMask(mMask);
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
#if OSG_MIN_VERSION_REQUIRED(3,3,3)
|
||||
// in OSG 3.3 and up Drawables can be directly in the scene graph without a Geode decorating them.
|
||||
void apply(osg::Drawable& drw)
|
||||
{
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||
{
|
||||
if (isWorldSpaceParticleSystem(partsys))
|
||||
{
|
||||
// HACK: Ignore the InverseWorldMatrix transform the particle system is attached to
|
||||
if (partsys->getNumParents() && partsys->getParent(0)->getNumParents())
|
||||
transformInitialParticles(partsys, partsys->getParent(0)->getParent(0));
|
||||
}
|
||||
partsys->setNodeMask(mMask);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void transformInitialParticles(osgParticle::ParticleSystem* partsys, osg::Node* node)
|
||||
{
|
||||
osg::MatrixList mats = node->getWorldMatrices();
|
||||
|
|
|
@ -22,11 +22,13 @@ namespace SceneUtil
|
|||
void DisableFreezeOnCullVisitor::apply(osg::Geode &geode)
|
||||
{
|
||||
for (unsigned int i=0; i<geode.getNumDrawables(); ++i)
|
||||
{
|
||||
osg::Drawable* drw = geode.getDrawable(i);
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(drw))
|
||||
partsys->setFreezeOnCull(false);
|
||||
}
|
||||
apply(*geode.getDrawable(i));
|
||||
}
|
||||
|
||||
void DisableFreezeOnCullVisitor::apply(osg::Drawable& drw)
|
||||
{
|
||||
if (osgParticle::ParticleSystem* partsys = dynamic_cast<osgParticle::ParticleSystem*>(&drw))
|
||||
partsys->setFreezeOnCull(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace SceneUtil
|
|||
}
|
||||
|
||||
virtual void apply(osg::Geode &geode);
|
||||
virtual void apply(osg::Drawable& drw);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue