mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-25 18:41:33 +00:00
Use reference type to pass nif node as argument where nullptr is not handled
This commit is contained in:
parent
4631d95739
commit
56eef691a8
2 changed files with 54 additions and 63 deletions
|
@ -18,11 +18,11 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
osg::Matrixf getWorldTransform(const Nif::Node *node)
|
osg::Matrixf getWorldTransform(const Nif::Node& node)
|
||||||
{
|
{
|
||||||
if(node->parent != nullptr)
|
if(node.parent != nullptr)
|
||||||
return node->trafo.toMatrix() * getWorldTransform(node->parent);
|
return node.trafo.toMatrix() * getWorldTransform(*node.parent);
|
||||||
return node->trafo.toMatrix();
|
return node.trafo.toMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pathFileNameStartsWithX(const std::string& path)
|
bool pathFileNameStartsWithX(const std::string& path)
|
||||||
|
@ -99,12 +99,12 @@ void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiGeometry* geometry, const osg::Matrixf &transform = osg::Matrixf())
|
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiGeometry& geometry, const osg::Matrixf &transform = osg::Matrixf())
|
||||||
{
|
{
|
||||||
if (geometry->recType == Nif::RC_NiTriShape || geometry->recType == Nif::RC_BSLODTriShape)
|
if (geometry.recType == Nif::RC_NiTriShape || geometry.recType == Nif::RC_BSLODTriShape)
|
||||||
fillTriangleMesh(mesh, static_cast<const Nif::NiTriShapeData&>(geometry->data.get()), transform);
|
fillTriangleMesh(mesh, static_cast<const Nif::NiTriShapeData&>(geometry.data.get()), transform);
|
||||||
else if (geometry->recType == Nif::RC_NiTriStrips)
|
else if (geometry.recType == Nif::RC_NiTriStrips)
|
||||||
fillTriangleMesh(mesh, static_cast<const Nif::NiTriStripsData&>(geometry->data.get()), transform);
|
fillTriangleMesh(mesh, static_cast<const Nif::NiTriStripsData&>(geometry.data.get()), transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
// Try to find a valid bounding box first. If one's found for any root node, use that.
|
// Try to find a valid bounding box first. If one's found for any root node, use that.
|
||||||
for (const Nif::Node* node : roots)
|
for (const Nif::Node* node : roots)
|
||||||
{
|
{
|
||||||
if (findBoundingBox(node, filename))
|
if (findBoundingBox(*node, filename))
|
||||||
{
|
{
|
||||||
const btVector3 extents = Misc::Convert::toBullet(mShape->mCollisionBox.mExtents);
|
const btVector3 extents = Misc::Convert::toBullet(mShape->mCollisionBox.mExtents);
|
||||||
const btVector3 center = Misc::Convert::toBullet(mShape->mCollisionBox.mCenter);
|
const btVector3 center = Misc::Convert::toBullet(mShape->mCollisionBox.mCenter);
|
||||||
|
@ -164,8 +164,8 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
// from the collision data present in every root node.
|
// from the collision data present in every root node.
|
||||||
for (const Nif::Node* node : roots)
|
for (const Nif::Node* node : roots)
|
||||||
{
|
{
|
||||||
bool autogenerated = hasAutoGeneratedCollision(node);
|
bool autogenerated = hasAutoGeneratedCollision(*node);
|
||||||
handleNode(filename, node, 0, autogenerated, isAnimated, autogenerated);
|
handleNode(filename, *node, 0, autogenerated, isAnimated, autogenerated);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCompoundShape)
|
if (mCompoundShape)
|
||||||
|
@ -198,41 +198,40 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
|
|
||||||
// Find a boundingBox in the node hierarchy.
|
// Find a boundingBox in the node hierarchy.
|
||||||
// Return: use bounding box for collision?
|
// Return: use bounding box for collision?
|
||||||
bool BulletNifLoader::findBoundingBox(const Nif::Node* node, const std::string& filename)
|
bool BulletNifLoader::findBoundingBox(const Nif::Node& node, const std::string& filename)
|
||||||
{
|
{
|
||||||
if (node->hasBounds)
|
if (node.hasBounds)
|
||||||
{
|
{
|
||||||
unsigned int type = node->bounds.type;
|
unsigned int type = node.bounds.type;
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Nif::NiBoundingVolume::Type::BOX_BV:
|
case Nif::NiBoundingVolume::Type::BOX_BV:
|
||||||
mShape->mCollisionBox.mExtents = node->bounds.box.extents;
|
mShape->mCollisionBox.mExtents = node.bounds.box.extents;
|
||||||
mShape->mCollisionBox.mCenter = node->bounds.box.center;
|
mShape->mCollisionBox.mCenter = node.bounds.box.center;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
std::stringstream warning;
|
std::stringstream warning;
|
||||||
warning << "Unsupported NiBoundingVolume type " << type << " in node " << node->recIndex;
|
warning << "Unsupported NiBoundingVolume type " << type << " in node " << node.recIndex;
|
||||||
warning << " in file " << filename;
|
warning << " in file " << filename;
|
||||||
warn(warning.str());
|
warn(warning.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->flags & Nif::NiNode::Flag_BBoxCollision)
|
if (node.flags & Nif::NiNode::Flag_BBoxCollision)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
|
if (const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(&node))
|
||||||
if(ninode)
|
|
||||||
{
|
{
|
||||||
const Nif::NodeList &list = ninode->children;
|
const Nif::NodeList &list = ninode->children;
|
||||||
for(size_t i = 0;i < list.length();i++)
|
for(size_t i = 0;i < list.length();i++)
|
||||||
{
|
{
|
||||||
if(!list[i].empty())
|
if(!list[i].empty())
|
||||||
{
|
{
|
||||||
if (findBoundingBox(list[i].getPtr(), filename))
|
if (findBoundingBox(list[i].get(), filename))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,10 +239,9 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node, const std::string&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node* rootNode)
|
bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node& rootNode)
|
||||||
{
|
{
|
||||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(rootNode);
|
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
|
||||||
if(ninode)
|
|
||||||
{
|
{
|
||||||
const Nif::NodeList &list = ninode->children;
|
const Nif::NodeList &list = ninode->children;
|
||||||
for(size_t i = 0;i < list.length();i++)
|
for(size_t i = 0;i < list.length();i++)
|
||||||
|
@ -258,32 +256,32 @@ bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node* rootNode)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNode(const std::string& fileName, 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, bool avoid)
|
bool isCollisionNode, bool isAnimated, bool autogenerated, bool avoid)
|
||||||
{
|
{
|
||||||
// TODO: allow on-the fly collision switching via toggling this flag
|
// TODO: allow on-the fly collision switching via toggling this flag
|
||||||
if (node->recType == Nif::RC_NiCollisionSwitch && !(node->flags & Nif::NiNode::Flag_ActiveCollision))
|
if (node.recType == Nif::RC_NiCollisionSwitch && !(node.flags & Nif::NiNode::Flag_ActiveCollision))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Accumulate the flags from all the child nodes. This works for all
|
// Accumulate the flags from all the child nodes. This works for all
|
||||||
// the flags we currently use, at least.
|
// the flags we currently use, at least.
|
||||||
flags |= node->flags;
|
flags |= node.flags;
|
||||||
|
|
||||||
if (!node->controller.empty() && node->controller->recType == Nif::RC_NiKeyframeController
|
if (!node.controller.empty() && node.controller->recType == Nif::RC_NiKeyframeController
|
||||||
&& (node->controller->flags & Nif::NiNode::ControllerFlag_Active))
|
&& (node.controller->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
isAnimated = true;
|
isAnimated = true;
|
||||||
|
|
||||||
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
|
isCollisionNode = isCollisionNode || (node.recType == Nif::RC_RootCollisionNode);
|
||||||
|
|
||||||
// Don't collide with AvoidNode shapes
|
// Don't collide with AvoidNode shapes
|
||||||
avoid = avoid || (node->recType == Nif::RC_AvoidNode);
|
avoid = avoid || (node.recType == Nif::RC_AvoidNode);
|
||||||
|
|
||||||
// We encountered a RootCollisionNode inside autogenerated mesh. It is not right.
|
// We encountered a RootCollisionNode inside autogenerated mesh. It is not right.
|
||||||
if (node->recType == Nif::RC_RootCollisionNode && autogenerated)
|
if (node.recType == Nif::RC_RootCollisionNode && autogenerated)
|
||||||
Log(Debug::Info) << "RootCollisionNode is not attached to the root node in " << fileName << ". Treating it as a common NiTriShape.";
|
Log(Debug::Info) << "RootCollisionNode is not attached to the root node in " << fileName << ". Treating it as a common NiTriShape.";
|
||||||
|
|
||||||
// Check for extra data
|
// Check for extra data
|
||||||
for (Nif::ExtraPtr e = node->extra; !e.empty(); e = e->next)
|
for (Nif::ExtraPtr e = node.extra; !e.empty(); e = e->next)
|
||||||
{
|
{
|
||||||
if (e->recType == Nif::RC_NiStringExtraData)
|
if (e->recType == Nif::RC_NiStringExtraData)
|
||||||
{
|
{
|
||||||
|
@ -310,61 +308,58 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n
|
||||||
// NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape!
|
// NOTE: a trishape with hasBounds=true, but no BBoxCollision flag should NOT go through handleNiTriShape!
|
||||||
// It must be ignored completely.
|
// It must be ignored completely.
|
||||||
// (occurs in tr_ex_imp_wall_arch_04.nif)
|
// (occurs in tr_ex_imp_wall_arch_04.nif)
|
||||||
if(!node->hasBounds && (node->recType == Nif::RC_NiTriShape
|
if(!node.hasBounds && (node.recType == Nif::RC_NiTriShape
|
||||||
|| node->recType == Nif::RC_NiTriStrips
|
|| node.recType == Nif::RC_NiTriStrips
|
||||||
|| node->recType == Nif::RC_BSLODTriShape))
|
|| node.recType == Nif::RC_BSLODTriShape))
|
||||||
{
|
{
|
||||||
handleNiTriShape(node, flags, getWorldTransform(node), isAnimated, avoid);
|
handleNiTriShape(node, flags, getWorldTransform(node), isAnimated, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For NiNodes, loop through children
|
// For NiNodes, loop through children
|
||||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
|
if (const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(&node))
|
||||||
if(ninode)
|
|
||||||
{
|
{
|
||||||
const Nif::NodeList &list = ninode->children;
|
const Nif::NodeList &list = ninode->children;
|
||||||
for(size_t i = 0;i < list.length();i++)
|
for(size_t i = 0;i < list.length();i++)
|
||||||
{
|
{
|
||||||
if(!list[i].empty())
|
if(!list[i].empty())
|
||||||
handleNode(fileName, list[i].getPtr(), flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
handleNode(fileName, list[i].get(), flags, isCollisionNode, isAnimated, autogenerated, avoid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, const osg::Matrixf &transform,
|
void BulletNifLoader::handleNiTriShape(const Nif::Node& nifNode, int flags, const osg::Matrixf &transform,
|
||||||
bool isAnimated, bool avoid)
|
bool isAnimated, bool avoid)
|
||||||
{
|
{
|
||||||
assert(nifNode != nullptr);
|
|
||||||
|
|
||||||
// If the object was marked "NCO" earlier, it shouldn't collide with
|
// If the object was marked "NCO" earlier, it shouldn't collide with
|
||||||
// anything. So don't do anything.
|
// anything. So don't do anything.
|
||||||
if ((flags & 0x800))
|
if ((flags & 0x800))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto niGeometry = static_cast<const Nif::NiGeometry*>(nifNode);
|
const Nif::NiGeometry& niGeometry = static_cast<const Nif::NiGeometry&>(nifNode);
|
||||||
if (niGeometry->data.empty() || niGeometry->data->vertices.empty())
|
if (niGeometry.data.empty() || niGeometry.data->vertices.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (niGeometry->recType == Nif::RC_NiTriShape || niGeometry->recType == Nif::RC_BSLODTriShape)
|
if (niGeometry.recType == Nif::RC_NiTriShape || niGeometry.recType == Nif::RC_BSLODTriShape)
|
||||||
{
|
{
|
||||||
if (niGeometry->data->recType != Nif::RC_NiTriShapeData)
|
if (niGeometry.data->recType != Nif::RC_NiTriShapeData)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto data = static_cast<const Nif::NiTriShapeData*>(niGeometry->data.getPtr());
|
auto data = static_cast<const Nif::NiTriShapeData*>(niGeometry.data.getPtr());
|
||||||
if (data->triangles.empty())
|
if (data->triangles.empty())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (niGeometry->recType == Nif::RC_NiTriStrips)
|
else if (niGeometry.recType == Nif::RC_NiTriStrips)
|
||||||
{
|
{
|
||||||
if (niGeometry->data->recType != Nif::RC_NiTriStripsData)
|
if (niGeometry.data->recType != Nif::RC_NiTriStripsData)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometry->data.getPtr());
|
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometry.data.getPtr());
|
||||||
if (data->strips.empty())
|
if (data->strips.empty())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!niGeometry->skin.empty())
|
if (!niGeometry.skin.empty())
|
||||||
isAnimated = false;
|
isAnimated = false;
|
||||||
|
|
||||||
if (isAnimated)
|
if (isAnimated)
|
||||||
|
@ -382,20 +377,16 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
|
||||||
std::unique_ptr<Resource::TriangleMeshShape> childShape(new Resource::TriangleMeshShape(childMesh.get(), true));
|
std::unique_ptr<Resource::TriangleMeshShape> childShape(new Resource::TriangleMeshShape(childMesh.get(), true));
|
||||||
childMesh.release();
|
childMesh.release();
|
||||||
|
|
||||||
float scale = nifNode->trafo.scale;
|
float scale = nifNode.trafo.scale;
|
||||||
const Nif::Node* parent = nifNode;
|
for (const Nif::Node* parent = nifNode.parent; parent != nullptr; parent = parent->parent)
|
||||||
while (parent->parent)
|
|
||||||
{
|
|
||||||
parent = parent->parent;
|
|
||||||
scale *= parent->trafo.scale;
|
scale *= parent->trafo.scale;
|
||||||
}
|
|
||||||
osg::Quat q = transform.getRotate();
|
osg::Quat q = transform.getRotate();
|
||||||
osg::Vec3f v = transform.getTrans();
|
osg::Vec3f v = transform.getTrans();
|
||||||
childShape->setLocalScaling(btVector3(scale, scale, scale));
|
childShape->setLocalScaling(btVector3(scale, scale, scale));
|
||||||
|
|
||||||
btTransform trans(btQuaternion(q.x(), q.y(), q.z(), q.w()), btVector3(v.x(), v.y(), v.z()));
|
btTransform trans(btQuaternion(q.x(), q.y(), q.z(), q.w()), btVector3(v.x(), v.y(), v.z()));
|
||||||
|
|
||||||
mShape->mAnimatedShapes.emplace(nifNode->recIndex, mCompoundShape->getNumChildShapes());
|
mShape->mAnimatedShapes.emplace(nifNode.recIndex, mCompoundShape->getNumChildShapes());
|
||||||
|
|
||||||
mCompoundShape->addChildShape(trans, childShape.get());
|
mCompoundShape->addChildShape(trans, childShape.get());
|
||||||
childShape.release();
|
childShape.release();
|
||||||
|
|
|
@ -52,14 +52,14 @@ public:
|
||||||
osg::ref_ptr<Resource::BulletShape> load(const Nif::File& file);
|
osg::ref_ptr<Resource::BulletShape> load(const Nif::File& file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool findBoundingBox(const Nif::Node* node, const std::string& filename);
|
bool findBoundingBox(const Nif::Node& node, const std::string& filename);
|
||||||
|
|
||||||
void handleNode(const std::string& fileName, Nif::Node const *node, int flags, bool isCollisionNode,
|
void handleNode(const std::string& fileName, const Nif::Node& node, int flags, bool isCollisionNode,
|
||||||
bool isAnimated=false, bool autogenerated=false, bool avoid=false);
|
bool isAnimated=false, bool autogenerated=false, bool avoid=false);
|
||||||
|
|
||||||
bool hasAutoGeneratedCollision(const Nif::Node *rootNode);
|
bool hasAutoGeneratedCollision(const Nif::Node& rootNode);
|
||||||
|
|
||||||
void handleNiTriShape(const Nif::Node *nifNode, int flags, const osg::Matrixf& transform, bool isAnimated, bool avoid);
|
void handleNiTriShape(const Nif::Node& nifNode, int flags, const osg::Matrixf& transform, bool isAnimated, bool avoid);
|
||||||
|
|
||||||
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
|
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue