1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-02-22 11:09:40 +00:00

Merge pull request #2816 from Capostrophic/switchlod

CollisionSwitch and Switch/LOD node fixes
This commit is contained in:
Bret Curtis 2020-05-01 23:49:08 +02:00 committed by GitHub
commit f51476a3c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 30 deletions

View file

@ -170,6 +170,17 @@ namespace NifOsg
class CollisionSwitch : public osg::MatrixTransform class CollisionSwitch : public osg::MatrixTransform
{ {
public: public:
CollisionSwitch() : osg::MatrixTransform()
{
}
CollisionSwitch(const CollisionSwitch& copy, const osg::CopyOp& copyop)
: osg::MatrixTransform(copy, copyop)
{
}
META_Node(NifOsg, CollisionSwitch)
CollisionSwitch(const osg::Matrixf& transformations, bool enabled) : osg::MatrixTransform(transformations) CollisionSwitch(const osg::Matrixf& transformations, bool enabled) : osg::MatrixTransform(transformations)
{ {
setEnabled(enabled); setEnabled(enabled);
@ -478,17 +489,8 @@ namespace NifOsg
osg::ref_ptr<osg::Group> node; osg::ref_ptr<osg::Group> node;
osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED; osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED;
// TODO: it is unclear how to handle transformations of LOD nodes and controllers for them.
switch (nifNode->recType) switch (nifNode->recType)
{ {
case Nif::RC_NiLODNode:
{
const Nif::NiLODNode* niLodNode = static_cast<const Nif::NiLODNode*>(nifNode);
node = handleLodNode(niLodNode);
dataVariance = osg::Object::DYNAMIC;
break;
}
case Nif::RC_NiSwitchNode:
case Nif::RC_NiAutoNormalParticles: case Nif::RC_NiAutoNormalParticles:
case Nif::RC_NiRotatingParticles: case Nif::RC_NiRotatingParticles:
// Leaf nodes in the NIF hierarchy, so won't be able to dynamically attach children. // Leaf nodes in the NIF hierarchy, so won't be able to dynamically attach children.
@ -669,6 +671,11 @@ namespace NifOsg
&& !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC) && !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags); handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
// LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly
// and we need to attach their children to the osg::LOD/osg::Switch nodes
// but we must return that transform to the caller of handleNode instead of the actual LOD/Switch nodes.
osg::ref_ptr<osg::Group> currentNode = node;
if (nifNode->recType == Nif::RC_NiSwitchNode) if (nifNode->recType == Nif::RC_NiSwitchNode)
{ {
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode); const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
@ -679,7 +686,14 @@ namespace NifOsg
else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel)) else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel))
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel); rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel);
node = switchNode; currentNode = switchNode;
}
else if (nifNode->recType == Nif::RC_NiLODNode)
{
const Nif::NiLODNode* niLodNode = static_cast<const Nif::NiLODNode*>(nifNode);
osg::ref_ptr<osg::LOD> lodNode = handleLodNode(niLodNode);
node->addChild(lodNode);
currentNode = lodNode;
} }
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode); const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
@ -689,14 +703,14 @@ namespace NifOsg
for (size_t i = 0; i < effects.length(); ++i) for (size_t i = 0; i < effects.length(); ++i)
{ {
if (!effects[i].empty()) if (!effects[i].empty())
handleEffect(effects[i].getPtr(), node, imageManager); handleEffect(effects[i].getPtr(), currentNode, imageManager);
} }
const Nif::NodeList &children = ninode->children; const Nif::NodeList &children = ninode->children;
for(size_t i = 0;i < children.length();++i) for(size_t i = 0;i < children.length();++i)
{ {
if(!children[i].empty()) if(!children[i].empty())
handleNode(children[i].getPtr(), node, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, isAnimated, textKeys, rootNode); handleNode(children[i].getPtr(), currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, isAnimated, textKeys, rootNode);
} }
} }

View file

@ -735,20 +735,6 @@ bool Optimizer::CombineStaticTransformsVisitor::removeTransforms(osg::Node* node
// RemoveEmptyNodes. // RemoveEmptyNodes.
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Switch& switchNode)
{
// We should keep all switch child nodes since they reflect different switch states.
for (unsigned int i=0; i<switchNode.getNumChildren(); ++i)
traverse(*switchNode.getChild(i));
}
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::LOD& lod)
{
// don't remove any direct children of the LOD because they are used to define each LOD level.
for (unsigned int i=0; i<lod.getNumChildren(); ++i)
traverse(*lod.getChild(i));
}
void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group) void Optimizer::RemoveEmptyNodesVisitor::apply(osg::Group& group)
{ {
if (group.getNumParents()>0) if (group.getNumParents()>0)
@ -787,10 +773,13 @@ void Optimizer::RemoveEmptyNodesVisitor::removeEmptyNodes()
++pitr) ++pitr)
{ {
osg::Group* parent = *pitr; osg::Group* parent = *pitr;
if (!parent->asSwitch() && !dynamic_cast<osg::LOD*>(parent))
{
parent->removeChild(nodeToRemove.get()); parent->removeChild(nodeToRemove.get());
if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent); if (parent->getNumChildren()==0 && isOperationPermissibleForObject(parent)) newEmptyGroups.insert(parent);
} }
} }
}
_redundantNodeList.clear(); _redundantNodeList.clear();
_redundantNodeList.swap(newEmptyGroups); _redundantNodeList.swap(newEmptyGroups);

View file

@ -321,8 +321,6 @@ class Optimizer
BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {} BaseOptimizerVisitor(optimizer, REMOVE_REDUNDANT_NODES) {}
virtual void apply(osg::Group& group); virtual void apply(osg::Group& group);
virtual void apply(osg::LOD& lod);
virtual void apply(osg::Switch& switchNode);
void removeEmptyNodes(); void removeEmptyNodes();

View file

@ -131,6 +131,7 @@ void registerSerializers()
"NifOsg::StaticBoundingBoxCallback", "NifOsg::StaticBoundingBoxCallback",
"NifOsg::GeomMorpherController", "NifOsg::GeomMorpherController",
"NifOsg::UpdateMorphGeometry", "NifOsg::UpdateMorphGeometry",
"NifOsg::CollisionSwitch",
"osgMyGUI::Drawable", "osgMyGUI::Drawable",
"osg::DrawCallback", "osg::DrawCallback",
"osgOQ::ClearQueriesCallback", "osgOQ::ClearQueriesCallback",