From fa23b590a4dee50196190a75ff0926018476b694 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 12 Jul 2018 11:44:11 +0300 Subject: [PATCH] Add unwalkable areas to NavMesh --- apps/openmw/mwphysics/object.cpp | 2 +- apps/openmw/mwworld/scene.cpp | 7 +- apps/openmw/mwworld/worldimp.cpp | 9 ++- .../detournavigator/navigator.cpp | 57 ++++++++++++++ .../detournavigator/recastmeshbuilder.cpp | 76 +++++++++++++++---- .../detournavigator/recastmeshobject.cpp | 30 +++++--- .../cachedrecastmeshmanager.cpp | 12 +-- .../cachedrecastmeshmanager.hpp | 5 +- components/detournavigator/chunkytrimesh.cpp | 16 ++-- components/detournavigator/chunkytrimesh.hpp | 6 +- components/detournavigator/makenavmesh.cpp | 13 ++++ components/detournavigator/navigator.cpp | 52 ++++++++++++- components/detournavigator/navigator.hpp | 18 +++++ components/detournavigator/navmeshmanager.cpp | 13 ++-- components/detournavigator/navmeshmanager.hpp | 6 +- components/detournavigator/recastmesh.cpp | 10 ++- components/detournavigator/recastmesh.hpp | 9 ++- .../detournavigator/recastmeshbuilder.cpp | 32 +++++--- .../detournavigator/recastmeshbuilder.hpp | 11 +-- .../detournavigator/recastmeshmanager.cpp | 11 +-- .../detournavigator/recastmeshmanager.hpp | 5 +- .../detournavigator/recastmeshobject.cpp | 28 ++++--- .../detournavigator/recastmeshobject.hpp | 17 +++-- .../tilecachedrecastmeshmanager.cpp | 12 +-- .../tilecachedrecastmeshmanager.hpp | 5 +- components/resource/bulletshape.cpp | 11 ++- components/resource/bulletshape.hpp | 6 +- 27 files changed, 368 insertions(+), 111 deletions(-) diff --git a/apps/openmw/mwphysics/object.cpp b/apps/openmw/mwphysics/object.cpp index d14f579dd..2f2866821 100644 --- a/apps/openmw/mwphysics/object.cpp +++ b/apps/openmw/mwphysics/object.cpp @@ -40,7 +40,7 @@ namespace MWPhysics void Object::setScale(float scale) { - mShapeInstance->getCollisionShape()->setLocalScaling(btVector3(scale,scale,scale)); + mShapeInstance->setLocalScaling(btVector3(scale, scale, scale)); } void Object::setRotation(const btQuaternion& quat) diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 32c83b95e..bfd21d5e2 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -86,7 +87,11 @@ namespace if (const auto object = physics.getObject(ptr)) { const auto navigator = MWBase::Environment::get().getWorld()->getNavigator(); - navigator->addObject(reinterpret_cast(object), *object->getCollisionObject()->getCollisionShape(), + const DetourNavigator::ObjectShapes shapes { + *object->getShapeInstance()->getCollisionShape(), + object->getShapeInstance()->getAvoidCollisionShape() + }; + navigator->addObject(reinterpret_cast(object), shapes, object->getCollisionObject()->getWorldTransform()); } else if (const auto actor = physics.getActor(ptr)) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 94227a724..a7bda8c0b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -17,6 +18,7 @@ #include +#include #include #include @@ -1544,8 +1546,11 @@ namespace MWWorld bool navigatorObjectsUpdated = false; mPhysics->forEachAnimatedObject([&] (const MWPhysics::Object* object) { - navigatorObjectsUpdated = mNavigator->updateObject(std::size_t(object), - *object->getCollisionObject()->getCollisionShape(), + const DetourNavigator::ObjectShapes shapes { + *object->getShapeInstance()->getCollisionShape(), + object->getShapeInstance()->getAvoidCollisionShape() + }; + navigatorObjectsUpdated = mNavigator->updateObject(std::size_t(object), shapes, object->getCollisionObject()->getWorldTransform()) || navigatorObjectsUpdated; }); if (navigatorObjectsUpdated) diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index de0636ca1..aa7906008 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -358,4 +358,61 @@ namespace osg::Vec3f(215, -215, 1.96328866481781005859375), })) << mPath; } + + TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape) + { + std::array heightfieldData {{ + 0, 0, 0, 0, 0, + 0, -25, -25, -25, -25, + 0, -25, -100, -100, -100, + 0, -25, -100, -100, -100, + 0, -25, -100, -100, -100, + }}; + btHeightfieldTerrainShape shape(5, 5, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false); + shape.setLocalScaling(btVector3(128, 128, 1)); + + std::array heightfieldDataAvoid {{ + -25, -25, -25, -25, -25, + -25, -25, -25, -25, -25, + -25, -25, -25, -25, -25, + -25, -25, -25, -25, -25, + -25, -25, -25, -25, -25, + }}; + btHeightfieldTerrainShape shapeAvoid(5, 5, heightfieldDataAvoid.data(), 1, 0, 0, 2, PHY_FLOAT, false); + shapeAvoid.setLocalScaling(btVector3(128, 128, 1)); + + mNavigator->addAgent(mAgentHalfExtents); + mNavigator->addObject(1, ObjectShapes {shape, &shapeAvoid}, btTransform::getIdentity()); + mNavigator->update(mPlayerPosition); + mNavigator->wait(); + + mNavigator->findPath(mAgentHalfExtents, mStart, mEnd, mOut); + + EXPECT_EQ(mPath, std::deque({ + osg::Vec3f(-215, 215, 1.9393787384033203125), + osg::Vec3f(-200.8159637451171875, 190.47265625, -0.639537751674652099609375), + osg::Vec3f(-186.6319427490234375, 165.9453125, -3.2184507846832275390625), + osg::Vec3f(-172.447906494140625, 141.41796875, -5.797363758087158203125), + osg::Vec3f(-158.263885498046875, 116.8906097412109375, -8.37627887725830078125), + osg::Vec3f(-144.079864501953125, 92.3632659912109375, -10.95519161224365234375), + osg::Vec3f(-129.89581298828125, 67.83591461181640625, -13.534107208251953125), + osg::Vec3f(-115.7117919921875, 43.308563232421875, -16.1130199432373046875), + osg::Vec3f(-101.5277557373046875, 18.7812137603759765625, -18.6919345855712890625), + osg::Vec3f(-87.34372711181640625, -5.7461376190185546875, -20.4680538177490234375), + osg::Vec3f(-67.02922821044921875, -25.4970550537109375, -20.514247894287109375), + osg::Vec3f(-46.714717864990234375, -45.2479705810546875, -20.5604457855224609375), + osg::Vec3f(-26.40021514892578125, -64.99889373779296875, -20.6066417694091796875), + osg::Vec3f(-6.085712432861328125, -84.74980926513671875, -20.652835845947265625), + osg::Vec3f(14.22879505157470703125, -104.50072479248046875, -18.151393890380859375), + osg::Vec3f(39.05098724365234375, -118.16222381591796875, -15.6674861907958984375), + osg::Vec3f(63.87317657470703125, -131.82373046875, -13.18357944488525390625), + osg::Vec3f(88.69537353515625, -145.4852142333984375, -10.69967365264892578125), + osg::Vec3f(113.51757049560546875, -159.146697998046875, -8.21576690673828125), + osg::Vec3f(138.3397674560546875, -172.808197021484375, -5.731858730316162109375), + osg::Vec3f(163.1619720458984375, -186.469696044921875, -3.2479503154754638671875), + osg::Vec3f(187.984161376953125, -200.1311798095703125, -0.764044582843780517578125), + osg::Vec3f(212.8063507080078125, -213.7926788330078125, 1.7198636531829833984375), + osg::Vec3f(215, -215, 1.93937528133392333984375), + })) << mPath; + } } diff --git a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp index a2a47722d..ad0502cb8 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp @@ -40,6 +40,7 @@ namespace const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector()); EXPECT_EQ(recastMesh->getIndices(), std::vector()); + EXPECT_EQ(recastMesh->getFlags(), std::vector()); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_bhv_triangle_mesh_shape) @@ -48,7 +49,7 @@ namespace mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0)); btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, @@ -56,6 +57,7 @@ namespace -1, 0, -1, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_bhv_triangle_mesh_shape) @@ -64,8 +66,11 @@ namespace mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0)); btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), - btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3))); + builder.addObject( + static_cast(shape), + btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), + 1 + ); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 2, 3, 0, @@ -73,6 +78,7 @@ namespace 0, 3, 0, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_heightfield_terrian_shape) @@ -80,7 +86,7 @@ namespace const std::array heightfieldData {{0, 0, 0, 0}}; btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -0.5, 0, -0.5, @@ -91,13 +97,14 @@ namespace 0.5, 0, 0.5, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2, 3, 4, 5})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1, 1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles) { btBoxShape shape(btVector3(1, 1, 2)); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 2, 1, @@ -123,6 +130,7 @@ namespace 7, 6, 4, 4, 5, 7, })); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_compound_shape) @@ -139,7 +147,7 @@ namespace shape.addChildShape(btTransform::getIdentity(), &box); shape.addChildShape(btTransform::getIdentity(), &triangle2); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, @@ -173,6 +181,7 @@ namespace 7, 8, 10, 11, 12, 13, })); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape) @@ -184,7 +193,8 @@ namespace shape.addChildShape(btTransform::getIdentity(), &triangle); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), - btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3))); + btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), + 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 2, 3, 0, @@ -192,6 +202,7 @@ namespace 0, 3, 0, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape_with_transformed_bhv_triangle_shape) @@ -203,8 +214,11 @@ namespace shape.addChildShape(btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), &triangle); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), - btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3))); + builder.addObject( + static_cast(shape), + btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), + 1 + ); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 3, 12, 2, @@ -212,16 +226,17 @@ namespace 1, 12, 2, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } - TEST_F(DetourNavigatorRecastMeshBuilderTest, without_bounds_add_transformed_compound_shape_with_transformed_bhv_triangle_shape_should_not_filter_by_bounds) + TEST_F(DetourNavigatorRecastMeshBuilderTest, without_bounds_add_bhv_triangle_shape_should_not_filter_by_bounds) { btTriangleMesh mesh; mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0)); mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0)); btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 1, 0, -1, @@ -232,9 +247,10 @@ namespace -3, 0, -3, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2, 3, 4, 5})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1, 1})); } - TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_transformed_compound_shape_with_transformed_bhv_triangle_shape_should_filter_by_bounds) + TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_bhv_triangle_shape_should_filter_by_bounds) { mSettings.mRecastScaleFactor = 0.1f; mBounds.mMin = osg::Vec2f(-3, -3) * mSettings.mRecastScaleFactor; @@ -244,7 +260,7 @@ namespace mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0)); btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity()); + builder.addObject(static_cast(shape), btTransform::getIdentity(), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -0.2f, 0, -0.3f, @@ -252,6 +268,7 @@ namespace -0.3f, 0, -0.3f, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_x_bhv_triangle_shape_should_filter_by_bounds) @@ -264,7 +281,7 @@ namespace btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), - btTransform(btQuaternion(btVector3(1, 0, 0), static_cast(-osg::PI_4)))); + btTransform(btQuaternion(btVector3(1, 0, 0), static_cast(-osg::PI_4))), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 0, -0.70710659027099609375, -3.535533905029296875, @@ -272,6 +289,7 @@ namespace 0, 2.384185791015625e-07, -4.24264049530029296875, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_y_bhv_triangle_shape_should_filter_by_bounds) @@ -284,7 +302,7 @@ namespace btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), - btTransform(btQuaternion(btVector3(0, 1, 0), static_cast(osg::PI_4)))); + btTransform(btQuaternion(btVector3(0, 1, 0), static_cast(osg::PI_4))), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ -3.535533905029296875, -0.70710659027099609375, 0, @@ -292,6 +310,7 @@ namespace -4.24264049530029296875, 2.384185791015625e-07, 0, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); } TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_z_bhv_triangle_shape_should_filter_by_bounds) @@ -304,7 +323,7 @@ namespace btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mSettings, mBounds); builder.addObject(static_cast(shape), - btTransform(btQuaternion(btVector3(0, 0, 1), static_cast(osg::PI_4)))); + btTransform(btQuaternion(btVector3(0, 0, 1), static_cast(osg::PI_4))), 1); const auto recastMesh = builder.create(); EXPECT_EQ(recastMesh->getVertices(), std::vector({ 0.707107067108154296875, 0, -3.535533905029296875, @@ -312,5 +331,30 @@ namespace 2.384185791015625e-07, 0, -4.24264049530029296875, })); EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1})); + } + + TEST_F(DetourNavigatorRecastMeshBuilderTest, flags_values_should_be_corresponding_to_added_objects) + { + btTriangleMesh mesh1; + mesh1.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0)); + btBvhTriangleMeshShape shape1(&mesh1, true); + btTriangleMesh mesh2; + mesh2.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0)); + btBvhTriangleMeshShape shape2(&mesh2, true); + RecastMeshBuilder builder(mSettings, mBounds); + builder.addObject(static_cast(shape1), btTransform::getIdentity(), 1); + builder.addObject(static_cast(shape2), btTransform::getIdentity(), 0); + const auto recastMesh = builder.create(); + EXPECT_EQ(recastMesh->getVertices(), std::vector({ + 1, 0, -1, + -1, 0, 1, + -1, 0, -1, + -2, 0, -3, + -3, 0, -2, + -3, 0, -3, + })); + EXPECT_EQ(recastMesh->getIndices(), std::vector({0, 1, 2, 3, 4, 5})); + EXPECT_EQ(recastMesh->getFlags(), std::vector({1, 0})); } } diff --git a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp index b0f03aa65..ba8441c60 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp @@ -26,41 +26,47 @@ namespace TEST_F(DetourNavigatorRecastMeshObjectTest, constructed_object_should_have_shape_and_transform) { - const RecastMeshObject object(mBoxShape, mTransform); + const RecastMeshObject object(mBoxShape, mTransform, 1); EXPECT_EQ(std::addressof(object.getShape()), std::addressof(mBoxShape)); EXPECT_EQ(object.getTransform(), mTransform); } TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_same_transform_for_not_compound_shape_should_return_false) { - RecastMeshObject object(mBoxShape, mTransform); - EXPECT_FALSE(object.update(mTransform)); + RecastMeshObject object(mBoxShape, mTransform, 1); + EXPECT_FALSE(object.update(mTransform, 1)); } TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_different_transform_should_return_true) { - RecastMeshObject object(mBoxShape, mTransform); - EXPECT_TRUE(object.update(btTransform::getIdentity())); + RecastMeshObject object(mBoxShape, mTransform, 1); + EXPECT_TRUE(object.update(btTransform::getIdentity(), 1)); + } + + TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_different_flags_should_return_true) + { + RecastMeshObject object(mBoxShape, mTransform, 1); + EXPECT_TRUE(object.update(mTransform, 2)); } TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_compound_shape_with_same_transform_and_not_changed_child_transform_should_return_false) { - RecastMeshObject object(mCompoundShape, mTransform); - EXPECT_FALSE(object.update(mTransform)); + RecastMeshObject object(mCompoundShape, mTransform, 1); + EXPECT_FALSE(object.update(mTransform, 1)); } TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_compound_shape_with_same_transform_and_changed_child_transform_should_return_true) { - RecastMeshObject object(mCompoundShape, mTransform); + RecastMeshObject object(mCompoundShape, mTransform, 1); mCompoundShape.updateChildTransform(0, btTransform::getIdentity()); - EXPECT_TRUE(object.update(mTransform)); + EXPECT_TRUE(object.update(mTransform, 1)); } TEST_F(DetourNavigatorRecastMeshObjectTest, repeated_update_for_compound_shape_without_changes_should_return_false) { - RecastMeshObject object(mCompoundShape, mTransform); + RecastMeshObject object(mCompoundShape, mTransform, 1); mCompoundShape.updateChildTransform(0, btTransform::getIdentity()); - object.update(mTransform); - EXPECT_FALSE(object.update(mTransform)); + object.update(mTransform, 1); + EXPECT_FALSE(object.update(mTransform, 1)); } } diff --git a/components/detournavigator/cachedrecastmeshmanager.cpp b/components/detournavigator/cachedrecastmeshmanager.cpp index cba3946e0..ce9fe5c51 100644 --- a/components/detournavigator/cachedrecastmeshmanager.cpp +++ b/components/detournavigator/cachedrecastmeshmanager.cpp @@ -5,20 +5,20 @@ namespace DetourNavigator { CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds) : mImpl(settings, bounds) - { - } + {} - bool CachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) + bool CachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, + const btTransform& transform, const unsigned char flags) { - if (!mImpl.addObject(id, shape, transform)) + if (!mImpl.addObject(id, shape, transform, flags)) return false; mCached.reset(); return true; } - bool CachedRecastMeshManager::updateObject(std::size_t id, const btTransform& transform) + bool CachedRecastMeshManager::updateObject(std::size_t id, const btTransform& transform, const unsigned char flags) { - if (!mImpl.updateObject(id, transform)) + if (!mImpl.updateObject(id, transform, flags)) return false; mCached.reset(); return true; diff --git a/components/detournavigator/cachedrecastmeshmanager.hpp b/components/detournavigator/cachedrecastmeshmanager.hpp index 71229ab2f..6f3f2a05a 100644 --- a/components/detournavigator/cachedrecastmeshmanager.hpp +++ b/components/detournavigator/cachedrecastmeshmanager.hpp @@ -12,9 +12,10 @@ namespace DetourNavigator public: CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds); - bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags); - bool updateObject(std::size_t id, const btTransform& transform); + bool updateObject(std::size_t id, const btTransform& transform, const unsigned char flags); boost::optional removeObject(std::size_t id); diff --git a/components/detournavigator/chunkytrimesh.cpp b/components/detournavigator/chunkytrimesh.cpp index cdce8b0e1..f6e257c54 100644 --- a/components/detournavigator/chunkytrimesh.cpp +++ b/components/detournavigator/chunkytrimesh.cpp @@ -13,6 +13,7 @@ namespace DetourNavigator { Rect mBounds; std::ptrdiff_t mOffset; + unsigned char mFlags; }; template @@ -43,9 +44,9 @@ namespace DetourNavigator } void subdivide(std::vector& items, const std::size_t imin, const std::size_t imax, - const std::size_t trisPerChunk, const std::vector& inIndices, + const std::size_t trisPerChunk, const std::vector& inIndices, const std::vector& inFlags, std::size_t& curNode, std::vector& nodes, std::size_t& curTri, - std::vector& outIndices) + std::vector& outIndices, std::vector& outFlags) { const auto inum = imax - imin; const auto icur = curNode; @@ -71,6 +72,7 @@ namespace DetourNavigator inIndices.begin() + items[i].mOffset * 3 + 3, outIndices.begin() + static_cast(curTri) * 3 ); + outFlags[curTri] = inFlags[static_cast(items[i].mOffset)]; curTri++; } } @@ -102,9 +104,9 @@ namespace DetourNavigator const auto isplit = imin + inum / 2; // Left - subdivide(items, imin, isplit, trisPerChunk, inIndices, curNode, nodes, curTri, outIndices); + subdivide(items, imin, isplit, trisPerChunk, inIndices, inFlags, curNode, nodes, curTri, outIndices, outFlags); // Right - subdivide(items, isplit, imax, trisPerChunk, inIndices, curNode, nodes, curTri, outIndices); + subdivide(items, isplit, imax, trisPerChunk, inIndices, inFlags, curNode, nodes, curTri, outIndices, outFlags); const auto iescape = static_cast(curNode) - static_cast(icur); // Negative index means escape. @@ -114,7 +116,7 @@ namespace DetourNavigator } ChunkyTriMesh::ChunkyTriMesh(const std::vector& verts, const std::vector& indices, - const std::size_t trisPerChunk) + const std::vector& flags, const std::size_t trisPerChunk) : mMaxTrisPerChunk(0) { const auto trianglesCount = indices.size() / 3; @@ -126,6 +128,7 @@ namespace DetourNavigator mNodes.resize(nchunks * 4); mIndices.resize(trianglesCount * 3); + mFlags.resize(trianglesCount); // Build tree std::vector items(trianglesCount); @@ -135,6 +138,7 @@ namespace DetourNavigator auto& item = items[i]; item.mOffset = static_cast(i); + item.mFlags = flags[i]; // Calc triangle XZ bounds. const auto baseIndex = static_cast(indices[i * 3]) * 3; @@ -156,7 +160,7 @@ namespace DetourNavigator std::size_t curTri = 0; std::size_t curNode = 0; - subdivide(items, 0, trianglesCount, trisPerChunk, indices, curNode, mNodes, curTri, mIndices); + subdivide(items, 0, trianglesCount, trisPerChunk, indices, flags, curNode, mNodes, curTri, mIndices, mFlags); items.clear(); diff --git a/components/detournavigator/chunkytrimesh.hpp b/components/detournavigator/chunkytrimesh.hpp index bc1898e2f..ddd0b93e6 100644 --- a/components/detournavigator/chunkytrimesh.hpp +++ b/components/detournavigator/chunkytrimesh.hpp @@ -24,6 +24,7 @@ namespace DetourNavigator struct Chunk { const int* const mIndices; + const unsigned char* const mFlags; const std::size_t mSize; }; @@ -40,7 +41,8 @@ namespace DetourNavigator public: /// Creates partitioned triangle mesh (AABB tree), /// where each node contains at max trisPerChunk triangles. - ChunkyTriMesh(const std::vector& verts, const std::vector& tris, std::size_t trisPerChunk); + ChunkyTriMesh(const std::vector& verts, const std::vector& tris, + const std::vector& flags, const std::size_t trisPerChunk); ChunkyTriMesh(const ChunkyTriMesh&) = delete; ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete; @@ -74,6 +76,7 @@ namespace DetourNavigator const auto& node = mNodes[chunkId]; return Chunk { mIndices.data() + node.mOffset * 3, + mFlags.data() + node.mOffset, node.mSize }; } @@ -86,6 +89,7 @@ namespace DetourNavigator private: std::vector mNodes; std::vector mIndices; + std::vector mFlags; std::size_t mMaxTrisPerChunk; }; } diff --git a/components/detournavigator/makenavmesh.cpp b/components/detournavigator/makenavmesh.cpp index c3c12d675..4b77f45b7 100644 --- a/components/detournavigator/makenavmesh.cpp +++ b/components/detournavigator/makenavmesh.cpp @@ -129,6 +129,19 @@ namespace areas.data() ); + for (std::size_t i = 0; i < chunk.mSize; ++i) + areas[i] &= chunk.mFlags[i]; + + rcClearUnwalkableTriangles( + &context, + config.walkableSlopeAngle, + recastMesh.getVertices().data(), + static_cast(recastMesh.getVerticesCount()), + chunk.mIndices, + static_cast(chunk.mSize), + areas.data() + ); + OPENMW_CHECK_DT_RESULT(rcRasterizeTriangles( &context, recastMesh.getVertices().data(), diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigator.cpp index 913ba2e2a..0fc195675 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigator.cpp @@ -2,6 +2,8 @@ #include "debug.hpp" #include "settingsutils.hpp" +#include + namespace DetourNavigator { Navigator::Navigator(const Settings& settings) @@ -27,17 +29,51 @@ namespace DetourNavigator bool Navigator::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) { - return mNavMeshManager.addObject(id, shape, transform); + return mNavMeshManager.addObject(id, shape, transform, RC_WALKABLE_AREA); + } + + bool Navigator::addObject(std::size_t id, const ObjectShapes& shapes, const btTransform& transform) + { + bool result = addObject(id, shapes.mShape, transform); + if (shapes.mAvoid) + { + const auto avoidId = reinterpret_cast(shapes.mAvoid); + if (mNavMeshManager.addObject(avoidId, *shapes.mAvoid, transform, RC_NULL_AREA)) + { + updateAvoidShapeId(id, avoidId); + result = true; + } + } + return result; } bool Navigator::updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) { - return mNavMeshManager.updateObject(id, shape, transform); + return mNavMeshManager.updateObject(id, shape, transform, RC_WALKABLE_AREA); + } + + bool Navigator::updateObject(std::size_t id, const ObjectShapes& shapes, const btTransform& transform) + { + bool result = updateObject(id, shapes.mShape, transform); + if (shapes.mAvoid) + { + const auto avoidId = reinterpret_cast(shapes.mAvoid); + if (mNavMeshManager.updateObject(avoidId, *shapes.mAvoid, transform, RC_NULL_AREA)) + { + updateAvoidShapeId(id, avoidId); + result = true; + } + } + return result; } bool Navigator::removeObject(std::size_t id) { - return mNavMeshManager.removeObject(id); + bool result = mNavMeshManager.removeObject(id); + const auto avoid = mAvoidIds.find(id); + if (avoid == mAvoidIds.end()) + return result; + return mNavMeshManager.removeObject(avoid->second) || result; } void Navigator::update(const osg::Vec3f& playerPosition) @@ -60,4 +96,14 @@ namespace DetourNavigator { return mSettings; } + + void Navigator::updateAvoidShapeId(std::size_t id, std::size_t avoidId) + { + auto inserted = mAvoidIds.insert(std::make_pair(id, avoidId)); + if (!inserted.second) + { + mNavMeshManager.removeObject(inserted.first->second); + inserted.second = avoidId; + } + } } diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 69529a9d4..39dd41a14 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -8,6 +8,17 @@ namespace DetourNavigator { + struct ObjectShapes + { + const btCollisionShape& mShape; + const btCollisionShape* mAvoid; + + ObjectShapes(const btCollisionShape& shape, const btCollisionShape* avoid) + : mShape(shape), mAvoid(avoid) + { + } + }; + class Navigator { public: @@ -19,8 +30,12 @@ namespace DetourNavigator bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool addObject(std::size_t id, const ObjectShapes& shapes, const btTransform& transform); + bool updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool updateObject(std::size_t id, const ObjectShapes& shapes, const btTransform& transform); + bool removeObject(std::size_t id); void update(const osg::Vec3f& playerPosition); @@ -44,6 +59,9 @@ namespace DetourNavigator Settings mSettings; NavMeshManager mNavMeshManager; std::map mAgents; + std::unordered_map mAvoidIds; + + void updateAvoidShapeId(std::size_t id, std::size_t avoidId); }; } diff --git a/components/detournavigator/navmeshmanager.cpp b/components/detournavigator/navmeshmanager.cpp index b13c5d83c..7ddaef55c 100644 --- a/components/detournavigator/navmeshmanager.cpp +++ b/components/detournavigator/navmeshmanager.cpp @@ -29,20 +29,21 @@ namespace DetourNavigator : mSettings(settings) , mRecastMeshManager(settings) , mAsyncNavMeshUpdater(settings, mRecastMeshManager) - { - } + {} - bool NavMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) + bool NavMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags) { - if (!mRecastMeshManager.addObject(id, shape, transform)) + if (!mRecastMeshManager.addObject(id, shape, transform, flags)) return false; addChangedTiles(shape, transform, ChangeType::add); return true; } - bool NavMeshManager::updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) + bool NavMeshManager::updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags) { - if (!mRecastMeshManager.updateObject(id, transform)) + if (!mRecastMeshManager.updateObject(id, transform, flags)) return false; addChangedTiles(shape, transform, ChangeType::mixed); return true; diff --git a/components/detournavigator/navmeshmanager.hpp b/components/detournavigator/navmeshmanager.hpp index 01840a3b6..fbbc81e6c 100644 --- a/components/detournavigator/navmeshmanager.hpp +++ b/components/detournavigator/navmeshmanager.hpp @@ -23,9 +23,11 @@ namespace DetourNavigator public: NavMeshManager(const Settings& settings); - bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags); - bool updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool updateObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags); bool removeObject(std::size_t id); diff --git a/components/detournavigator/recastmesh.cpp b/components/detournavigator/recastmesh.cpp index d765656e4..fc23c1fea 100644 --- a/components/detournavigator/recastmesh.cpp +++ b/components/detournavigator/recastmesh.cpp @@ -1,15 +1,21 @@ #include "recastmesh.hpp" #include "settings.hpp" +#include "exceptions.hpp" #include namespace DetourNavigator { - RecastMesh::RecastMesh(std::vector indices, std::vector vertices, const Settings& settings) + RecastMesh::RecastMesh(std::vector indices, std::vector vertices, + std::vector flags, const Settings& settings) : mIndices(std::move(indices)) , mVertices(std::move(vertices)) - , mChunkyTriMesh(mVertices, mIndices, settings.mTrianglesPerChunk) + , mFlags(std::move(flags)) + , mChunkyTriMesh(mVertices, mIndices, mFlags, settings.mTrianglesPerChunk) { + if (getTrianglesCount() != mFlags.size()) + throw InvalidArgument("number of flags doesn't match number of triangles: triangles=" + + std::to_string(getTrianglesCount()) + ", flags=" + std::to_string(mFlags.size())); if (getVerticesCount()) rcCalcBounds(mVertices.data(), static_cast(getVerticesCount()), mBoundsMin.ptr(), mBoundsMax.ptr()); } diff --git a/components/detournavigator/recastmesh.hpp b/components/detournavigator/recastmesh.hpp index 8dcb717e2..59f97b2ee 100644 --- a/components/detournavigator/recastmesh.hpp +++ b/components/detournavigator/recastmesh.hpp @@ -15,7 +15,8 @@ namespace DetourNavigator class RecastMesh { public: - RecastMesh(std::vector indices, std::vector vertices, const Settings& settings); + RecastMesh(std::vector indices, std::vector vertices, + std::vector flags, const Settings& settings); const std::vector& getIndices() const { @@ -27,6 +28,11 @@ namespace DetourNavigator return mVertices; } + const std::vector& getFlags() const + { + return mFlags; + } + std::size_t getVerticesCount() const { return mVertices.size() / 3; @@ -55,6 +61,7 @@ namespace DetourNavigator private: std::vector mIndices; std::vector mVertices; + std::vector mFlags; ChunkyTriMesh mChunkyTriMesh; osg::Vec3f mBoundsMin; osg::Vec3f mBoundsMax; diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index a34b114ac..229f42022 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -35,46 +35,52 @@ namespace DetourNavigator mBounds.mMax /= mSettings.get().mRecastScaleFactor; } - void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform) + void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags) { if (shape.isCompound()) - return addObject(static_cast(shape), transform); + return addObject(static_cast(shape), transform, flags); else if (shape.getShapeType() == TERRAIN_SHAPE_PROXYTYPE) - return addObject(static_cast(shape), transform); + return addObject(static_cast(shape), transform, flags); else if (shape.isConcave()) - return addObject(static_cast(shape), transform); + return addObject(static_cast(shape), transform, flags); else if (shape.getShapeType() == BOX_SHAPE_PROXYTYPE) - return addObject(static_cast(shape), transform); + return addObject(static_cast(shape), transform, flags); std::ostringstream message; message << "Unsupported shape type: " << BroadphaseNativeTypes(shape.getShapeType()); throw InvalidArgument(message.str()); } - void RecastMeshBuilder::addObject(const btCompoundShape& shape, const btTransform& transform) + void RecastMeshBuilder::addObject(const btCompoundShape& shape, const btTransform& transform, + const unsigned char flags) { for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) - addObject(*shape.getChildShape(i), transform * shape.getChildTransform(i)); + addObject(*shape.getChildShape(i), transform * shape.getChildTransform(i), flags); } - void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform) + void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform, + const unsigned char flags) { return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int) { for (std::size_t i = 3; i > 0; --i) addTriangleVertex(transform(triangle[i - 1])); + mFlags.push_back(flags); })); } - void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform) + void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform, + const unsigned char flags) { return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int) { for (std::size_t i = 0; i < 3; ++i) addTriangleVertex(transform(triangle[i])); + mFlags.push_back(flags); })); } - void RecastMeshBuilder::addObject(const btBoxShape& shape, const btTransform& transform) + void RecastMeshBuilder::addObject(const btBoxShape& shape, const btTransform& transform, const unsigned char flags) { const auto indexOffset = int(mVertices.size() / 3); @@ -85,6 +91,9 @@ namespace DetourNavigator addVertex(transform(position)); } + for (int vertex = 0; vertex < 12; ++vertex) + mFlags.push_back(flags); + static const std::array indices {{ 0, 2, 3, 3, 1, 0, @@ -106,13 +115,14 @@ namespace DetourNavigator std::shared_ptr RecastMeshBuilder::create() const { - return std::make_shared(mIndices, mVertices, mSettings); + return std::make_shared(mIndices, mVertices, mFlags, mSettings); } void RecastMeshBuilder::reset() { mIndices.clear(); mVertices.clear(); + mFlags.clear(); } void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform, diff --git a/components/detournavigator/recastmeshbuilder.hpp b/components/detournavigator/recastmeshbuilder.hpp index d06f2cdd6..770acbf9d 100644 --- a/components/detournavigator/recastmeshbuilder.hpp +++ b/components/detournavigator/recastmeshbuilder.hpp @@ -20,15 +20,15 @@ namespace DetourNavigator public: RecastMeshBuilder(const Settings& settings, const TileBounds& bounds); - void addObject(const btCollisionShape& shape, const btTransform& transform); + void addObject(const btCollisionShape& shape, const btTransform& transform, const unsigned char flags); - void addObject(const btCompoundShape& shape, const btTransform& transform); + void addObject(const btCompoundShape& shape, const btTransform& transform, const unsigned char flags); - void addObject(const btConcaveShape& shape, const btTransform& transform); + void addObject(const btConcaveShape& shape, const btTransform& transform, const unsigned char flags); - void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform); + void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform, const unsigned char flags); - void addObject(const btBoxShape& shape, const btTransform& transform); + void addObject(const btBoxShape& shape, const btTransform& transform, const unsigned char flags); std::shared_ptr create() const; @@ -39,6 +39,7 @@ namespace DetourNavigator TileBounds mBounds; std::vector mIndices; std::vector mVertices; + std::vector mFlags; void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback); diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index d4b905e7d..66009d8b5 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -11,20 +11,21 @@ namespace DetourNavigator { } - bool RecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform) + bool RecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags) { - if (!mObjects.emplace(id, RecastMeshObject(shape, transform)).second) + if (!mObjects.emplace(id, RecastMeshObject(shape, transform, flags)).second) return false; mShouldRebuild = true; return mShouldRebuild; } - bool RecastMeshManager::updateObject(std::size_t id, const btTransform& transform) + bool RecastMeshManager::updateObject(std::size_t id, const btTransform& transform, const unsigned char flags) { const auto object = mObjects.find(id); if (object == mObjects.end()) return false; - if (!object->second.update(transform)) + if (!object->second.update(transform, flags)) return false; mShouldRebuild = true; return mShouldRebuild; @@ -58,7 +59,7 @@ namespace DetourNavigator return; mMeshBuilder.reset(); for (const auto& v : mObjects) - mMeshBuilder.addObject(v.second.getShape(), v.second.getTransform()); + mMeshBuilder.addObject(v.second.getShape(), v.second.getTransform(), v.second.getFlags()); mShouldRebuild = false; } } diff --git a/components/detournavigator/recastmeshmanager.hpp b/components/detournavigator/recastmeshmanager.hpp index c8e32714e..d475d494d 100644 --- a/components/detournavigator/recastmeshmanager.hpp +++ b/components/detournavigator/recastmeshmanager.hpp @@ -25,9 +25,10 @@ namespace DetourNavigator public: RecastMeshManager(const Settings& settings, const TileBounds& bounds); - bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags); - bool updateObject(std::size_t id, const btTransform& transform); + bool updateObject(std::size_t id, const btTransform& transform, const unsigned char flags); boost::optional removeObject(std::size_t id); diff --git a/components/detournavigator/recastmeshobject.cpp b/components/detournavigator/recastmeshobject.cpp index b6727ba5e..54fb25ea0 100644 --- a/components/detournavigator/recastmeshobject.cpp +++ b/components/detournavigator/recastmeshobject.cpp @@ -8,14 +8,16 @@ namespace DetourNavigator { - RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform) + RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags) : mShape(shape) , mTransform(transform) - , mChildren(makeChildrenObjects(shape)) + , mFlags(flags) + , mChildren(makeChildrenObjects(shape, mFlags)) { } - bool RecastMeshObject::update(const btTransform& transform) + bool RecastMeshObject::update(const btTransform& transform, const unsigned char flags) { bool result = false; if (!(mTransform == transform)) @@ -23,36 +25,42 @@ namespace DetourNavigator mTransform = transform; result = true; } + if (mFlags != flags) + { + mFlags = flags; + result = true; + } if (mShape.get().isCompound()) - result = updateCompoundObject(static_cast(mShape.get()), mChildren) || result; + result = updateCompoundObject(static_cast(mShape.get()), mFlags, mChildren) || result; return result; } - bool RecastMeshObject::updateCompoundObject(const btCompoundShape& shape, std::vector& children) + bool RecastMeshObject::updateCompoundObject(const btCompoundShape& shape, + const unsigned char flags, std::vector& children) { assert(static_cast(shape.getNumChildShapes()) == children.size()); bool result = false; for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) { assert(shape.getChildShape(i) == std::addressof(children[static_cast(i)].mShape.get())); - result = children[static_cast(i)].update(shape.getChildTransform(i)) || result; + result = children[static_cast(i)].update(shape.getChildTransform(i), flags) || result; } return result; } - std::vector makeChildrenObjects(const btCollisionShape& shape) + std::vector makeChildrenObjects(const btCollisionShape& shape, const unsigned char flags) { if (shape.isCompound()) - return makeChildrenObjects(static_cast(shape)); + return makeChildrenObjects(static_cast(shape), flags); else return std::vector(); } - std::vector makeChildrenObjects(const btCompoundShape& shape) + std::vector makeChildrenObjects(const btCompoundShape& shape, const unsigned char flags) { std::vector result; for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) - result.emplace_back(*shape.getChildShape(i), shape.getChildTransform(i)); + result.emplace_back(*shape.getChildShape(i), shape.getChildTransform(i), flags); return result; } } diff --git a/components/detournavigator/recastmeshobject.hpp b/components/detournavigator/recastmeshobject.hpp index 697acfa58..bc7b54d5a 100644 --- a/components/detournavigator/recastmeshobject.hpp +++ b/components/detournavigator/recastmeshobject.hpp @@ -14,9 +14,9 @@ namespace DetourNavigator class RecastMeshObject { public: - RecastMeshObject(const btCollisionShape& shape, const btTransform& transform); + RecastMeshObject(const btCollisionShape& shape, const btTransform& transform, const unsigned char flags); - bool update(const btTransform& transform); + bool update(const btTransform& transform, const unsigned char flags); const btCollisionShape& getShape() const { @@ -28,17 +28,24 @@ namespace DetourNavigator return mTransform; } + unsigned char getFlags() const + { + return mFlags; + } + private: std::reference_wrapper mShape; btTransform mTransform; + unsigned char mFlags; std::vector mChildren; - static bool updateCompoundObject(const btCompoundShape& shape, std::vector& children); + static bool updateCompoundObject(const btCompoundShape& shape, const unsigned char flags, + std::vector& children); }; - std::vector makeChildrenObjects(const btCollisionShape& shape); + std::vector makeChildrenObjects(const btCollisionShape& shape, const unsigned char flags); - std::vector makeChildrenObjects(const btCompoundShape& shape); + std::vector makeChildrenObjects(const btCompoundShape& shape, const unsigned char flags); } #endif diff --git a/components/detournavigator/tilecachedrecastmeshmanager.cpp b/components/detournavigator/tilecachedrecastmeshmanager.cpp index 346ab9fd1..a3dec79cd 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.cpp @@ -7,11 +7,10 @@ namespace DetourNavigator { TileCachedRecastMeshManager::TileCachedRecastMeshManager(const Settings& settings) : mSettings(settings) - { - } + {} bool TileCachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape, - const btTransform& transform) + const btTransform& transform, const unsigned char flags) { bool result = false; auto& tilesPositions = mObjectsTilesPositions[id]; @@ -28,7 +27,7 @@ namespace DetourNavigator tile = mTiles.insert(std::make_pair(tilePosition, CachedRecastMeshManager(mSettings, tileBounds))).first; } - if (tile->second.addObject(id, shape, transform)) + if (tile->second.addObject(id, shape, transform, flags)) { lock.unlock(); tilesPositions.push_back(tilePosition); @@ -40,7 +39,8 @@ namespace DetourNavigator return result; } - bool TileCachedRecastMeshManager::updateObject(std::size_t id, const btTransform& transform) + bool TileCachedRecastMeshManager::updateObject(std::size_t id, const btTransform& transform, + const unsigned char flags) { const auto object = mObjectsTilesPositions.find(id); if (object == mObjectsTilesPositions.end()) @@ -51,7 +51,7 @@ namespace DetourNavigator { const auto tile = mTiles.find(tilePosition); if (tile != mTiles.end()) - result = tile->second.updateObject(id, transform) || result; + result = tile->second.updateObject(id, transform, flags) || result; } lock.unlock(); if (result) diff --git a/components/detournavigator/tilecachedrecastmeshmanager.hpp b/components/detournavigator/tilecachedrecastmeshmanager.hpp index 9e5c07e84..37299e281 100644 --- a/components/detournavigator/tilecachedrecastmeshmanager.hpp +++ b/components/detournavigator/tilecachedrecastmeshmanager.hpp @@ -14,9 +14,10 @@ namespace DetourNavigator public: TileCachedRecastMeshManager(const Settings& settings); - bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform); + bool addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform, + const unsigned char flags); - bool updateObject(std::size_t id, const btTransform& transform); + bool updateObject(std::size_t id, const btTransform& transform, const unsigned char flags); boost::optional removeObject(std::size_t id); diff --git a/components/resource/bulletshape.cpp b/components/resource/bulletshape.cpp index 645a5dd3b..e3f6b22b4 100644 --- a/components/resource/bulletshape.cpp +++ b/components/resource/bulletshape.cpp @@ -80,16 +80,23 @@ btCollisionShape* BulletShape::duplicateCollisionShape(const btCollisionShape *s throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName()); } -btCollisionShape *BulletShape::getCollisionShape() +btCollisionShape *BulletShape::getCollisionShape() const { return mCollisionShape; } -btCollisionShape *BulletShape::getAvoidCollisionShape() +btCollisionShape *BulletShape::getAvoidCollisionShape() const { return mAvoidCollisionShape; } +void BulletShape::setLocalScaling(const btVector3& scale) +{ + mCollisionShape->setLocalScaling(scale); + if (mAvoidCollisionShape) + mAvoidCollisionShape->setLocalScaling(scale); +} + osg::ref_ptr BulletShape::makeInstance() const { osg::ref_ptr instance (new BulletShapeInstance(this)); diff --git a/components/resource/bulletshape.hpp b/components/resource/bulletshape.hpp index f2f45cac9..8d6354b01 100644 --- a/components/resource/bulletshape.hpp +++ b/components/resource/bulletshape.hpp @@ -43,9 +43,11 @@ namespace Resource btCollisionShape* duplicateCollisionShape(const btCollisionShape* shape) const; - btCollisionShape* getCollisionShape(); + btCollisionShape* getCollisionShape() const; - btCollisionShape* getAvoidCollisionShape(); + btCollisionShape* getAvoidCollisionShape() const; + + void setLocalScaling(const btVector3& scale); private: