1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-06-25 12:41:33 +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 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();

View file

@ -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;