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, 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) 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()); osg::ref_ptr<osg::Group> node = new osg::MatrixTransform(nifNode->trafo.toMatrix());
if (nifNode->recType == Nif::RC_NiBillboardNode)
{
transformNode->addCullCallback(new BillboardCallback);
}
// Set a default DataVariance (used as hint by optimization routines). // Set a default DataVariance (used as hint by optimization routines).
switch (nifNode->recType) switch (nifNode->recType)
@ -429,21 +424,34 @@ namespace NifOsg
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.
// No support for keyframe controllers (just crashes in the original engine). // No support for keyframe controllers (just crashes in the original engine).
transformNode->setDataVariance(osg::Object::STATIC); node->setDataVariance(osg::Object::STATIC);
break; break;
default: default:
// could have new children attached at any time, or added external keyframe controllers from .kf files // 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; 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) if (parentNode)
parentNode->addChild(transformNode); parentNode->addChild(node);
if (!rootNode) if (!rootNode)
rootNode = transformNode; rootNode = node;
// UserData used for a variety of features: // UserData used for a variety of features:
// - finding the correct emitter node for a particle system // - finding the correct emitter node for a particle system
@ -451,7 +459,7 @@ namespace NifOsg
// - finding a random child NiNode in NiBspArrayController // - finding a random child NiNode in NiBspArrayController
// - storing the previous 3x3 rotation and scale values for when a KeyframeController wants to // - storing the previous 3x3 rotation and scale values for when a KeyframeController wants to
// change only certain elements of the 4x4 transform // change only certain elements of the 4x4 transform
transformNode->getOrCreateUserDataContainer()->addUserObject( node->getOrCreateUserDataContainer()->addUserObject(
new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation)); new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation));
for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->extra) for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->extra)
@ -485,7 +493,7 @@ namespace NifOsg
{ {
skipMeshes = true; skipMeshes = true;
// Leave mask for UpdateVisitor enabled // 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 // 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 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 // 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; 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) if (nifNode->recType == Nif::RC_NiTriShape && !skipMeshes)
{ {
const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode); const Nif::NiTriShape* triShape = static_cast<const Nif::NiTriShape*>(nifNode);
if (triShape->skin.empty()) if (triShape->skin.empty())
handleTriShape(triShape, transformNode, composite, boundTextures, animflags); handleTriShape(triShape, node, composite, boundTextures, animflags);
else else
handleSkinnedTriShape(triShape, transformNode, composite, boundTextures, animflags); handleSkinnedTriShape(triShape, node, composite, boundTextures, animflags);
if (!nifNode->controller.empty()) if (!nifNode->controller.empty())
handleMeshControllers(nifNode, composite, boundTextures, animflags); handleMeshControllers(nifNode, composite, boundTextures, animflags);
} }
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles) 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) 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). // 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. // We can take advantage of this constraint for optimizations later.
if (!nifNode->controller.empty()) if (!nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
handleNodeControllers(nifNode, transformNode, animflags); handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
// Optimization pass // Optimization pass
optimize(nifNode, transformNode, skipMeshes); optimize(nifNode, node, skipMeshes);
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode); const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
if(ninode) if(ninode)
@ -542,12 +550,12 @@ namespace NifOsg
{ {
if(!children[i].empty()) 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) void handleMeshControllers(const Nif::Node *nifNode, SceneUtil::CompositeStateSetUpdater* composite, const std::map<int, int> &boundTextures, int animflags)

Loading…
Cancel
Save