1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-19 03:39:58 +00:00

Avoid mesh allocation when data is invalid

This commit is contained in:
elsid 2021-10-31 14:59:35 +01:00
parent 4ac83f4c39
commit 4e8e8304aa
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40
2 changed files with 38 additions and 26 deletions

View File

@ -1159,8 +1159,7 @@ namespace
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif")); EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
const auto result = mLoader.load(mNifFile); const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected; const Resource::BulletShape expected;
expected.mCollisionShape.reset(new btCompoundShape);
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }

View File

@ -1,6 +1,7 @@
#include "bulletnifloader.hpp" #include "bulletnifloader.hpp"
#include <vector> #include <vector>
#include <variant>
#include <BulletCollision/CollisionShapes/btBoxShape.h> #include <BulletCollision/CollisionShapes/btBoxShape.h>
#include <BulletCollision/CollisionShapes/btTriangleMesh.h> #include <BulletCollision/CollisionShapes/btTriangleMesh.h>
@ -99,12 +100,38 @@ void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, co
} }
} }
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiGeometry& geometry, const osg::Matrixf &transform = osg::Matrixf()) template <class Function>
auto handleNiGeometry(const Nif::NiGeometry& geometry, Function&& function)
-> decltype(function(static_cast<const Nif::NiTriShapeData&>(geometry.data.get())))
{ {
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); return function(static_cast<const Nif::NiTriShapeData&>(geometry.data.get()));
else if (geometry.recType == Nif::RC_NiTriStrips)
fillTriangleMesh(mesh, static_cast<const Nif::NiTriStripsData&>(geometry.data.get()), transform); if (geometry.recType == Nif::RC_NiTriStrips)
return function(static_cast<const Nif::NiTriStripsData&>(geometry.data.get()));
return {};
}
std::monostate fillTriangleMesh(std::unique_ptr<btTriangleMesh>& mesh, const Nif::NiGeometry& geometry, const osg::Matrixf &transform)
{
return handleNiGeometry(geometry, [&] (const auto& data)
{
if (mesh == nullptr)
mesh.reset(new btTriangleMesh(false));
fillTriangleMesh(*mesh, data, transform);
return std::monostate {};
});
}
std::unique_ptr<btTriangleMesh> makeChildMesh(const Nif::NiGeometry& geometry)
{
return handleNiGeometry(geometry, [&] (const auto& data)
{
std::unique_ptr<btTriangleMesh> mesh(new btTriangleMesh);
fillTriangleMesh(*mesh, data, osg::Matrixf());
return mesh;
});
} }
} }
@ -369,16 +396,13 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const
if (isAnimated) if (isAnimated)
{ {
std::unique_ptr<btTriangleMesh> childMesh = makeChildMesh(niGeometry);
if (childMesh == nullptr || childMesh->getNumTriangles() == 0)
return;
if (!mCompoundShape) if (!mCompoundShape)
mCompoundShape.reset(new btCompoundShape); mCompoundShape.reset(new btCompoundShape);
std::unique_ptr<btTriangleMesh> childMesh(new btTriangleMesh);
fillTriangleMesh(*childMesh, niGeometry);
if (childMesh->getNumTriangles() == 0)
return;
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();
@ -397,20 +421,9 @@ void BulletNifLoader::handleNiTriShape(const Nif::NiGeometry& niGeometry, const
childShape.release(); childShape.release();
} }
else if (avoid) else if (avoid)
{ fillTriangleMesh(mAvoidStaticMesh, niGeometry, transform);
if (!mAvoidStaticMesh)
mAvoidStaticMesh.reset(new btTriangleMesh(false));
fillTriangleMesh(*mAvoidStaticMesh, niGeometry, transform);
}
else else
{ fillTriangleMesh(mStaticMesh, niGeometry, transform);
if (!mStaticMesh)
mStaticMesh.reset(new btTriangleMesh(false));
// Static shape, just transform all vertices into position
fillTriangleMesh(*mStaticMesh, niGeometry, transform);
}
} }
} // namespace NifBullet } // namespace NifBullet