|
|
|
@ -94,13 +94,16 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::NIFFilePtr&
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
bool autogenerated = hasAutoGeneratedCollision(node);
|
|
|
|
|
|
|
|
|
|
// files with the name convention xmodel.nif usually have keyframes stored in a separate file xmodel.kf (see Animation::addAnimSource).
|
|
|
|
|
// assume all nodes in the file will be animated
|
|
|
|
|
const bool isAnimated = pathFileNameStartsWithX(nif->getFilename());
|
|
|
|
|
|
|
|
|
|
handleNode(node, 0, autogenerated, isAnimated, autogenerated);
|
|
|
|
|
// If the mesh has RootCollisionNode, attached to actual root node, use it as collision mesh
|
|
|
|
|
const Nif::Node* rootCollisionNode = getCollisionNode(node);
|
|
|
|
|
if (rootCollisionNode)
|
|
|
|
|
handleNode(nif->getFilename(), rootCollisionNode, 0, false, isAnimated, false);
|
|
|
|
|
else
|
|
|
|
|
handleNode(nif->getFilename(), node, 0, true, isAnimated, true);
|
|
|
|
|
|
|
|
|
|
if (mCompoundShape)
|
|
|
|
|
{
|
|
|
|
@ -153,25 +156,34 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node, int flags)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node* rootNode)
|
|
|
|
|
const Nif::Node* BulletNifLoader::getCollisionNode(const Nif::Node* rootNode)
|
|
|
|
|
{
|
|
|
|
|
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(rootNode);
|
|
|
|
|
if(ninode)
|
|
|
|
|
{
|
|
|
|
|
// If root NiNode has only other NiNode as child, consider it as a wrapper, not as actual root node
|
|
|
|
|
const Nif::NodeList &list = ninode->children;
|
|
|
|
|
for(size_t i = 0;i < list.length();i++)
|
|
|
|
|
if (list.length() == 1 &&
|
|
|
|
|
rootNode->recType == Nif::RC_NiNode &&
|
|
|
|
|
list[0].getPtr()->recType == Nif::RC_NiNode)
|
|
|
|
|
{
|
|
|
|
|
if(!list[i].empty())
|
|
|
|
|
{
|
|
|
|
|
if(list[i].getPtr()->recType == Nif::RC_RootCollisionNode)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return getCollisionNode(list[0].getPtr());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for(size_t i = 0; i < list.length(); i++)
|
|
|
|
|
{
|
|
|
|
|
if(list[i].empty())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
const Nif::Node* childNode = list[i].getPtr();
|
|
|
|
|
if(childNode->recType == Nif::RC_RootCollisionNode)
|
|
|
|
|
return childNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|
|
|
|
void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *node, int flags,
|
|
|
|
|
bool isCollisionNode, bool isAnimated, bool autogenerated)
|
|
|
|
|
{
|
|
|
|
|
// Accumulate the flags from all the child nodes. This works for all
|
|
|
|
@ -184,6 +196,9 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|
|
|
|
|
|
|
|
|
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
|
|
|
|
|
|
|
|
|
|
if (node->recType == Nif::RC_RootCollisionNode && autogenerated)
|
|
|
|
|
std::cerr << "Found RootCollisionNode attached to non-root node in " << fileName << ". Treat it as a common NiTriShape." << std::endl;
|
|
|
|
|
|
|
|
|
|
// Don't collide with AvoidNode shapes
|
|
|
|
|
if(node->recType == Nif::RC_AvoidNode)
|
|
|
|
|
flags |= 0x800;
|
|
|
|
@ -212,7 +227,6 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|
|
|
|
// Marker can still have collision if the model explicitely specifies it via a RootCollisionNode.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -235,7 +249,7 @@ void BulletNifLoader::handleNode(const Nif::Node *node, int flags,
|
|
|
|
|
for(size_t i = 0;i < list.length();i++)
|
|
|
|
|
{
|
|
|
|
|
if(!list[i].empty())
|
|
|
|
|
handleNode(list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated);
|
|
|
|
|
handleNode(fileName, list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|