1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-16 18:29:55 +00:00

Add more tests for BulletNifLoader

This commit is contained in:
elsid 2021-10-31 15:19:19 +01:00
parent 523289c531
commit 4631d95739
No known key found for this signature in database
GPG key ID: B845CB9FEE18AB40
2 changed files with 216 additions and 7 deletions

View file

@ -60,6 +60,19 @@ namespace
{
return isNear(lhs.getOrigin(), rhs.getOrigin()) && isNear(lhs.getBasis(), rhs.getBasis());
}
struct WriteVec3f
{
osg::Vec3f mValue;
friend std::ostream& operator <<(std::ostream& stream, const WriteVec3f& value)
{
return stream << "osg::Vec3f {"
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue.x() << ", "
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue.y() << ", "
<< std::setprecision(std::numeric_limits<float>::max_exponent10) << value.mValue.z() << "}";
}
};
}
static std::ostream& operator <<(std::ostream& stream, const btVector3& value)
@ -122,6 +135,17 @@ static std::ostream& operator <<(std::ostream& stream, const TriangleMeshShape&
return stream << "}}";
}
static bool operator ==(const BulletShape::CollisionBox& l, const BulletShape::CollisionBox& r)
{
const auto tie = [] (const BulletShape::CollisionBox& v) { return std::tie(v.mExtents, v.mCenter); };
return tie(l) == tie(r);
}
static std::ostream& operator <<(std::ostream& stream, const BulletShape::CollisionBox& value)
{
return stream << "CollisionBox {" << WriteVec3f {value.mExtents} << ", " << WriteVec3f {value.mCenter} << "}";
}
}
static std::ostream& operator <<(std::ostream& stream, const btCollisionShape& value)
@ -162,8 +186,7 @@ namespace Resource
{
return compareObjects(lhs.mCollisionShape.get(), rhs.mCollisionShape.get())
&& compareObjects(lhs.mAvoidCollisionShape.get(), rhs.mAvoidCollisionShape.get())
&& lhs.mCollisionBox.mExtents == rhs.mCollisionBox.mExtents
&& lhs.mCollisionBox.mCenter == rhs.mCollisionBox.mCenter
&& lhs.mCollisionBox == rhs.mCollisionBox
&& lhs.mAnimatedShapes == rhs.mAnimatedShapes;
}
@ -172,8 +195,7 @@ namespace Resource
return stream << "Resource::BulletShape {"
<< value.mCollisionShape.get() << ", "
<< value.mAvoidCollisionShape.get() << ", "
<< "osg::Vec3f {" << value.mCollisionBox.mExtents << "}" << ", "
<< "osg::Vec3f {" << value.mCollisionBox.mCenter << "}" << ", "
<< value.mCollisionBox << ", "
<< value.mAnimatedShapes
<< "}";
}
@ -272,6 +294,12 @@ namespace
value.recType = Nif::RC_NiTriShape;
}
void init(Nif::NiTriStrips& value)
{
init(static_cast<Nif::NiGeometry&>(value));
value.recType = Nif::RC_NiTriStrips;
}
void init(Nif::NiSkinInstance& value)
{
value.data = Nif::NiSkinDataPtr(nullptr);
@ -330,6 +358,8 @@ namespace
Nif::NiTriShape mNiTriShape;
Nif::NiTriShapeData mNiTriShapeData2;
Nif::NiTriShape mNiTriShape2;
Nif::NiTriStripsData mNiTriStripsData;
Nif::NiTriStrips mNiTriStrips;
Nif::NiSkinInstance mNiSkinInstance;
Nif::NiStringExtraData mNiStringExtraData;
Nif::NiStringExtraData mNiStringExtraData2;
@ -361,6 +391,7 @@ namespace
init(mNiNode3);
init(mNiTriShape);
init(mNiTriShape2);
init(mNiTriStrips);
init(mNiSkinInstance);
init(mNiStringExtraData);
init(mNiStringExtraData2);
@ -375,6 +406,11 @@ namespace
mNiTriShapeData2.vertices = {osg::Vec3f(0, 0, 1), osg::Vec3f(1, 0, 1), osg::Vec3f(1, 1, 1)};
mNiTriShapeData2.triangles = {0, 1, 2};
mNiTriShape2.data = Nif::NiGeometryDataPtr(&mNiTriShapeData2);
mNiTriStripsData.recType = Nif::RC_NiTriStripsData;
mNiTriStripsData.vertices = {osg::Vec3f(0, 0, 0), osg::Vec3f(1, 0, 0), osg::Vec3f(1, 1, 0), osg::Vec3f(0, 1, 0)};
mNiTriStripsData.strips = {{0, 1, 2, 3}};
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
}
};
@ -389,6 +425,18 @@ namespace
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_ignore_nullptr_root)
{
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(nullptr));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default)
{
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
@ -860,6 +908,34 @@ namespace
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_add_static_mesh_to_existing_compound_mesh)
{
mNiTriShape.parent = &mNiNode;
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriShape2));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
const auto result = mLoader.load(mNifFile);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
std::unique_ptr<btTriangleMesh> triangles2(new btTriangleMesh(false));
triangles2->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
std::unique_ptr<btCompoundShape> compound(new btCompoundShape);
compound->addChildShape(btTransform::getIdentity(), new Resource::TriangleMeshShape(triangles.release(), true));
compound->addChildShape(btTransform::getIdentity(), new Resource::TriangleMeshShape(triangles2.release(), true));
Resource::BulletShape expected;
expected.mCollisionShape.reset(compound.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_root_avoid_node_and_tri_shape_child_node_should_return_shape_with_null_collision_shape)
{
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
@ -983,4 +1059,134 @@ namespace
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_ignore_tri_shape_data_with_mismatching_data_rec_type)
{
mNiTriShape.data = Nif::NiGeometryDataPtr(&mNiTriStripsData);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriShape));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
const Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape)
{
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
triangles->addTriangle(btVector3(1, 0, 0), btVector3(0, 1, 0), btVector3(1, 1, 0));
Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true));
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_ignore_tri_strips_data_with_mismatching_data_rec_type)
{
mNiTriStrips.data = Nif::NiGeometryDataPtr(&mNiTriShapeData);
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
const Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_ignore_tri_strips_data_with_empty_strips)
{
mNiTriStripsData.strips.clear();
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
const Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_static_mesh_should_ignore_tri_strips_data_with_less_than_3_strips)
{
mNiTriStripsData.strips.front() = {0, 1};
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
const Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_avoid_collision_mesh_should_ignore_tri_strips_data_with_less_than_3_strips)
{
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
mNiNode.recType = Nif::RC_AvoidNode;
mNiTriStripsData.strips.front() = {0, 1};
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("test.nif"));
const auto result = mLoader.load(mNifFile);
const Resource::BulletShape expected;
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, for_animated_mesh_should_ignore_tri_strips_data_with_less_than_3_strips)
{
mNiTriStripsData.strips.front() = {0, 1};
mNiTriStrips.parent = &mNiNode;
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriStrips)}));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
const auto result = mLoader.load(mNifFile);
Resource::BulletShape expected;
expected.mCollisionShape.reset(new btCompoundShape);
EXPECT_EQ(*result, expected);
}
TEST_F(TestBulletNifLoader, should_not_add_static_mesh_with_no_triangles_to_compound_shape)
{
mNiTriStripsData.strips.front() = {0, 1};
mNiTriShape.parent = &mNiNode;
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(2));
EXPECT_CALL(mNifFile, getRoot(0)).WillOnce(Return(&mNiNode));
EXPECT_CALL(mNifFile, getRoot(1)).WillOnce(Return(&mNiTriStrips));
EXPECT_CALL(mNifFile, getFilename()).WillOnce(Return("xtest.nif"));
const auto result = mLoader.load(mNifFile);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
std::unique_ptr<btCompoundShape> compound(new btCompoundShape);
compound->addChildShape(btTransform::getIdentity(), new Resource::TriangleMeshShape(triangles.release(), true));
Resource::BulletShape expected;
expected.mCollisionShape.reset(compound.release());
expected.mAnimatedShapes = {{-1, 0}};
EXPECT_EQ(*result, expected);
}
}

View file

@ -170,7 +170,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
if (mCompoundShape)
{
if (mStaticMesh)
if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
{
btTransform trans;
trans.setIdentity();
@ -181,13 +181,13 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
}
mShape->mCollisionShape = std::move(mCompoundShape);
}
else if (mStaticMesh)
else if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
{
mShape->mCollisionShape.reset(new Resource::TriangleMeshShape(mStaticMesh.get(), true));
mStaticMesh.release();
}
if (mAvoidStaticMesh)
if (mAvoidStaticMesh != nullptr && mAvoidStaticMesh->getNumTriangles() > 0)
{
mShape->mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false));
mAvoidStaticMesh.release();
@ -376,6 +376,9 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
fillTriangleMesh(*childMesh, niGeometry);
if (childMesh->getNumTriangles() == 0)
return;
std::unique_ptr<Resource::TriangleMeshShape> childShape(new Resource::TriangleMeshShape(childMesh.get(), true));
childMesh.release();