custom class for osgAnimation::RigGeometry, Collada animated deforming body parts

just_say_no_to_geode
Nelsson Huotari 2 years ago committed by psi29a
parent e5e6645575
commit 334c6dde0b

@ -140,6 +140,7 @@
Feature #5198: Implement "Magic effect expired" event
Feature #5454: Clear active spells from actor when he disappears from scene
Feature #5489: MCP: Telekinesis fix for activators
Feature #5701: Convert osgAnimation::RigGeometry to double-buffered custom version
Feature #5737: Handle instance move from one cell to another
Feature #5996: Support Lua scripts in OpenMW
Feature #6017: Separate persistent and temporary cell references when saving

@ -24,6 +24,7 @@
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/settings/settings.hpp>
#include <components/misc/rng.hpp>
@ -244,6 +245,8 @@ namespace MWRender
if (dynamic_cast<const osgParticle::ParticleSystem*>(drawable))
return nullptr;
if (dynamic_cast<const SceneUtil::OsgaRigGeometry*>(drawable))
return nullptr;
if (const SceneUtil::RigGeometry* rig = dynamic_cast<const SceneUtil::RigGeometry*>(drawable))
return operator()(rig->getSourceGeometry());
if (const SceneUtil::MorphGeometry* morph = dynamic_cast<const SceneUtil::MorphGeometry*>(drawable))

@ -61,7 +61,7 @@ add_component_dir (sceneutil
clone attach visitor util statesetupdater controller skeleton riggeometry morphgeometry lightcontroller
lightmanager lightutil positionattitudetransform workqueue pathgridutil waterutil writescene serialize optimizer
actorutil detourdebugdraw navmesh agentpath shadow mwshadowtechnique recastmesh shadowsbin osgacontroller rtt
screencapture depth color
screencapture depth color riggeometryosgaextension
)
add_component_dir (nif

@ -4,9 +4,12 @@
#include <filesystem>
#include <osg/AlphaFunc>
#include <osg/Group>
#include <osg/Node>
#include <osg/UserDataContainer>
#include <osgAnimation/RigGeometry>
#include <osgParticle/ParticleSystem>
#include <osgUtil/IncrementalCompileOperation>
@ -35,6 +38,7 @@
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/shader/shadervisitor.hpp>
#include <components/shader/shadermanager.hpp>
@ -226,11 +230,12 @@ namespace Resource
};
// Check Collada extra descriptions
class ColladaAlphaTrickVisitor : public osg::NodeVisitor
class ColladaDescriptionVisitor : public osg::NodeVisitor
{
public:
ColladaAlphaTrickVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
ColladaDescriptionVisitor()
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
mSkeleton(nullptr)
{
}
@ -268,7 +273,6 @@ namespace Resource
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
}
}
/* Check if the <node> has <extra type="Node"> <technique profile="OpenSceneGraph"> <Descriptions> <Description>
correct format for OpenMW: <Description>alphatest mode value MaterialName</Description>
e.g <Description>alphatest GEQUAL 0.8 MyAlphaTestedMaterial</Description> */
@ -299,6 +303,25 @@ namespace Resource
node.getStateSet()->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);
}
}
if (descriptionParts.size() > (0) && descriptionParts.at(0) == "bodypart")
{
SceneUtil::FindByClassVisitor osgaRigFinder("RigGeometryHolder");
node.accept(osgaRigFinder);
for(osg::Node* foundRigNode : osgaRigFinder.mFoundNodes)
{
if (SceneUtil::RigGeometryHolder* rigGeometryHolder = dynamic_cast<SceneUtil::RigGeometryHolder*> (foundRigNode))
mRigGeometryHolders.emplace_back(osg::ref_ptr<SceneUtil::RigGeometryHolder> (rigGeometryHolder));
else Log(Debug::Error) << "Converted RigGeometryHolder is of a wrong type.";
}
if (!mRigGeometryHolders.empty())
{
osgAnimation::RigGeometry::FindNearestParentSkeleton skeletonFinder;
mRigGeometryHolders[0]->accept(skeletonFinder);
if (skeletonFinder._root.valid()) mSkeleton = skeletonFinder._root;
}
}
}
}
@ -306,6 +329,9 @@ namespace Resource
}
private:
std::vector<std::string> mDescriptions;
public:
osgAnimation::Skeleton* mSkeleton; //pointer is valid only if the model is a bodypart, osg::ref_ptr<Skeleton>
std::vector<osg::ref_ptr<SceneUtil::RigGeometryHolder>> mRigGeometryHolders;
};
SceneManager::SceneManager(const VFS::Manager *vfs, Resource::ImageManager* imageManager, Resource::NifFileManager* nifFileManager)
@ -424,7 +450,7 @@ namespace Resource
{
return mLightingMethod;
}
void SceneManager::setConvertAlphaTestToAlphaToCoverage(bool convert)
{
mConvertAlphaTestToAlphaToCoverage = convert;
@ -525,11 +551,55 @@ namespace Resource
if (nameFinder.mFoundNode)
nameFinder.mFoundNode->setNodeMask(hiddenNodeMask);
// Recognize and convert osgAnimation::RigGeometry to OpenMW-optimized type
SceneUtil::FindByClassVisitor rigFinder("RigGeometry");
node->accept(rigFinder);
for(osg::Node* foundRigNode : rigFinder.mFoundNodes)
{
if (foundRigNode->libraryName() == std::string("osgAnimation"))
{
osgAnimation::RigGeometry* foundRigGeometry = static_cast<osgAnimation::RigGeometry*> (foundRigNode);
osg::ref_ptr<SceneUtil::RigGeometryHolder> newRig = new SceneUtil::RigGeometryHolder(*foundRigGeometry, osg::CopyOp::DEEP_COPY_ALL);
if (foundRigGeometry->getStateSet()) newRig->setStateSet(foundRigGeometry->getStateSet());
if (osg::Group* parent = dynamic_cast<osg::Group*> (foundRigGeometry->getParent(0)))
{
parent->removeChild(foundRigGeometry);
parent->addChild(newRig);
}
}
}
if (ext == "dae")
{
// Collada alpha testing
Resource::ColladaAlphaTrickVisitor colladaAlphaTrickVisitor;
node->accept(colladaAlphaTrickVisitor);
Resource::ColladaDescriptionVisitor colladaDescriptionVisitor;
node->accept(colladaDescriptionVisitor);
if (colladaDescriptionVisitor.mSkeleton)
{
if ( osg::Group* group = dynamic_cast<osg::Group*> (node) )
{
group->removeChildren(0, group->getNumChildren());
for (osg::ref_ptr<SceneUtil::RigGeometryHolder> newRiggeometryHolder : colladaDescriptionVisitor.mRigGeometryHolders)
{
osg::ref_ptr<osg::MatrixTransform> backToOriginTrans = new osg::MatrixTransform();
newRiggeometryHolder->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(newRiggeometryHolder->getGeometry(0)));
backToOriginTrans->getOrCreateUserDataContainer()->addUserObject(new TemplateRef(newRiggeometryHolder->getGeometry(0)));
newRiggeometryHolder->setBodyPart(true);
for (int i = 0; i < 2; ++i)
{
if (newRiggeometryHolder->getGeometry(i)) newRiggeometryHolder->getGeometry(i)->setSkeleton(nullptr);
}
backToOriginTrans->addChild(newRiggeometryHolder);
group->addChild(backToOriginTrans);
}
}
}
node->getOrCreateStateSet()->addUniform(new osg::Uniform("emissiveMult", 1.f));
node->getOrCreateStateSet()->addUniform(new osg::Uniform("specStrength", 1.f));

@ -11,6 +11,7 @@
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
namespace SceneUtil
{
@ -41,7 +42,9 @@ namespace SceneUtil
if (const osgParticle::ParticleSystem* partsys = dynamic_cast<const osgParticle::ParticleSystem*>(drawable))
return operator()(partsys);
if (dynamic_cast<const SceneUtil::RigGeometry*>(drawable) || dynamic_cast<const SceneUtil::MorphGeometry*>(drawable) || dynamic_cast<const osgAnimation::RigGeometry*>(drawable) || dynamic_cast<const osgAnimation::MorphGeometry*>(drawable))
if (dynamic_cast<const SceneUtil::RigGeometry*>(drawable) || dynamic_cast<const SceneUtil::MorphGeometry*>(drawable) ||
dynamic_cast<const osgAnimation::RigGeometry*>(drawable) || dynamic_cast<const osgAnimation::MorphGeometry*>(drawable) ||
dynamic_cast<const SceneUtil::RigGeometryHolder*>(drawable))
{
return static_cast<osg::Drawable*>(drawable->clone(*this));
}

@ -0,0 +1,281 @@
#include "riggeometryosgaextension.hpp"
#include <osgAnimation/RigGeometry>
#include <osg/Drawable>
#include <osg/NodeVisitor>
#include <osg/Version>
#include <components/debug/debuglog.hpp>
#include <components/resource/scenemanager.hpp>
namespace SceneUtil
{
OsgaRigGeometry::OsgaRigGeometry() : osgAnimation::RigGeometry()
{
setDataVariance(osg::Object::STATIC);
}
OsgaRigGeometry::OsgaRigGeometry(const osgAnimation::RigGeometry& copy, const osg::CopyOp& copyop) : osgAnimation::RigGeometry(copy, copyop)
{
setDataVariance(osg::Object::STATIC);
}
OsgaRigGeometry::OsgaRigGeometry(const OsgaRigGeometry& copy, const osg::CopyOp& copyop) :
osgAnimation::RigGeometry(copy, copyop)
{
setDataVariance(osg::Object::STATIC);
}
void OsgaRigGeometry::computeMatrixFromRootSkeleton(osg::MatrixList mtxList)
{
if (!_root.valid())
{
Log(Debug::Warning) << "Warning " << className() <<"::computeMatrixFromRootSkeleton if you have this message it means you miss to call buildTransformer(Skeleton* root), or your RigGeometry (" << getName() <<") is not attached to a Skeleton subgraph";
return;
}
osg::Matrix notRoot = _root->getMatrix();
_matrixFromSkeletonToGeometry = mtxList[0] * osg::Matrix::inverse(notRoot);
_invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(_matrixFromSkeletonToGeometry);
_needToComputeMatrix = false;
}
RigGeometryHolder::RigGeometryHolder() :
mBackToOrigin(nullptr),
mLastFrameNumber(0),
mIsBodyPart(false)
{
}
RigGeometryHolder::RigGeometryHolder(const RigGeometryHolder& copy, const osg::CopyOp& copyop) :
Drawable(copy, copyop),
mBackToOrigin(copy.mBackToOrigin),
mLastFrameNumber(0),
mIsBodyPart(copy.mIsBodyPart)
{
setUseVertexBufferObjects(true);
if (!copy.getSourceRigGeometry())
{
Log(Debug::Error) << "copy constructor of RigGeometryHolder partially failed (no source RigGeometry)";
return;
}
osg::ref_ptr<OsgaRigGeometry> rigGeometry = new OsgaRigGeometry(*copy.getSourceRigGeometry(), copyop);
setSourceRigGeometry(rigGeometry);
}
RigGeometryHolder::RigGeometryHolder(const osgAnimation::RigGeometry& copy, const osg::CopyOp& copyop) :
mBackToOrigin(nullptr),
mLastFrameNumber(0),
mIsBodyPart(false)
{
setUseVertexBufferObjects(true);
osg::ref_ptr<OsgaRigGeometry> rigGeometry = new OsgaRigGeometry(copy, copyop);
setSourceRigGeometry(rigGeometry);
}
void RigGeometryHolder::setSourceRigGeometry(osg::ref_ptr<OsgaRigGeometry> sourceRigGeometry)
{
for (unsigned int i=0; i<2; ++i)
mGeometry.at(i) = nullptr;
mSourceRigGeometry = sourceRigGeometry;
_boundingBox = mSourceRigGeometry->getComputeBoundingBoxCallback()->computeBound(*mSourceRigGeometry);
_boundingSphere = osg::BoundingSphere(_boundingBox);
for (unsigned int i=0; i<2; ++i)
{
const OsgaRigGeometry& from = *sourceRigGeometry;
// DO NOT COPY AND PASTE THIS CODE. Cloning osg::Geometry without also cloning its contained Arrays is generally unsafe.
// In this specific case the operation is safe under the following two assumptions:
// - When Arrays are removed or replaced in the cloned geometry, the original Arrays in their place must outlive the cloned geometry regardless. (ensured by mSourceRigGeometry, possibly also RigGeometry._geometry)
// - Arrays that we add or replace in the cloned geometry must be explicitely forbidden from reusing BufferObjects of the original geometry.
mGeometry.at(i) = new OsgaRigGeometry(from, osg::CopyOp::SHALLOW_COPY);
mGeometry.at(i)->getOrCreateUserDataContainer()->addUserObject(new Resource::TemplateRef(mSourceRigGeometry));
OsgaRigGeometry& to = *mGeometry.at(i);
to.setSupportsDisplayList(false);
to.setUseVertexBufferObjects(true);
to.setCullingActive(false); // make sure to disable culling since that's handled by this class
to.setDataVariance(osg::Object::STATIC);
to.setNeedToComputeMatrix(true);
// vertices and normals are modified every frame, so we need to deep copy them.
// assign a dedicated VBO to make sure that modifications don't interfere with source geometry's VBO.
osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject);
vbo->setUsage(GL_DYNAMIC_DRAW_ARB);
osg::ref_ptr<osg::Array> vertexArray = static_cast<osg::Array*>(from.getVertexArray()->clone(osg::CopyOp::DEEP_COPY_ALL));
if (vertexArray)
{
vertexArray->setVertexBufferObject(vbo);
to.setVertexArray(vertexArray);
}
if (const osg::Array* normals = from.getNormalArray())
{
osg::ref_ptr<osg::Array> normalArray = static_cast<osg::Array*>(normals->clone(osg::CopyOp::DEEP_COPY_ALL));
if (normalArray)
{
normalArray->setVertexBufferObject(vbo);
to.setNormalArray(normalArray, osg::Array::BIND_PER_VERTEX);
}
}
if (const osg::Vec4Array* tangents = dynamic_cast<const osg::Vec4Array*>(from.getTexCoordArray(7)))
{
osg::ref_ptr<osg::Array> tangentArray = static_cast<osg::Array*>(tangents->clone(osg::CopyOp::DEEP_COPY_ALL));
tangentArray->setVertexBufferObject(vbo);
to.setTexCoordArray(7, tangentArray, osg::Array::BIND_PER_VERTEX);
}
}
}
osg::ref_ptr<OsgaRigGeometry> RigGeometryHolder::getSourceRigGeometry() const
{
return mSourceRigGeometry;
}
void RigGeometryHolder::updateRigGeometry(OsgaRigGeometry* geom, osg::NodeVisitor *nv)
{
if(!geom)
return;
if(!geom->getSkeleton() && !this->getParents().empty())
{
osgAnimation::RigGeometry::FindNearestParentSkeleton finder;
if(this->getParents().size() > 1)
Log(Debug::Warning) << "A RigGeometry should not have multi parent ( " << geom->getName() << " )";
this->getParents()[0]->accept(finder);
if(!finder._root.valid())
{
Log(Debug::Warning) << "A RigGeometry did not find a parent skeleton for RigGeometry ( " << geom->getName() << " )";
return;
}
geom->getRigTransformImplementation()->prepareData(*geom);
geom->setSkeleton(finder._root.get());
}
if(!geom->getSkeleton())
return;
if(geom->getNeedToComputeMatrix())
{
osgAnimation::Skeleton* root = geom->getSkeleton();
if (!root)
{
Log(Debug::Warning) << "Warning: if you have this message it means you miss to call buildTransformer(Skeleton* root), or your RigGeometry is not attached to a Skeleton subgraph";
return;
}
osg::MatrixList mtxList = root->getWorldMatrices(root); //We always assume that RigGeometries have origin at their root
geom->computeMatrixFromRootSkeleton(mtxList);
if (mIsBodyPart && mBackToOrigin) updateBackToOriginTransform(geom);
}
if(geom->getSourceGeometry())
{
osg::Drawable::UpdateCallback * up = dynamic_cast<osg::Drawable::UpdateCallback*>(geom->getSourceGeometry()->getUpdateCallback());
if(up)
{
up->update(nv, geom->getSourceGeometry());
}
}
geom->update();
}
OsgaRigGeometry* RigGeometryHolder::getGeometry(int geometry)
{
return mGeometry.at(geometry).get();
}
void RigGeometryHolder::updateBackToOriginTransform(OsgaRigGeometry* geometry)
{
osgAnimation::Skeleton* skeleton = geometry->getSkeleton();
if (skeleton)
{
osg::MatrixList mtxList = mBackToOrigin->getParents()[0]->getWorldMatrices(skeleton);
osg::Matrix skeletonMatrix = skeleton->getMatrix();
osg::Matrixf matrixFromSkeletonToGeometry = mtxList[0] * osg::Matrix::inverse(skeletonMatrix);
osg::Matrixf invMatrixFromSkeletonToGeometry = osg::Matrix::inverse(matrixFromSkeletonToGeometry);
mBackToOrigin->setMatrix(invMatrixFromSkeletonToGeometry);
}
}
void RigGeometryHolder::accept(osg::NodeVisitor &nv)
{
if (!nv.validNodeMask(*this))
return;
nv.pushOntoNodePath(this);
if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR && mSourceRigGeometry.get())
{
unsigned int traversalNumber = nv.getTraversalNumber();
if (mLastFrameNumber == traversalNumber)
{
OsgaRigGeometry& geom = *getRigGeometryPerFrame(mLastFrameNumber);
nv.pushOntoNodePath(&geom);
nv.apply(geom);
nv.popFromNodePath();
}
else
{
mLastFrameNumber = traversalNumber;
OsgaRigGeometry& geom = *getRigGeometryPerFrame(mLastFrameNumber);
if (mIsBodyPart)
{
if (mBackToOrigin) updateBackToOriginTransform(&geom);
else
{
osg::MatrixTransform* matrixTransform = dynamic_cast<osg::MatrixTransform*> (this->getParents()[0]);
if (matrixTransform)
{
mBackToOrigin = matrixTransform;
updateBackToOriginTransform(&geom);
}
}
}
updateRigGeometry(&geom, &nv);
nv.pushOntoNodePath(&geom);
nv.apply(geom);
nv.popFromNodePath();
}
}
else if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
{
}
else
nv.apply(*this);
nv.popFromNodePath();
}
void RigGeometryHolder::accept(osg::PrimitiveFunctor& func) const
{
getRigGeometryPerFrame(mLastFrameNumber)->accept(func);
}
OsgaRigGeometry* RigGeometryHolder::getRigGeometryPerFrame(unsigned int frame) const
{
return mGeometry.at(frame%2).get();
}
}

@ -0,0 +1,72 @@
#ifndef OPENMW_COMPONENTS_OSGAEXTENSION_RIGGEOMETRY_H
#define OPENMW_COMPONENTS_OSGAEXTENSION_RIGGEOMETRY_H
#include <array>
#include <osg/Drawable>
#include <osgAnimation/RigGeometry>
#include <osg/NodeVisitor>
namespace SceneUtil
{
/// @brief Custom RigGeometry-class for osgAnimation-formats (collada)
class OsgaRigGeometry : public osgAnimation::RigGeometry
{
public:
OsgaRigGeometry();
OsgaRigGeometry(const osgAnimation::RigGeometry& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
OsgaRigGeometry(const OsgaRigGeometry& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
META_Object(SceneUtil, OsgaRigGeometry);
void computeMatrixFromRootSkeleton(osg::MatrixList mtxList);
};
/// @brief OpenMW-compatible double buffered static datavariance version of osgAnimation::RigGeometry
/// This class is based on osgAnimation::RigGeometry and SceneUtil::RigGeometry
class RigGeometryHolder : public osg::Drawable
{
public:
RigGeometryHolder();
RigGeometryHolder(const RigGeometryHolder& copy, const osg::CopyOp& copyop);
RigGeometryHolder(const osgAnimation::RigGeometry& copy, const osg::CopyOp& copyop);
META_Object(SceneUtil, RigGeometryHolder);
void setSourceRigGeometry(osg::ref_ptr<OsgaRigGeometry> sourceRigGeometry);
osg::ref_ptr<OsgaRigGeometry> getSourceRigGeometry() const;
/// @brief Modified rig update, code based on osgAnimation::UpdateRigGeometry : public osg::Drawable::UpdateCallback
void updateRigGeometry(OsgaRigGeometry* geom, osg::NodeVisitor *nv);
OsgaRigGeometry* getGeometry(int geometry);
void accept(osg::NodeVisitor &nv) override;
void accept(osg::PrimitiveFunctor&) const override;
bool supports(const osg::PrimitiveFunctor&) const override{ return true; }
void setBackToOrigin(osg::MatrixTransform* backToOrigin) {mBackToOrigin = backToOrigin;}
void setBodyPart(bool isBodyPart) {mIsBodyPart = isBodyPart;}
private:
std::array<osg::ref_ptr<OsgaRigGeometry>, 2> mGeometry;
osg::ref_ptr<OsgaRigGeometry> mSourceRigGeometry;
osg::MatrixTransform* mBackToOrigin; //This is used to move riggeometries from their slot locations to skeleton origin in order to get correct deformations for bodyparts
unsigned int mLastFrameNumber;
bool mIsBodyPart;
void updateBackToOriginTransform(OsgaRigGeometry* geometry);
OsgaRigGeometry* getRigGeometryPerFrame(unsigned int frame) const;
};
}
#endif

@ -8,6 +8,7 @@
#include <components/sceneutil/positionattitudetransform.hpp>
#include <components/sceneutil/skeleton.hpp>
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include <components/sceneutil/morphgeometry.hpp>
namespace SceneUtil
@ -49,6 +50,24 @@ public:
}
};
class RigGeometryHolderSerializer : public osgDB::ObjectWrapper
{
public:
RigGeometryHolderSerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::RigGeometryHolder>, "SceneUtil::RigGeometryHolder", "osg::Object osg::Node osg::Drawable SceneUtil::RigGeometryHolder")
{
}
};
class OsgaRigGeometrySerializer : public osgDB::ObjectWrapper
{
public:
OsgaRigGeometrySerializer()
: osgDB::ObjectWrapper(createInstanceFunc<SceneUtil::OsgaRigGeometry>, "SceneUtil::OsgaRigGeometry", "osg::Object osg::Node osg::Geometry osgAnimation::RigGeometry SceneUtil::OsgaRigGeometry")
{
}
};
class MorphGeometrySerializer : public osgDB::ObjectWrapper
{
public:
@ -108,6 +127,8 @@ void registerSerializers()
mgr->addWrapper(new PositionAttitudeTransformSerializer);
mgr->addWrapper(new SkeletonSerializer);
mgr->addWrapper(new RigGeometrySerializer);
mgr->addWrapper(new RigGeometryHolderSerializer);
mgr->addWrapper(new OsgaRigGeometrySerializer);
mgr->addWrapper(new MorphGeometrySerializer);
mgr->addWrapper(new LightManagerSerializer);
mgr->addWrapper(new CameraRelativeTransformSerializer);

@ -25,6 +25,7 @@
#include <components/sceneutil/riggeometry.hpp>
#include <components/sceneutil/morphgeometry.hpp>
#include <components/sceneutil/depth.hpp>
#include <components/sceneutil/riggeometryosgaextension.hpp>
#include "removedalphafunc.hpp"
#include "shadermanager.hpp"
@ -922,6 +923,17 @@ namespace Shader
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
morph->setSourceGeometry(sourceGeometry);
}
else if (auto osgaRig = dynamic_cast<SceneUtil::RigGeometryHolder*>(&drawable))
{
osg::ref_ptr<SceneUtil::OsgaRigGeometry> sourceOsgaRigGeometry = osgaRig->getSourceRigGeometry();
osg::ref_ptr<osg::Geometry> sourceGeometry = sourceOsgaRigGeometry->getSourceGeometry();
if (sourceGeometry && adjustGeometry(*sourceGeometry, reqs))
{
sourceOsgaRigGeometry->setSourceGeometry(sourceGeometry);
osgaRig->setSourceRigGeometry(sourceOsgaRigGeometry);
}
}
}
else
ensureFFP(drawable);

Loading…
Cancel
Save