You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/components/sceneutil/statesetupdater.cpp

125 lines
3.7 KiB
C++

#include "statesetupdater.hpp"
#include <components/stereo/stereomanager.hpp>
#include <osg/Node>
#include <osg/NodeVisitor>
#include <osgUtil/CullVisitor>
namespace SceneUtil
{
void StateSetUpdater::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
bool isCullVisitor = nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
if (isCullVisitor)
return applyCull(node, static_cast<osgUtil::CullVisitor*>(nv));
else
return applyUpdate(node, nv);
}
void StateSetUpdater::applyUpdate(osg::Node* node, osg::NodeVisitor* nv)
{
if (!mStateSetsUpdate[0])
{
for (int i = 0; i < 2; ++i)
{
mStateSetsUpdate[i] = new osg::StateSet(*node->getOrCreateStateSet(),
osg::CopyOp::SHALLOW_COPY); // Using SHALLOW_COPY for StateAttributes, if users want to modify it is
// their responsibility to set a non-shared one first in setDefaults
setDefaults(mStateSetsUpdate[i]);
}
}
osg::ref_ptr<osg::StateSet> stateset = mStateSetsUpdate[nv->getTraversalNumber() % 2];
apply(stateset, nv);
node->setStateSet(stateset);
traverse(node, nv);
}
void StateSetUpdater::applyCull(osg::Node* node, osgUtil::CullVisitor* cv)
{
auto stateset = getCvDependentStateset(cv);
apply(stateset, cv);
auto* sm = &Stereo::Manager::instance();
if (sm != nullptr)
{
if (sm->getEye(cv) == Stereo::Eye::Left)
applyLeft(stateset, cv);
if (sm->getEye(cv) == Stereo::Eye::Right)
applyRight(stateset, cv);
}
cv->pushStateSet(stateset);
traverse(node, cv);
cv->popStateSet();
}
osg::StateSet* StateSetUpdater::getCvDependentStateset(osgUtil::CullVisitor* cv)
{
auto it = mStateSetsCull.find(cv);
if (it == mStateSetsCull.end())
{
osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
mStateSetsCull.emplace(cv, stateset);
setDefaults(stateset);
return stateset;
}
return it->second;
}
void StateSetUpdater::reset()
{
mStateSetsUpdate[0] = nullptr;
mStateSetsUpdate[1] = nullptr;
mStateSetsCull.clear();
}
StateSetUpdater::StateSetUpdater() {}
StateSetUpdater::StateSetUpdater(const StateSetUpdater& copy, const osg::CopyOp& copyop)
: SceneUtil::NodeCallback<StateSetUpdater>(copy, copyop)
{
}
// ----------------------------------------------------------------------------------
void CompositeStateSetUpdater::apply(osg::StateSet* stateset, osg::NodeVisitor* nv)
{
for (unsigned int i = 0; i < mCtrls.size(); ++i)
mCtrls[i]->apply(stateset, nv);
}
void CompositeStateSetUpdater::setDefaults(osg::StateSet* stateset)
{
for (unsigned int i = 0; i < mCtrls.size(); ++i)
mCtrls[i]->setDefaults(stateset);
}
CompositeStateSetUpdater::CompositeStateSetUpdater() {}
CompositeStateSetUpdater::CompositeStateSetUpdater(const CompositeStateSetUpdater& copy, const osg::CopyOp& copyop)
: StateSetUpdater(copy, copyop)
{
for (unsigned int i = 0; i < copy.mCtrls.size(); ++i)
mCtrls.emplace_back(osg::clone(copy.mCtrls[i].get(), copyop));
}
unsigned int CompositeStateSetUpdater::getNumControllers()
{
return mCtrls.size();
}
StateSetUpdater* CompositeStateSetUpdater::getController(int i)
{
return mCtrls[i];
}
void CompositeStateSetUpdater::addController(StateSetUpdater* ctrl)
{
mCtrls.emplace_back(ctrl);
}
}