Merge branch 'bullettime' into 'master'

Don't combine static node collision geometry (bug #6027)

Closes #6027

See merge request OpenMW/openmw!2779
depth-refraction
psi29a 2 years ago
commit 09c784c840

@ -15,6 +15,7 @@
Bug #5870: Disposing of actors who were selected in the console doesn't deselect them like vanilla Bug #5870: Disposing of actors who were selected in the console doesn't deselect them like vanilla
Bug #5883: Immobile creatures don't cause water ripples Bug #5883: Immobile creatures don't cause water ripples
Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load Bug #5977: Fatigueless NPCs' corpse underwater changes animation on game load
Bug #6027: Collisionshape becomes spiderweb-like when the mesh is too complex
Bug #6313: Followers with high Fight can turn hostile Bug #6313: Followers with high Fight can turn hostile
Bug #6427: Enemy health bar disappears before damaging effect ends Bug #6427: Enemy health bar disappears before damaging effect ends
Bug #6550: Cloned body parts don't inherit texture effects Bug #6550: Cloned body parts don't inherit texture effects

@ -586,7 +586,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_tri_shape_root_node_should_return_static_shape)
{ {
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiTriShape); file.mRoots.push_back(&mNiTriShape);
@ -596,14 +596,18 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_tri_shape_root_node_with_bounds_should_return_shape_with_bounds_but_with_null_collision_shape) for_tri_shape_root_node_with_bounds_should_return_static_shape_with_bounds_but_with_null_collision_shape)
{ {
mNiTriShape.hasBounds = true; mNiTriShape.hasBounds = true;
mNiTriShape.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV; mNiTriShape.bounds.type = Nif::NiBoundingVolume::Type::BOX_BV;
@ -623,7 +627,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_should_return_static_shape)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiTriShape) }));
@ -636,13 +640,17 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_nested_tri_shape_child_should_return_static_shape)
{ {
mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) })); mNiNode.children = Nif::NodeList(std::vector<Nif::NodePtr>({ Nif::NodePtr(&mNiNode2) }));
mNiNode2.parents.push_back(&mNiNode); mNiNode2.parents.push_back(&mNiNode);
@ -657,13 +665,17 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_shape_with_triangle_mesh_shape_with_all_meshes) TEST_F(TestBulletNifLoader, for_two_tri_shape_children_should_return_static_shape_with_all_meshes)
{ {
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
mNiTriShape2.parents.push_back(&mNiNode); mNiTriShape2.parents.push_back(&mNiNode);
@ -677,16 +689,22 @@ namespace
const auto result = mLoader.load(file); const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0)); 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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader,
for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_shape_with_triangle_mesh_shape) for_tri_shape_child_node_and_filename_starting_with_x_and_not_empty_skin_should_return_static_shape)
{ {
mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance); mNiTriShape.skin = Nif::NiSkinInstancePtr(&mNiSkinInstance);
mNiTriShape.parents.push_back(&mNiNode); mNiTriShape.parents.push_back(&mNiNode);
@ -700,14 +718,16 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader, for_tri_shape_root_node_and_filename_starting_with_x_should_return_animated_shape)
for_tri_shape_root_node_and_filename_starting_with_x_should_return_shape_with_compound_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
@ -731,8 +751,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader, for_tri_shape_child_node_and_filename_starting_with_x_should_return_animated_shape)
for_tri_shape_child_node_and_filename_starting_with_x_should_return_shape_with_compound_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
@ -759,8 +778,8 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(
for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_shape_with_compound_shape) TestBulletNifLoader, for_two_tri_shape_children_nodes_and_filename_starting_with_x_should_return_animated_shape)
{ {
copy(mTransform, mNiTriShape.trafo); copy(mTransform, mNiTriShape.trafo);
mNiTriShape.trafo.scale = 3; mNiTriShape.trafo.scale = 3;
@ -801,7 +820,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_shape_with_compound_shape) TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_controller_should_return_animated_shape)
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::Controller::Flag_Active; mController.flags |= Nif::Controller::Flag_Active;
@ -831,8 +850,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, TEST_F(TestBulletNifLoader, for_two_tri_shape_children_nodes_where_one_with_controller_should_return_animated_shape)
for_two_tri_shape_children_nodes_where_one_with_controller_should_return_shape_with_compound_shape)
{ {
mController.recType = Nif::RC_NiKeyframeController; mController.recType = Nif::RC_NiKeyframeController;
mController.flags |= Nif::Controller::Flag_Active; mController.flags |= Nif::Controller::Flag_Active;
@ -856,10 +874,9 @@ namespace
const auto result = mLoader.load(file); const auto result = mLoader.load(file);
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false));
triangles->addTriangle( triangles->addTriangle(btVector3(0, 0, 0), btVector3(1, 0, 0), btVector3(1, 1, 0));
btVector3(4, 8, 12), btVector3(16, 8, 12), btVector3(16, 18.5309906005859375, 6.246893405914306640625));
std::unique_ptr<Resource::TriangleMeshShape> mesh(new Resource::TriangleMeshShape(triangles.release(), true)); std::unique_ptr<Resource::TriangleMeshShape> mesh(new Resource::TriangleMeshShape(triangles.release(), true));
mesh->setLocalScaling(btVector3(1, 1, 1)); mesh->setLocalScaling(btVector3(12, 12, 12));
std::unique_ptr<btTriangleMesh> triangles2(new btTriangleMesh(false)); std::unique_ptr<btTriangleMesh> triangles2(new btTriangleMesh(false));
triangles2->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1)); triangles2->addTriangle(btVector3(0, 0, 1), btVector3(1, 0, 1), btVector3(1, 1, 1));
@ -867,11 +884,11 @@ namespace
mesh2->setLocalScaling(btVector3(12, 12, 12)); mesh2->setLocalScaling(btVector3(12, 12, 12));
std::unique_ptr<btCompoundShape> shape(new btCompoundShape); std::unique_ptr<btCompoundShape> shape(new btCompoundShape);
shape->addChildShape(mResultTransform2, mesh.release());
shape->addChildShape(mResultTransform2, mesh2.release()); shape->addChildShape(mResultTransform2, mesh2.release());
shape->addChildShape(btTransform::getIdentity(), mesh.release());
Resource::BulletShape expected; Resource::BulletShape expected;
expected.mCollisionShape.reset(shape.release()); expected.mCollisionShape.reset(shape.release());
expected.mAnimatedShapes = { { -1, 0 } }; expected.mAnimatedShapes = { { -1, 1 } };
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
@ -921,8 +938,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), false)); expected.mAvoidCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
@ -980,8 +1000,12 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
expected.mVisualCollisionType = Resource::VisualCollisionType::Camera; expected.mVisualCollisionType = Resource::VisualCollisionType::Camera;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
@ -1005,8 +1029,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
expected.mVisualCollisionType = Resource::VisualCollisionType::Camera; expected.mVisualCollisionType = Resource::VisualCollisionType::Camera;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
@ -1029,8 +1056,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
expected.mVisualCollisionType = Resource::VisualCollisionType::Default; expected.mVisualCollisionType = Resource::VisualCollisionType::Default;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
@ -1054,8 +1084,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
expected.mVisualCollisionType = Resource::VisualCollisionType::Default; expected.mVisualCollisionType = Resource::VisualCollisionType::Default;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
@ -1085,8 +1118,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
expected.mVisualCollisionType = Resource::VisualCollisionType::Camera; expected.mVisualCollisionType = Resource::VisualCollisionType::Camera;
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
@ -1133,8 +1169,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
@ -1154,7 +1193,7 @@ namespace
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }
TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_shape_with_triangle_mesh_shape) TEST_F(TestBulletNifLoader, for_tri_strips_root_node_should_return_static_shape)
{ {
Nif::NIFFile file("test.nif"); Nif::NIFFile file("test.nif");
file.mRoots.push_back(&mNiTriStrips); file.mRoots.push_back(&mNiTriStrips);
@ -1165,8 +1204,11 @@ namespace
std::unique_ptr<btTriangleMesh> triangles(new btTriangleMesh(false)); 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(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)); triangles->addTriangle(btVector3(1, 0, 0), btVector3(0, 1, 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; Resource::BulletShape expected;
expected.mCollisionShape.reset(new Resource::TriangleMeshShape(triangles.release(), true)); expected.mCollisionShape.reset(compound.release());
EXPECT_EQ(*result, expected); EXPECT_EQ(*result, expected);
} }

@ -40,7 +40,7 @@ namespace
return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X'); return letterPos < path.size() && (path[letterPos] == 'x' || path[letterPos] == 'X');
} }
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data, const osg::Matrixf& transform) void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriShapeData& data)
{ {
const std::vector<osg::Vec3f>& vertices = data.vertices; const std::vector<osg::Vec3f>& vertices = data.vertices;
const std::vector<unsigned short>& triangles = data.triangles; const std::vector<unsigned short>& triangles = data.triangles;
@ -49,13 +49,13 @@ namespace
for (std::size_t i = 0; i < triangles.size(); i += 3) for (std::size_t i = 0; i < triangles.size(); i += 3)
{ {
mesh.addTriangle(Misc::Convert::toBullet(vertices[triangles[i + 0]] * transform), mesh.addTriangle(Misc::Convert::toBullet(vertices[triangles[i + 0]]),
Misc::Convert::toBullet(vertices[triangles[i + 1]] * transform), Misc::Convert::toBullet(vertices[triangles[i + 1]]),
Misc::Convert::toBullet(vertices[triangles[i + 2]] * transform)); Misc::Convert::toBullet(vertices[triangles[i + 2]]));
} }
} }
void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data, const osg::Matrixf& transform) void fillTriangleMesh(btTriangleMesh& mesh, const Nif::NiTriStripsData& data)
{ {
mesh.preallocateVertices(static_cast<int>(data.vertices.size())); mesh.preallocateVertices(static_cast<int>(data.vertices.size()));
mesh.preallocateIndices(static_cast<int>(data.mNumTriangles)); mesh.preallocateIndices(static_cast<int>(data.mNumTriangles));
@ -75,9 +75,9 @@ namespace
c = strip[i]; c = strip[i];
if (a == b || b == c || a == c) if (a == b || b == c || a == c)
continue; continue;
const btVector3 vertexA = Misc::Convert::toBullet(data.vertices[a] * transform); const btVector3 vertexA = Misc::Convert::toBullet(data.vertices[a]);
const btVector3 vertexB = Misc::Convert::toBullet(data.vertices[b] * transform); const btVector3 vertexB = Misc::Convert::toBullet(data.vertices[b]);
const btVector3 vertexC = Misc::Convert::toBullet(data.vertices[c] * transform); const btVector3 vertexC = Misc::Convert::toBullet(data.vertices[c]);
if (i % 2 == 0) if (i % 2 == 0)
mesh.addTriangle(vertexA, vertexB, vertexC); mesh.addTriangle(vertexA, vertexB, vertexC);
else else
@ -117,22 +117,11 @@ namespace
return {}; 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 = std::make_unique<btTriangleMesh>(false);
fillTriangleMesh(*mesh, data, transform);
return std::monostate{};
});
}
std::unique_ptr<btTriangleMesh> makeChildMesh(const Nif::NiGeometry& geometry) std::unique_ptr<btTriangleMesh> makeChildMesh(const Nif::NiGeometry& geometry)
{ {
return handleNiGeometry(geometry, [&](const auto& data) { return handleNiGeometry(geometry, [&](const auto& data) {
auto mesh = std::make_unique<btTriangleMesh>(); auto mesh = std::make_unique<btTriangleMesh>();
fillTriangleMesh(*mesh, data, osg::Matrixf()); fillTriangleMesh(*mesh, data);
return mesh; return mesh;
}); });
} }
@ -147,8 +136,7 @@ namespace NifBullet
mShape = new Resource::BulletShape; mShape = new Resource::BulletShape;
mCompoundShape.reset(); mCompoundShape.reset();
mStaticMesh.reset(); mAvoidCompoundShape.reset();
mAvoidStaticMesh.reset();
mShape->mFileHash = nif.getHash(); mShape->mFileHash = nif.getHash();
@ -208,30 +196,10 @@ namespace NifBullet
} }
if (mCompoundShape) if (mCompoundShape)
{
if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
{
btTransform trans;
trans.setIdentity();
std::unique_ptr<btCollisionShape> child
= std::make_unique<Resource::TriangleMeshShape>(mStaticMesh.get(), true);
mCompoundShape->addChildShape(trans, child.get());
std::ignore = child.release();
std::ignore = mStaticMesh.release();
}
mShape->mCollisionShape = std::move(mCompoundShape); mShape->mCollisionShape = std::move(mCompoundShape);
}
else if (mStaticMesh != nullptr && mStaticMesh->getNumTriangles() > 0)
{
mShape->mCollisionShape.reset(new Resource::TriangleMeshShape(mStaticMesh.get(), true));
std::ignore = mStaticMesh.release();
}
if (mAvoidStaticMesh != nullptr && mAvoidStaticMesh->getNumTriangles() > 0) if (mAvoidCompoundShape)
{ mShape->mAvoidCollisionShape = std::move(mAvoidCompoundShape);
mShape->mAvoidCollisionShape.reset(new Resource::TriangleMeshShape(mAvoidStaticMesh.get(), false));
std::ignore = mAvoidStaticMesh.release();
}
return mShape; return mShape;
} }
@ -409,36 +377,39 @@ namespace NifBullet
if (!niGeometry.skin.empty()) if (!niGeometry.skin.empty())
isAnimated = false; isAnimated = false;
if (isAnimated) std::unique_ptr<btTriangleMesh> childMesh = makeChildMesh(niGeometry);
{ if (childMesh == nullptr || childMesh->getNumTriangles() == 0)
std::unique_ptr<btTriangleMesh> childMesh = makeChildMesh(niGeometry); return;
if (childMesh == nullptr || childMesh->getNumTriangles() == 0)
return;
if (!mCompoundShape)
mCompoundShape.reset(new btCompoundShape);
auto childShape = std::make_unique<Resource::TriangleMeshShape>(childMesh.get(), true); auto childShape = std::make_unique<Resource::TriangleMeshShape>(childMesh.get(), true);
std::ignore = childMesh.release(); std::ignore = childMesh.release();
float scale = niGeometry.trafo.scale; float scale = niGeometry.trafo.scale;
for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent) for (const Nif::Parent* parent = nodeParent; parent != nullptr; parent = parent->mParent)
scale *= parent->mNiNode.trafo.scale; scale *= parent->mNiNode.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(niGeometry.recIndex, mCompoundShape->getNumChildShapes()); if (!avoid)
{
if (!mCompoundShape)
mCompoundShape.reset(new btCompoundShape);
if (isAnimated)
mShape->mAnimatedShapes.emplace(niGeometry.recIndex, mCompoundShape->getNumChildShapes());
mCompoundShape->addChildShape(trans, childShape.get()); mCompoundShape->addChildShape(trans, childShape.get());
std::ignore = childShape.release();
} }
else if (avoid)
fillTriangleMesh(mAvoidStaticMesh, niGeometry, transform);
else else
fillTriangleMesh(mStaticMesh, niGeometry, transform); {
if (!mAvoidCompoundShape)
mAvoidCompoundShape.reset(new btCompoundShape);
mAvoidCompoundShape->addChildShape(trans, childShape.get());
}
std::ignore = childShape.release();
} }
} // namespace NifBullet } // namespace NifBullet

@ -64,10 +64,7 @@ namespace NifBullet
bool isAnimated, bool avoid); bool isAnimated, bool avoid);
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape; std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mCompoundShape;
std::unique_ptr<btCompoundShape, Resource::DeleteCollisionShape> mAvoidCompoundShape;
std::unique_ptr<btTriangleMesh> mStaticMesh;
std::unique_ptr<btTriangleMesh> mAvoidStaticMesh;
osg::ref_ptr<Resource::BulletShape> mShape; osg::ref_ptr<Resource::BulletShape> mShape;
}; };

Loading…
Cancel
Save