bool Exporter::removeUnreferencedBones(NiNodeRef node) { NiNodeRef parent = node->GetParent(); bool remove = (NULL != parent) && !node->IsSkinInfluence(); Matrix44 ntm = node->GetLocalTransform(); vector<NiAVObjectRef> children = node->GetChildren(); for (vector<NiAVObjectRef>::iterator itr = children.begin(); itr != children.end(); ++itr) { NiAVObjectRef& child = (*itr); bool childRemove = false; if (child->IsDerivedType(NiNode::TYPE)) { childRemove = removeUnreferencedBones(StaticCast<NiNode>(child)); } if (childRemove) { node->RemoveChild(child); } else if (remove) // Reparent abandoned nodes to root { Matrix44 tm = child->GetLocalTransform(); child->SetLocalTransform( ntm * tm ); node->RemoveChild(child); mNiRoot->AddChild(child); } } return remove; }
/*---------------------------------------------------------------------------*/ void NifCollisionUtility::cleanTreeCollision(NiNodeRef pNode) { vector<NiAVObjectRef> srcChildList(pNode->GetChildren()); // children of node // remove collision object (new style [>= Oblivion]) pNode->SetCollisionObject(NULL); // iterate over source nodes and remove possible old-style [Morrowind] collision node for (auto ppIter=srcChildList.begin(), pEnd=srcChildList.end(); ppIter != pEnd; ppIter++) { // RootCollisionNode if (DynamicCast<RootCollisionNode>(*ppIter) != NULL) { pNode->RemoveChild(*ppIter); } // NiNode else if (DynamicCast<NiNode>(*ppIter) != NULL) { cleanTreeCollision(DynamicCast<NiNode>(*ppIter)); } // other children else { (*ppIter)->SetCollisionObject(NULL); } } // for (vector<NiAVObjectRef>::iterator ppIter = srcChildList.begin(); .... }
/*---------------------------------------------------------------------------*/ bool NifCollisionUtility::parseTreeCollision(NiNodeRef pNode, string fileNameCollTmpl, vector<hkGeometry>& geometryMapColl) { vector<NiAVObjectRef> srcChildList (pNode->GetChildren()); // get list of children from input node bool haveCollision(false); // check for own collision object if (DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()) != NULL) { bhkCollisionObjectRef pCollObj(DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject())); bhkRigidBodyRef pRBody (DynamicCast<bhkRigidBody> (pCollObj->GetBody())); // check on valid body if (pRBody != NULL) { array<7, unsigned short> unknown7(pRBody->GetUnknown7Shorts()); // force SKYRIM values unknown7[3] = 0; unknown7[4] = 0; unknown7[5] = 1; unknown7[6] = 65535; pRBody->SetUnknown7Shorts(unknown7); pRBody->SetTranslation(pRBody->GetTranslation() * 0.1f); pRBody->SetShape(parseCollisionShape(fileNameCollTmpl, pRBody->GetShape(), pRBody)); } // if (pRBody != NULL) haveCollision |= true; } // if (DynamicCast<bhkCollisionObject>(pNode->GetCollisionObject()) != NULL) // iterate over source nodes and get geometry for (vector<NiAVObjectRef>::iterator ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++) { // RootCollisionNode if (DynamicCast<RootCollisionNode>(*ppIter) != NULL) { NiNodeRef pRootTemplate(DynamicCast<BSFadeNode>(ReadNifTree((const char*) fileNameCollTmpl.c_str()))); vector<hkGeometry> geometryMapCollLocal; vector<Matrix44> transformAryLocal; // get template if (pRootTemplate != NULL) { bhkCollisionObjectRef pCollNodeTmpl(DynamicCast<bhkCollisionObject>(pRootTemplate->GetCollisionObject())); if (pCollNodeTmpl != NULL) { // get collision data from sub-nodes getGeometryFromNode(&(*DynamicCast<RootCollisionNode>(*ppIter)), geometryMapCollLocal, geometryMapCollLocal, transformAryLocal); // replace collision object pNode->SetCollisionObject(createCollNode(geometryMapCollLocal, pCollNodeTmpl, pNode)); pNode->RemoveChild(*ppIter); haveCollision |= true; } // if (pCollNodeTmpl == NULL) } // if (pRootTemplate != NULL) } // NiNode (and derived classes?) else if (DynamicCast<NiNode>(*ppIter) != NULL) { haveCollision |= parseTreeCollision(DynamicCast<NiNode>(*ppIter), fileNameCollTmpl, geometryMapColl); } } // for (vector<NiAVObjectRef>::iterator ppIter = srcChildList.begin(); ppIter != srcChildList.end(); ppIter++) return haveCollision; }