1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-29 04:20:29 +00:00

Use reference type to pass nif node as argument where nullptr is not handled

This commit is contained in:
elsid 2021-10-31 14:23:44 +01:00
parent 4631d95739
commit 56eef691a8
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40
2 changed files with 54 additions and 63 deletions

View File

@ -18,11 +18,11 @@
namespace
{
osg::Matrixf getWorldTransform(const Nif::Node *node)
osg::Matrixf getWorldTransform(const Nif::Node& node)
{
if(node->parent != nullptr)
return node->trafo.toMatrix() * getWorldTransform(node->parent);
return node->trafo.toMatrix();
if(node.parent != nullptr)
return node.trafo.toMatrix() * getWorldTransform(*node.parent);
return node.trafo.toMatrix();
}
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)
fillTriangleMesh(mesh, static_cast<const Nif::NiTriShapeData&>(geometry->data.get()), transform);
else if (geometry->recType == Nif::RC_NiTriStrips)
fillTriangleMesh(mesh, static_cast<const Nif::NiTriStripsData&>(geometry->data.get()), transform);
if (geometry.recType == Nif::RC_NiTriShape || geometry.recType == Nif::RC_BSLODTriShape)
fillTriangleMesh(mesh, static_cast<const Nif::NiTriShapeData&>(geometry.data.get()), transform);
else if (geometry.recType == Nif::RC_NiTriStrips)
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.
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 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.
for (const Nif::Node* node : roots)
{
bool autogenerated = hasAutoGeneratedCollision(node);
handleNode(filename, node, 0, autogenerated, isAnimated, autogenerated);
bool autogenerated = hasAutoGeneratedCollision(*node);
handleNode(filename, *node, 0, autogenerated, isAnimated, autogenerated);
}
if (mCompoundShape)
@ -198,41 +198,40 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
// Find a boundingBox in the node hierarchy.
// 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)
{
case Nif::NiBoundingVolume::Type::BOX_BV:
mShape->mCollisionBox.mExtents = node->bounds.box.extents;
mShape->mCollisionBox.mCenter = node->bounds.box.center;
mShape->mCollisionBox.mExtents = node.bounds.box.extents;
mShape->mCollisionBox.mCenter = node.bounds.box.center;
break;
default:
{
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;
warn(warning.str());
}
}
if (node->flags & Nif::NiNode::Flag_BBoxCollision)
if (node.flags & Nif::NiNode::Flag_BBoxCollision)
{
return true;
}
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
if (const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(&node))
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
{
if(!list[i].empty())
{
if (findBoundingBox(list[i].getPtr(), filename))
if (findBoundingBox(list[i].get(), filename))
return true;
}
}
@ -240,10 +239,9 @@ bool BulletNifLoader::findBoundingBox(const Nif::Node* node, const std::string&
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(ninode)
if (const Nif::NiNode* ninode = dynamic_cast<const Nif::NiNode*>(&rootNode))
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
@ -258,32 +256,32 @@ bool BulletNifLoader::hasAutoGeneratedCollision(const Nif::Node* rootNode)
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)
{
// 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;
// Accumulate the flags from all the child nodes. This works for all
// the flags we currently use, at least.
flags |= node->flags;
flags |= node.flags;
if (!node->controller.empty() && node->controller->recType == Nif::RC_NiKeyframeController
&& (node->controller->flags & Nif::NiNode::ControllerFlag_Active))
if (!node.controller.empty() && node.controller->recType == Nif::RC_NiKeyframeController
&& (node.controller->flags & Nif::NiNode::ControllerFlag_Active))
isAnimated = true;
isCollisionNode = isCollisionNode || (node->recType == Nif::RC_RootCollisionNode);
isCollisionNode = isCollisionNode || (node.recType == Nif::RC_RootCollisionNode);
// 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.
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.";
// 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)
{
@ -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!
// It must be ignored completely.
// (occurs in tr_ex_imp_wall_arch_04.nif)
if(!node->hasBounds && (node->recType == Nif::RC_NiTriShape
|| node->recType == Nif::RC_NiTriStrips
|| node->recType == Nif::RC_BSLODTriShape))
if(!node.hasBounds && (node.recType == Nif::RC_NiTriShape
|| node.recType == Nif::RC_NiTriStrips
|| node.recType == Nif::RC_BSLODTriShape))
{
handleNiTriShape(node, flags, getWorldTransform(node), isAnimated, avoid);
}
}
// For NiNodes, loop through children
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
if (const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(&node))
{
const Nif::NodeList &list = ninode->children;
for(size_t i = 0;i < list.length();i++)
{
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)
{
assert(nifNode != nullptr);
// If the object was marked "NCO" earlier, it shouldn't collide with
// anything. So don't do anything.
if ((flags & 0x800))
return;
auto niGeometry = static_cast<const Nif::NiGeometry*>(nifNode);
if (niGeometry->data.empty() || niGeometry->data->vertices.empty())
const Nif::NiGeometry& niGeometry = static_cast<const Nif::NiGeometry&>(nifNode);
if (niGeometry.data.empty() || niGeometry.data->vertices.empty())
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;
auto data = static_cast<const Nif::NiTriShapeData*>(niGeometry->data.getPtr());
auto data = static_cast<const Nif::NiTriShapeData*>(niGeometry.data.getPtr());
if (data->triangles.empty())
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;
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometry->data.getPtr());
auto data = static_cast<const Nif::NiTriStripsData*>(niGeometry.data.getPtr());
if (data->strips.empty())
return;
}
if (!niGeometry->skin.empty())
if (!niGeometry.skin.empty())
isAnimated = false;
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));
childMesh.release();
float scale = nifNode->trafo.scale;
const Nif::Node* parent = nifNode;
while (parent->parent)
{
parent = parent->parent;
float scale = nifNode.trafo.scale;
for (const Nif::Node* parent = nifNode.parent; parent != nullptr; parent = parent->parent)
scale *= parent->trafo.scale;
}
osg::Quat q = transform.getRotate();
osg::Vec3f v = transform.getTrans();
childShape->setLocalScaling(btVector3(scale, scale, scale));
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());
childShape.release();

View File

@ -52,14 +52,14 @@ public:
osg::ref_ptr<Resource::BulletShape> load(const Nif::File& file);
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 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;