mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-06 01:41:32 +00:00
Add more tests for BulletNifLoader
This commit is contained in:
parent
523289c531
commit
4631d95739
2 changed files with 216 additions and 7 deletions
|
@ -60,6 +60,19 @@ namespace
|
||||||
{
|
{
|
||||||
return isNear(lhs.getOrigin(), rhs.getOrigin()) && isNear(lhs.getBasis(), rhs.getBasis());
|
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)
|
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 << "}}";
|
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)
|
static std::ostream& operator <<(std::ostream& stream, const btCollisionShape& value)
|
||||||
|
@ -162,8 +186,7 @@ namespace Resource
|
||||||
{
|
{
|
||||||
return compareObjects(lhs.mCollisionShape.get(), rhs.mCollisionShape.get())
|
return compareObjects(lhs.mCollisionShape.get(), rhs.mCollisionShape.get())
|
||||||
&& compareObjects(lhs.mAvoidCollisionShape.get(), rhs.mAvoidCollisionShape.get())
|
&& compareObjects(lhs.mAvoidCollisionShape.get(), rhs.mAvoidCollisionShape.get())
|
||||||
&& lhs.mCollisionBox.mExtents == rhs.mCollisionBox.mExtents
|
&& lhs.mCollisionBox == rhs.mCollisionBox
|
||||||
&& lhs.mCollisionBox.mCenter == rhs.mCollisionBox.mCenter
|
|
||||||
&& lhs.mAnimatedShapes == rhs.mAnimatedShapes;
|
&& lhs.mAnimatedShapes == rhs.mAnimatedShapes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +195,7 @@ namespace Resource
|
||||||
return stream << "Resource::BulletShape {"
|
return stream << "Resource::BulletShape {"
|
||||||
<< value.mCollisionShape.get() << ", "
|
<< value.mCollisionShape.get() << ", "
|
||||||
<< value.mAvoidCollisionShape.get() << ", "
|
<< value.mAvoidCollisionShape.get() << ", "
|
||||||
<< "osg::Vec3f {" << value.mCollisionBox.mExtents << "}" << ", "
|
<< value.mCollisionBox << ", "
|
||||||
<< "osg::Vec3f {" << value.mCollisionBox.mCenter << "}" << ", "
|
|
||||||
<< value.mAnimatedShapes
|
<< value.mAnimatedShapes
|
||||||
<< "}";
|
<< "}";
|
||||||
}
|
}
|
||||||
|
@ -272,6 +294,12 @@ namespace
|
||||||
value.recType = Nif::RC_NiTriShape;
|
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)
|
void init(Nif::NiSkinInstance& value)
|
||||||
{
|
{
|
||||||
value.data = Nif::NiSkinDataPtr(nullptr);
|
value.data = Nif::NiSkinDataPtr(nullptr);
|
||||||
|
@ -330,6 +358,8 @@ namespace
|
||||||
Nif::NiTriShape mNiTriShape;
|
Nif::NiTriShape mNiTriShape;
|
||||||
Nif::NiTriShapeData mNiTriShapeData2;
|
Nif::NiTriShapeData mNiTriShapeData2;
|
||||||
Nif::NiTriShape mNiTriShape2;
|
Nif::NiTriShape mNiTriShape2;
|
||||||
|
Nif::NiTriStripsData mNiTriStripsData;
|
||||||
|
Nif::NiTriStrips mNiTriStrips;
|
||||||
Nif::NiSkinInstance mNiSkinInstance;
|
Nif::NiSkinInstance mNiSkinInstance;
|
||||||
Nif::NiStringExtraData mNiStringExtraData;
|
Nif::NiStringExtraData mNiStringExtraData;
|
||||||
Nif::NiStringExtraData mNiStringExtraData2;
|
Nif::NiStringExtraData mNiStringExtraData2;
|
||||||
|
@ -361,6 +391,7 @@ namespace
|
||||||
init(mNiNode3);
|
init(mNiNode3);
|
||||||
init(mNiTriShape);
|
init(mNiTriShape);
|
||||||
init(mNiTriShape2);
|
init(mNiTriShape2);
|
||||||
|
init(mNiTriStrips);
|
||||||
init(mNiSkinInstance);
|
init(mNiSkinInstance);
|
||||||
init(mNiStringExtraData);
|
init(mNiStringExtraData);
|
||||||
init(mNiStringExtraData2);
|
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.vertices = {osg::Vec3f(0, 0, 1), osg::Vec3f(1, 0, 1), osg::Vec3f(1, 1, 1)};
|
||||||
mNiTriShapeData2.triangles = {0, 1, 2};
|
mNiTriShapeData2.triangles = {0, 1, 2};
|
||||||
mNiTriShape2.data = Nif::NiGeometryDataPtr(&mNiTriShapeData2);
|
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);
|
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)
|
TEST_F(TestBulletNifLoader, for_default_root_nif_node_should_return_default)
|
||||||
{
|
{
|
||||||
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
EXPECT_CALL(mNifFile, numRoots()).WillOnce(Return(1));
|
||||||
|
@ -860,6 +908,34 @@ namespace
|
||||||
EXPECT_EQ(*result, expected);
|
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)
|
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)}));
|
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({Nif::NodePtr(&mNiTriShape)}));
|
||||||
|
@ -983,4 +1059,134 @@ namespace
|
||||||
|
|
||||||
EXPECT_EQ(*result, expected);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
|
|
||||||
if (mCompoundShape)
|
if (mCompoundShape)
|
||||||
{
|
{
|
||||||
if (mStaticMesh)
|
if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
|
||||||
{
|
{
|
||||||
btTransform trans;
|
btTransform trans;
|
||||||
trans.setIdentity();
|
trans.setIdentity();
|
||||||
|
@ -181,13 +181,13 @@ osg::ref_ptr<Resource::BulletShape> BulletNifLoader::load(const Nif::File& nif)
|
||||||
}
|
}
|
||||||
mShape->mCollisionShape = std::move(mCompoundShape);
|
mShape->mCollisionShape = std::move(mCompoundShape);
|
||||||
}
|
}
|
||||||
else if (mStaticMesh)
|
else if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
|
||||||
{
|
{
|
||||||
mShape->mCollisionShape.reset(new Resource::TriangleMeshShape(mStaticMesh.get(), true));
|
mShape->mCollisionShape.reset(new Resource::TriangleMeshShape(mStaticMesh.get(), true));
|
||||||
mStaticMesh.release();
|
mStaticMesh.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mAvoidStaticMesh)
|
if (mAvoidStaticMesh != nullptr && mAvoidStaticMesh->getNumTriangles() > 0)
|
||||||
{
|
{
|
||||||
mShape->mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false));
|
mShape->mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false));
|
||||||
mAvoidStaticMesh.release();
|
mAvoidStaticMesh.release();
|
||||||
|
@ -376,6 +376,9 @@ void BulletNifLoader::handleNiTriShape(const Nif::Node *nifNode, int flags, cons
|
||||||
|
|
||||||
fillTriangleMesh(*childMesh, niGeometry);
|
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();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue