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:
parent
4631d95739
commit
56eef691a8
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user