mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 12:35:46 +00:00
Streamline node controller handling
Reduce code duplication Allow non-animated nodes controlled by NiVisController to be optimized out
This commit is contained in:
parent
89a2c69a61
commit
fc9a10ba48
@ -512,17 +512,9 @@ namespace NifOsg
|
|||||||
// This takes advantage of the fact root nodes can't have additional controllers
|
// This takes advantage of the fact root nodes can't have additional controllers
|
||||||
// loaded from an external .kf file (original engine just throws "can't find node" errors if you try).
|
// loaded from an external .kf file (original engine just throws "can't find node" errors if you try).
|
||||||
if (!nifNode->parent && nifNode->controller.empty() && nifNode->trafo.isIdentity())
|
if (!nifNode->parent && nifNode->controller.empty() && nifNode->trafo.isIdentity())
|
||||||
{
|
|
||||||
node = new osg::Group;
|
node = new osg::Group;
|
||||||
dataVariance = osg::Object::STATIC;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dataVariance = (nifNode->controller.empty() ? osg::Object::STATIC : osg::Object::DYNAMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nifNode->isBone)
|
dataVariance = nifNode->isBone ? osg::Object::DYNAMIC : osg::Object::STATIC;
|
||||||
dataVariance = osg::Object::DYNAMIC;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -535,7 +527,7 @@ namespace NifOsg
|
|||||||
}
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::ImageManager* imageManager,
|
||||||
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool isAnimated, TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
|
std::vector<unsigned int> boundTextures, int animflags, bool skipMeshes, bool hasMarkers, bool hasAnimatedParents, TextKeyMap* textKeys, osg::Node* rootNode=nullptr)
|
||||||
{
|
{
|
||||||
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
if (rootNode != nullptr && Misc::StringUtils::ciEqual(nifNode->name, "Bounding Box"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -547,9 +539,6 @@ namespace NifOsg
|
|||||||
node->addCullCallback(new BillboardCallback);
|
node->addCullCallback(new BillboardCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nifNode->controller.empty() && nifNode->controller->recType == Nif::RC_NiKeyframeController)
|
|
||||||
isAnimated = true;
|
|
||||||
|
|
||||||
node->setName(nifNode->name);
|
node->setName(nifNode->name);
|
||||||
|
|
||||||
if (parentNode)
|
if (parentNode)
|
||||||
@ -619,16 +608,6 @@ namespace NifOsg
|
|||||||
node->setNodeMask(Loader::getHiddenNodeMask());
|
node->setNodeMask(Loader::getHiddenNodeMask());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((skipMeshes || hasMarkers) && isAnimated) // make sure the empty node is not optimized away so the physicssystem can find it.
|
|
||||||
{
|
|
||||||
node->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((nifNode->recType == Nif::RC_NiTriShape || nifNode->recType == Nif::RC_NiTriStrips) && isAnimated) // Same thing for animated shapes
|
|
||||||
{
|
|
||||||
node->setDataVariance(osg::Object::DYNAMIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
|
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
|
||||||
|
|
||||||
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
|
applyNodeProperties(nifNode, node, composite, imageManager, boundTextures, animflags);
|
||||||
@ -660,9 +639,12 @@ namespace NifOsg
|
|||||||
if (composite->getNumControllers() > 0)
|
if (composite->getNumControllers() > 0)
|
||||||
node->addUpdateCallback(composite);
|
node->addUpdateCallback(composite);
|
||||||
|
|
||||||
if (nifNode->recType != Nif::RC_NiTriShape && nifNode->recType != Nif::RC_NiTriStrips
|
bool isAnimated = false;
|
||||||
&& !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
|
handleNodeControllers(nifNode, node, animflags, isAnimated);
|
||||||
handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
|
hasAnimatedParents |= isAnimated;
|
||||||
|
// Make sure empty nodes are not optimized away so the physics system can find them.
|
||||||
|
if (isAnimated || (hasAnimatedParents && (skipMeshes || hasMarkers)))
|
||||||
|
node->setDataVariance(osg::Object::DYNAMIC);
|
||||||
|
|
||||||
// LOD and Switch nodes must be wrapped by a transform (the current node) to support transformations properly
|
// 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
|
// and we need to attach their children to the osg::LOD/osg::Switch nodes
|
||||||
@ -703,7 +685,7 @@ namespace NifOsg
|
|||||||
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(), currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, isAnimated, textKeys, rootNode);
|
handleNode(children[i].getPtr(), currentNode, imageManager, boundTextures, animflags, skipMeshes, hasMarkers, hasAnimatedParents, textKeys, rootNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,40 +716,10 @@ namespace NifOsg
|
|||||||
setupController(niuvctrl, uvctrl, animflags);
|
setupController(niuvctrl, uvctrl, animflags);
|
||||||
composite->addController(uvctrl);
|
composite->addController(uvctrl);
|
||||||
}
|
}
|
||||||
else if (ctrl->recType == Nif::RC_NiKeyframeController)
|
|
||||||
{
|
|
||||||
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
|
|
||||||
if(!key->data.empty())
|
|
||||||
{
|
|
||||||
osg::ref_ptr<KeyframeController> callback(new KeyframeController(key->data.getPtr()));
|
|
||||||
|
|
||||||
setupController(key, callback, animflags);
|
|
||||||
node->addUpdateCallback(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctrl->recType == Nif::RC_NiPathController)
|
|
||||||
{
|
|
||||||
const Nif::NiPathController *path = static_cast<const Nif::NiPathController*>(ctrl.getPtr());
|
|
||||||
if (!path->posData.empty() && !path->floatData.empty())
|
|
||||||
{
|
|
||||||
osg::ref_ptr<PathController> callback(new PathController(path));
|
|
||||||
|
|
||||||
setupController(path, callback, animflags);
|
|
||||||
node->addUpdateCallback(callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ctrl->recType == Nif::RC_NiVisController)
|
|
||||||
{
|
|
||||||
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), node, animflags);
|
|
||||||
}
|
|
||||||
else if(ctrl->recType == Nif::RC_NiGeomMorpherController)
|
|
||||||
{} // handled in handleTriShape
|
|
||||||
else
|
|
||||||
Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleNodeControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, int animflags)
|
void handleNodeControllers(const Nif::Node* nifNode, osg::Node* node, int animflags, bool& isAnimated)
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
@ -776,54 +728,52 @@ namespace NifOsg
|
|||||||
if (ctrl->recType == Nif::RC_NiKeyframeController)
|
if (ctrl->recType == Nif::RC_NiKeyframeController)
|
||||||
{
|
{
|
||||||
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
|
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
|
||||||
if(!key->data.empty())
|
if (key->data.empty())
|
||||||
{
|
continue;
|
||||||
osg::ref_ptr<KeyframeController> callback(new KeyframeController(key->data.getPtr()));
|
osg::ref_ptr<KeyframeController> callback(new KeyframeController(key->data.getPtr()));
|
||||||
|
|
||||||
setupController(key, callback, animflags);
|
setupController(key, callback, animflags);
|
||||||
transformNode->addUpdateCallback(callback);
|
node->addUpdateCallback(callback);
|
||||||
}
|
isAnimated = true;
|
||||||
}
|
}
|
||||||
else if (ctrl->recType == Nif::RC_NiPathController)
|
else if (ctrl->recType == Nif::RC_NiPathController)
|
||||||
{
|
{
|
||||||
const Nif::NiPathController *path = static_cast<const Nif::NiPathController*>(ctrl.getPtr());
|
const Nif::NiPathController *path = static_cast<const Nif::NiPathController*>(ctrl.getPtr());
|
||||||
if (!path->posData.empty() && !path->floatData.empty())
|
if (path->posData.empty() || path->floatData.empty())
|
||||||
{
|
continue;
|
||||||
osg::ref_ptr<PathController> callback(new PathController(path));
|
osg::ref_ptr<PathController> callback(new PathController(path));
|
||||||
|
|
||||||
setupController(path, callback, animflags);
|
setupController(path, callback, animflags);
|
||||||
transformNode->addUpdateCallback(callback);
|
node->addUpdateCallback(callback);
|
||||||
}
|
isAnimated = true;
|
||||||
}
|
}
|
||||||
else if (ctrl->recType == Nif::RC_NiVisController)
|
else if (ctrl->recType == Nif::RC_NiVisController)
|
||||||
{
|
{
|
||||||
handleVisController(static_cast<const Nif::NiVisController*>(ctrl.getPtr()), transformNode, animflags);
|
const Nif::NiVisController *visctrl = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
|
||||||
}
|
|
||||||
else if (ctrl->recType == Nif::RC_NiRollController)
|
|
||||||
{
|
|
||||||
handleRollController(static_cast<const Nif::NiRollController*>(ctrl.getPtr()), transformNode, animflags);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleVisController(const Nif::NiVisController* visctrl, osg::Node* node, int animflags)
|
|
||||||
{
|
|
||||||
if (visctrl->data.empty())
|
if (visctrl->data.empty())
|
||||||
return;
|
continue;
|
||||||
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr(), Loader::getHiddenNodeMask()));
|
osg::ref_ptr<VisController> callback(new VisController(visctrl->data.getPtr(), Loader::getHiddenNodeMask()));
|
||||||
setupController(visctrl, callback, animflags);
|
setupController(visctrl, callback, animflags);
|
||||||
node->addUpdateCallback(callback);
|
node->addUpdateCallback(callback);
|
||||||
}
|
}
|
||||||
|
else if (ctrl->recType == Nif::RC_NiRollController)
|
||||||
void handleRollController(const Nif::NiRollController* rollctrl, osg::Node* node, int animflags)
|
|
||||||
{
|
{
|
||||||
|
const Nif::NiRollController *rollctrl = static_cast<const Nif::NiRollController*>(ctrl.getPtr());
|
||||||
if (rollctrl->data.empty())
|
if (rollctrl->data.empty())
|
||||||
return;
|
continue;
|
||||||
osg::ref_ptr<RollController> callback(new RollController(rollctrl->data.getPtr()));
|
osg::ref_ptr<RollController> callback(new RollController(rollctrl->data.getPtr()));
|
||||||
setupController(rollctrl, callback, animflags);
|
setupController(rollctrl, callback, animflags);
|
||||||
node->addUpdateCallback(callback);
|
node->addUpdateCallback(callback);
|
||||||
|
isAnimated = true;
|
||||||
|
}
|
||||||
|
else if (ctrl->recType == Nif::RC_NiGeomMorpherController
|
||||||
|
|| ctrl->recType == Nif::RC_NiParticleSystemController
|
||||||
|
|| ctrl->recType == Nif::RC_NiBSPArrayController
|
||||||
|
|| ctrl->recType == Nif::RC_NiUVController)
|
||||||
|
{
|
||||||
|
// These controllers are handled elsewhere
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
void handleMaterialControllers(const Nif::Property *materialProperty, SceneUtil::CompositeStateSetUpdater* composite, int animflags)
|
||||||
@ -1062,8 +1012,6 @@ namespace NifOsg
|
|||||||
continue;
|
continue;
|
||||||
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
|
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
|
||||||
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
|
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
|
||||||
else
|
|
||||||
Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename;
|
|
||||||
}
|
}
|
||||||
if (!partctrl)
|
if (!partctrl)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user