Create NIF root nodes as Group instead of Transform when possible

c++11
scrawl 10 years ago
parent b79ab1a3b8
commit d7a4a9fd66

@ -414,12 +414,7 @@ namespace NifOsg
osg::ref_ptr<osg::Node> handleNode(const Nif::Node* nifNode, osg::Group* parentNode, Resource::TextureManager* textureManager,
std::map<int, int> boundTextures, int animflags, int particleflags, bool skipMeshes, TextKeyMap* textKeys, osg::Node* rootNode=NULL)
{
osg::ref_ptr<osg::MatrixTransform> transformNode = new osg::MatrixTransform(nifNode->trafo.toMatrix());
if (nifNode->recType == Nif::RC_NiBillboardNode)
{
transformNode->addCullCallback(new BillboardCallback);
}
osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
// Set a default DataVariance (used as hint by optimization routines).
switch (nifNode->recType)
@ -429,21 +424,34 @@ namespace NifOsg
case Nif::RC_NiRotatingParticles:
// Leaf nodes in the NIF hierarchy, so won't be able to dynamically attach children.
// No support for keyframe controllers (just crashes in the original engine).
transformNode->setDataVariance(osg::Object::STATIC);
node->setDataVariance(osg::Object::STATIC);
break;
default:
// could have new children attached at any time, or added external keyframe controllers from .kf files
transformNode->setDataVariance(osg::Object::DYNAMIC);
node->setDataVariance(osg::Object::DYNAMIC);
break;
}
transformNode->setName(nifNode->name);
if (nifNode->recType == Nif::RC_NiBillboardNode)
{
node->addCullCallback(new BillboardCallback);
}
else if (!rootNode && nifNode->controller.empty() && nifNode->trafo.isIdentity())
{
// The Root node can be created as a Group if no transformation is required.
// 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).
node = new osg::Group;
node->setDataVariance(osg::Object::STATIC);
}
node->setName(nifNode->name);
if (parentNode)
parentNode->addChild(transformNode);
parentNode->addChild(node);
if (!rootNode)
rootNode = transformNode;
rootNode = node;
// UserData used for a variety of features:
// - finding the correct emitter node for a particle system
@ -451,7 +459,7 @@ namespace NifOsg
// - finding a random child NiNode in NiBspArrayController
// - storing the previous 3x3 rotation and scale values for when a KeyframeController wants to
// change only certain elements of the 4x4 transform
transformNode->getOrCreateUserDataContainer()->addUserObject(
node->getOrCreateUserDataContainer()->addUserObject(
new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation));
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->extra)
@ -485,7 +493,7 @@ namespace NifOsg
{
skipMeshes = true;
// Leave mask for UpdateVisitor enabled
transformNode->setNodeMask(0x1);
node->setNodeMask(0x1);
}
// We can skip creating meshes for hidden nodes if they don't have a VisController that
@ -500,39 +508,39 @@ namespace NifOsg
skipMeshes = true; // skip child meshes, but still create the child node hierarchy for animating collision shapes
// now hide this node, but leave the mask for UpdateVisitor enabled so that KeyframeController works
transformNode->setNodeMask(0x1);
node->setNodeMask(0x1);
}
osg::ref_ptr<SceneUtil::CompositeStateSetUpdater> composite = new SceneUtil::CompositeStateSetUpdater;
applyNodeProperties(nifNode, transformNode, composite, textureManager, boundTextures, animflags);
applyNodeProperties(nifNode, node, composite, textureManager, boundTextures, animflags);
if (nifNode->recType == Nif::RC_NiTriShape && !skipMeshes)
{
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
if (triShape->skin.empty())
handleTriShape(triShape, transformNode, composite, boundTextures, animflags);
handleTriShape(triShape, node, composite, boundTextures, animflags);
else
handleSkinnedTriShape(triShape, transformNode, composite, boundTextures, animflags);
handleSkinnedTriShape(triShape, node, composite, boundTextures, animflags);
if (!nifNode->controller.empty())
handleMeshControllers(nifNode, composite, boundTextures, animflags);
}
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
handleParticleSystem(nifNode, transformNode, composite, animflags, particleflags, rootNode);
handleParticleSystem(nifNode, node, composite, animflags, particleflags, rootNode);
if (composite->getNumControllers() > 0)
transformNode->addUpdateCallback(composite);
node->addUpdateCallback(composite);
// Note: NiTriShapes are not allowed to have KeyframeControllers (the vanilla engine just crashes when there is one).
// We can take advantage of this constraint for optimizations later.
if (!nifNode->controller.empty())
handleNodeControllers(nifNode, transformNode, animflags);
if (!nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
// Optimization pass
optimize(nifNode, transformNode, skipMeshes);
optimize(nifNode, node, skipMeshes);
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
if(ninode)
@ -542,12 +550,12 @@ namespace NifOsg
{
if(!children[i].empty())
{
handleNode(children[i].getPtr(), transformNode, textureManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode);
handleNode(children[i].getPtr(), node, textureManager, boundTextures, animflags, particleflags, skipMeshes, textKeys, rootNode);
}
}
}
return transformNode;
return node;
}
void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map<int, int> &boundTextures, int animflags)

Loading…
Cancel
Save