mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 00:36:46 +00:00
Add unwalkable areas to NavMesh
This commit is contained in:
parent
c771986c56
commit
fa23b590a4
27 changed files with 368 additions and 111 deletions
|
@ -40,7 +40,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
void Object::setScale(float scale)
|
void Object::setScale(float scale)
|
||||||
{
|
{
|
||||||
mShapeInstance->getCollisionShape()->setLocalScaling(btVector3(scale,scale,scale));
|
mShapeInstance->setLocalScaling(btVector3(scale, scale, scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::setRotation(const btQuaternion& quat)
|
void Object::setRotation(const btQuaternion& quat)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
||||||
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
@ -86,7 +87,11 @@ namespace
|
||||||
if (const auto object = physics.getObject(ptr))
|
if (const auto object = physics.getObject(ptr))
|
||||||
{
|
{
|
||||||
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
const auto navigator = MWBase::Environment::get().getWorld()->getNavigator();
|
||||||
navigator->addObject(reinterpret_cast<std::size_t>(object), *object->getCollisionObject()->getCollisionShape(),
|
const DetourNavigator::ObjectShapes shapes {
|
||||||
|
*object->getShapeInstance()->getCollisionShape(),
|
||||||
|
object->getShapeInstance()->getAvoidCollisionShape()
|
||||||
|
};
|
||||||
|
navigator->addObject(reinterpret_cast<std::size_t>(object), shapes,
|
||||||
object->getCollisionObject()->getWorldTransform());
|
object->getCollisionObject()->getWorldTransform());
|
||||||
}
|
}
|
||||||
else if (const auto actor = physics.getActor(ptr))
|
else if (const auto actor = physics.getActor(ptr))
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <osg/ComputeBoundsVisitor>
|
#include <osg/ComputeBoundsVisitor>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||||
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
|
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
|
|
||||||
|
#include <components/resource/bulletshape.hpp>
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||||
|
@ -1544,8 +1546,11 @@ namespace MWWorld
|
||||||
bool navigatorObjectsUpdated = false;
|
bool navigatorObjectsUpdated = false;
|
||||||
mPhysics->forEachAnimatedObject([&] (const MWPhysics::Object* object)
|
mPhysics->forEachAnimatedObject([&] (const MWPhysics::Object* object)
|
||||||
{
|
{
|
||||||
navigatorObjectsUpdated = mNavigator->updateObject(std::size_t(object),
|
const DetourNavigator::ObjectShapes shapes {
|
||||||
*object->getCollisionObject()->getCollisionShape(),
|
*object->getShapeInstance()->getCollisionShape(),
|
||||||
|
object->getShapeInstance()->getAvoidCollisionShape()
|
||||||
|
};
|
||||||
|
navigatorObjectsUpdated = mNavigator->updateObject(std::size_t(object), shapes,
|
||||||
object->getCollisionObject()->getWorldTransform()) || navigatorObjectsUpdated;
|
object->getCollisionObject()->getWorldTransform()) || navigatorObjectsUpdated;
|
||||||
});
|
});
|
||||||
if (navigatorObjectsUpdated)
|
if (navigatorObjectsUpdated)
|
||||||
|
|
|
@ -358,4 +358,61 @@ namespace
|
||||||
osg::Vec3f(215, -215, 1.96328866481781005859375),
|
osg::Vec3f(215, -215, 1.96328866481781005859375),
|
||||||
})) << mPath;
|
})) << mPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorNavigatorTest, path_should_be_around_avoid_shape)
|
||||||
|
{
|
||||||
|
std::array<btScalar, 5 * 5> 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<btScalar, 5 * 5> 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>({
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>());
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>());
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_bhv_triangle_mesh_shape)
|
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));
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
|
@ -56,6 +57,7 @@ namespace
|
||||||
-1, 0, -1,
|
-1, 0, -1,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_bhv_triangle_mesh_shape)
|
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));
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
|
1
|
||||||
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
|
@ -73,6 +78,7 @@ namespace
|
||||||
0, 3, 0,
|
0, 3, 0,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_heightfield_terrian_shape)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_heightfield_terrian_shape)
|
||||||
|
@ -80,7 +86,7 @@ namespace
|
||||||
const std::array<btScalar, 4> heightfieldData {{0, 0, 0, 0}};
|
const std::array<btScalar, 4> heightfieldData {{0, 0, 0, 0}};
|
||||||
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-0.5, 0, -0.5,
|
-0.5, 0, -0.5,
|
||||||
|
@ -91,13 +97,14 @@ namespace
|
||||||
0.5, 0, 0.5,
|
0.5, 0, 0.5,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1, 1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles)
|
||||||
{
|
{
|
||||||
btBoxShape shape(btVector3(1, 1, 2));
|
btBoxShape shape(btVector3(1, 1, 2));
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 2, 1,
|
1, 2, 1,
|
||||||
|
@ -123,6 +130,7 @@ namespace
|
||||||
7, 6, 4,
|
7, 6, 4,
|
||||||
4, 5, 7,
|
4, 5, 7,
|
||||||
}));
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_compound_shape)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_compound_shape)
|
||||||
|
@ -139,7 +147,7 @@ namespace
|
||||||
shape.addChildShape(btTransform::getIdentity(), &box);
|
shape.addChildShape(btTransform::getIdentity(), &box);
|
||||||
shape.addChildShape(btTransform::getIdentity(), &triangle2);
|
shape.addChildShape(btTransform::getIdentity(), &triangle2);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
|
@ -173,6 +181,7 @@ namespace
|
||||||
7, 8, 10,
|
7, 8, 10,
|
||||||
11, 12, 13,
|
11, 12, 13,
|
||||||
}));
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape)
|
||||||
|
@ -184,7 +193,8 @@ namespace
|
||||||
shape.addChildShape(btTransform::getIdentity(), &triangle);
|
shape.addChildShape(btTransform::getIdentity(), &triangle);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(static_cast<const btCollisionShape&>(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();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
2, 3, 0,
|
2, 3, 0,
|
||||||
|
@ -192,6 +202,7 @@ namespace
|
||||||
0, 3, 0,
|
0, 3, 0,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape_with_transformed_bhv_triangle_shape)
|
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)),
|
shape.addChildShape(btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
&triangle);
|
&triangle);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(
|
||||||
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
|
1
|
||||||
|
);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
3, 12, 2,
|
3, 12, 2,
|
||||||
|
@ -212,16 +226,17 @@ namespace
|
||||||
1, 12, 2,
|
1, 12, 2,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({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;
|
btTriangleMesh mesh;
|
||||||
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
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));
|
mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
|
@ -232,9 +247,10 @@ namespace
|
||||||
-3, 0, -3,
|
-3, 0, -3,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({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;
|
mSettings.mRecastScaleFactor = 0.1f;
|
||||||
mBounds.mMin = osg::Vec2f(-3, -3) * mSettings.mRecastScaleFactor;
|
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));
|
mesh.addTriangle(btVector3(-3, -3, 0), btVector3(-3, -2, 0), btVector3(-2, -3, 0));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
builder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity(), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-0.2f, 0, -0.3f,
|
-0.2f, 0, -0.3f,
|
||||||
|
@ -252,6 +268,7 @@ namespace
|
||||||
-0.3f, 0, -0.3f,
|
-0.3f, 0, -0.3f,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_x_bhv_triangle_shape_should_filter_by_bounds)
|
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);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
btTransform(btQuaternion(btVector3(1, 0, 0), static_cast<btScalar>(-osg::PI_4))));
|
btTransform(btQuaternion(btVector3(1, 0, 0), static_cast<btScalar>(-osg::PI_4))), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
0, -0.70710659027099609375, -3.535533905029296875,
|
0, -0.70710659027099609375, -3.535533905029296875,
|
||||||
|
@ -272,6 +289,7 @@ namespace
|
||||||
0, 2.384185791015625e-07, -4.24264049530029296875,
|
0, 2.384185791015625e-07, -4.24264049530029296875,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_y_bhv_triangle_shape_should_filter_by_bounds)
|
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);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
btTransform(btQuaternion(btVector3(0, 1, 0), static_cast<btScalar>(osg::PI_4))));
|
btTransform(btQuaternion(btVector3(0, 1, 0), static_cast<btScalar>(osg::PI_4))), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
-3.535533905029296875, -0.70710659027099609375, 0,
|
-3.535533905029296875, -0.70710659027099609375, 0,
|
||||||
|
@ -292,6 +310,7 @@ namespace
|
||||||
-4.24264049530029296875, 2.384185791015625e-07, 0,
|
-4.24264049530029296875, 2.384185791015625e-07, 0,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1}));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, with_bounds_add_rotated_by_z_bhv_triangle_shape_should_filter_by_bounds)
|
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);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
RecastMeshBuilder builder(mSettings, mBounds);
|
RecastMeshBuilder builder(mSettings, mBounds);
|
||||||
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
builder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
btTransform(btQuaternion(btVector3(0, 0, 1), static_cast<btScalar>(osg::PI_4))));
|
btTransform(btQuaternion(btVector3(0, 0, 1), static_cast<btScalar>(osg::PI_4))), 1);
|
||||||
const auto recastMesh = builder.create();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
0.707107067108154296875, 0, -3.535533905029296875,
|
0.707107067108154296875, 0, -3.535533905029296875,
|
||||||
|
@ -312,5 +331,30 @@ namespace
|
||||||
2.384185791015625e-07, 0, -4.24264049530029296875,
|
2.384185791015625e-07, 0, -4.24264049530029296875,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({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<const btCollisionShape&>(shape1), btTransform::getIdentity(), 1);
|
||||||
|
builder.addObject(static_cast<const btCollisionShape&>(shape2), btTransform::getIdentity(), 0);
|
||||||
|
const auto recastMesh = builder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
1, 0, -1,
|
||||||
|
-1, 0, 1,
|
||||||
|
-1, 0, -1,
|
||||||
|
-2, 0, -3,
|
||||||
|
-3, 0, -2,
|
||||||
|
-3, 0, -3,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2, 3, 4, 5}));
|
||||||
|
EXPECT_EQ(recastMesh->getFlags(), std::vector<unsigned char>({1, 0}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,41 +26,47 @@ namespace
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshObjectTest, constructed_object_should_have_shape_and_transform)
|
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(std::addressof(object.getShape()), std::addressof(mBoxShape));
|
||||||
EXPECT_EQ(object.getTransform(), mTransform);
|
EXPECT_EQ(object.getTransform(), mTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_same_transform_for_not_compound_shape_should_return_false)
|
TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_same_transform_for_not_compound_shape_should_return_false)
|
||||||
{
|
{
|
||||||
RecastMeshObject object(mBoxShape, mTransform);
|
RecastMeshObject object(mBoxShape, mTransform, 1);
|
||||||
EXPECT_FALSE(object.update(mTransform));
|
EXPECT_FALSE(object.update(mTransform, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_different_transform_should_return_true)
|
TEST_F(DetourNavigatorRecastMeshObjectTest, update_with_different_transform_should_return_true)
|
||||||
{
|
{
|
||||||
RecastMeshObject object(mBoxShape, mTransform);
|
RecastMeshObject object(mBoxShape, mTransform, 1);
|
||||||
EXPECT_TRUE(object.update(btTransform::getIdentity()));
|
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)
|
TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_compound_shape_with_same_transform_and_not_changed_child_transform_should_return_false)
|
||||||
{
|
{
|
||||||
RecastMeshObject object(mCompoundShape, mTransform);
|
RecastMeshObject object(mCompoundShape, mTransform, 1);
|
||||||
EXPECT_FALSE(object.update(mTransform));
|
EXPECT_FALSE(object.update(mTransform, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshObjectTest, update_for_compound_shape_with_same_transform_and_changed_child_transform_should_return_true)
|
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());
|
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)
|
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());
|
mCompoundShape.updateChildTransform(0, btTransform::getIdentity());
|
||||||
object.update(mTransform);
|
object.update(mTransform, 1);
|
||||||
EXPECT_FALSE(object.update(mTransform));
|
EXPECT_FALSE(object.update(mTransform, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,20 +5,20 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
CachedRecastMeshManager::CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds)
|
||||||
: mImpl(settings, 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;
|
return false;
|
||||||
mCached.reset();
|
mCached.reset();
|
||||||
return true;
|
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;
|
return false;
|
||||||
mCached.reset();
|
mCached.reset();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -12,9 +12,10 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
CachedRecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
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<RemovedRecastMeshObject> removeObject(std::size_t id);
|
boost::optional<RemovedRecastMeshObject> removeObject(std::size_t id);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
Rect mBounds;
|
Rect mBounds;
|
||||||
std::ptrdiff_t mOffset;
|
std::ptrdiff_t mOffset;
|
||||||
|
unsigned char mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t axis>
|
template <std::size_t axis>
|
||||||
|
@ -43,9 +44,9 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
void subdivide(std::vector<BoundsItem>& items, const std::size_t imin, const std::size_t imax,
|
void subdivide(std::vector<BoundsItem>& items, const std::size_t imin, const std::size_t imax,
|
||||||
const std::size_t trisPerChunk, const std::vector<int>& inIndices,
|
const std::size_t trisPerChunk, const std::vector<int>& inIndices, const std::vector<unsigned char>& inFlags,
|
||||||
std::size_t& curNode, std::vector<ChunkyTriMeshNode>& nodes, std::size_t& curTri,
|
std::size_t& curNode, std::vector<ChunkyTriMeshNode>& nodes, std::size_t& curTri,
|
||||||
std::vector<int>& outIndices)
|
std::vector<int>& outIndices, std::vector<unsigned char>& outFlags)
|
||||||
{
|
{
|
||||||
const auto inum = imax - imin;
|
const auto inum = imax - imin;
|
||||||
const auto icur = curNode;
|
const auto icur = curNode;
|
||||||
|
@ -71,6 +72,7 @@ namespace DetourNavigator
|
||||||
inIndices.begin() + items[i].mOffset * 3 + 3,
|
inIndices.begin() + items[i].mOffset * 3 + 3,
|
||||||
outIndices.begin() + static_cast<std::ptrdiff_t>(curTri) * 3
|
outIndices.begin() + static_cast<std::ptrdiff_t>(curTri) * 3
|
||||||
);
|
);
|
||||||
|
outFlags[curTri] = inFlags[static_cast<std::size_t>(items[i].mOffset)];
|
||||||
curTri++;
|
curTri++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -102,9 +104,9 @@ namespace DetourNavigator
|
||||||
const auto isplit = imin + inum / 2;
|
const auto isplit = imin + inum / 2;
|
||||||
|
|
||||||
// Left
|
// Left
|
||||||
subdivide(items, imin, isplit, trisPerChunk, inIndices, curNode, nodes, curTri, outIndices);
|
subdivide(items, imin, isplit, trisPerChunk, inIndices, inFlags, curNode, nodes, curTri, outIndices, outFlags);
|
||||||
// Right
|
// 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<std::ptrdiff_t>(curNode) - static_cast<std::ptrdiff_t>(icur);
|
const auto iescape = static_cast<std::ptrdiff_t>(curNode) - static_cast<std::ptrdiff_t>(icur);
|
||||||
// Negative index means escape.
|
// Negative index means escape.
|
||||||
|
@ -114,7 +116,7 @@ namespace DetourNavigator
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkyTriMesh::ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& indices,
|
ChunkyTriMesh::ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& indices,
|
||||||
const std::size_t trisPerChunk)
|
const std::vector<unsigned char>& flags, const std::size_t trisPerChunk)
|
||||||
: mMaxTrisPerChunk(0)
|
: mMaxTrisPerChunk(0)
|
||||||
{
|
{
|
||||||
const auto trianglesCount = indices.size() / 3;
|
const auto trianglesCount = indices.size() / 3;
|
||||||
|
@ -126,6 +128,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
mNodes.resize(nchunks * 4);
|
mNodes.resize(nchunks * 4);
|
||||||
mIndices.resize(trianglesCount * 3);
|
mIndices.resize(trianglesCount * 3);
|
||||||
|
mFlags.resize(trianglesCount);
|
||||||
|
|
||||||
// Build tree
|
// Build tree
|
||||||
std::vector<BoundsItem> items(trianglesCount);
|
std::vector<BoundsItem> items(trianglesCount);
|
||||||
|
@ -135,6 +138,7 @@ namespace DetourNavigator
|
||||||
auto& item = items[i];
|
auto& item = items[i];
|
||||||
|
|
||||||
item.mOffset = static_cast<std::ptrdiff_t>(i);
|
item.mOffset = static_cast<std::ptrdiff_t>(i);
|
||||||
|
item.mFlags = flags[i];
|
||||||
|
|
||||||
// Calc triangle XZ bounds.
|
// Calc triangle XZ bounds.
|
||||||
const auto baseIndex = static_cast<std::size_t>(indices[i * 3]) * 3;
|
const auto baseIndex = static_cast<std::size_t>(indices[i * 3]) * 3;
|
||||||
|
@ -156,7 +160,7 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::size_t curTri = 0;
|
std::size_t curTri = 0;
|
||||||
std::size_t curNode = 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();
|
items.clear();
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace DetourNavigator
|
||||||
struct Chunk
|
struct Chunk
|
||||||
{
|
{
|
||||||
const int* const mIndices;
|
const int* const mIndices;
|
||||||
|
const unsigned char* const mFlags;
|
||||||
const std::size_t mSize;
|
const std::size_t mSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,7 +41,8 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
/// Creates partitioned triangle mesh (AABB tree),
|
/// Creates partitioned triangle mesh (AABB tree),
|
||||||
/// where each node contains at max trisPerChunk triangles.
|
/// where each node contains at max trisPerChunk triangles.
|
||||||
ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& tris, std::size_t trisPerChunk);
|
ChunkyTriMesh(const std::vector<float>& verts, const std::vector<int>& tris,
|
||||||
|
const std::vector<unsigned char>& flags, const std::size_t trisPerChunk);
|
||||||
|
|
||||||
ChunkyTriMesh(const ChunkyTriMesh&) = delete;
|
ChunkyTriMesh(const ChunkyTriMesh&) = delete;
|
||||||
ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete;
|
ChunkyTriMesh& operator=(const ChunkyTriMesh&) = delete;
|
||||||
|
@ -74,6 +76,7 @@ namespace DetourNavigator
|
||||||
const auto& node = mNodes[chunkId];
|
const auto& node = mNodes[chunkId];
|
||||||
return Chunk {
|
return Chunk {
|
||||||
mIndices.data() + node.mOffset * 3,
|
mIndices.data() + node.mOffset * 3,
|
||||||
|
mFlags.data() + node.mOffset,
|
||||||
node.mSize
|
node.mSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -86,6 +89,7 @@ namespace DetourNavigator
|
||||||
private:
|
private:
|
||||||
std::vector<ChunkyTriMeshNode> mNodes;
|
std::vector<ChunkyTriMeshNode> mNodes;
|
||||||
std::vector<int> mIndices;
|
std::vector<int> mIndices;
|
||||||
|
std::vector<unsigned char> mFlags;
|
||||||
std::size_t mMaxTrisPerChunk;
|
std::size_t mMaxTrisPerChunk;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,19 @@ namespace
|
||||||
areas.data()
|
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<int>(recastMesh.getVerticesCount()),
|
||||||
|
chunk.mIndices,
|
||||||
|
static_cast<int>(chunk.mSize),
|
||||||
|
areas.data()
|
||||||
|
);
|
||||||
|
|
||||||
OPENMW_CHECK_DT_RESULT(rcRasterizeTriangles(
|
OPENMW_CHECK_DT_RESULT(rcRasterizeTriangles(
|
||||||
&context,
|
&context,
|
||||||
recastMesh.getVertices().data(),
|
recastMesh.getVertices().data(),
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
#include "settingsutils.hpp"
|
#include "settingsutils.hpp"
|
||||||
|
|
||||||
|
#include <Recast.h>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
Navigator::Navigator(const Settings& settings)
|
Navigator::Navigator(const Settings& settings)
|
||||||
|
@ -27,17 +29,51 @@ namespace DetourNavigator
|
||||||
|
|
||||||
bool Navigator::addObject(std::size_t id, const btCollisionShape& shape, const btTransform& transform)
|
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<std::size_t>(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)
|
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<std::size_t>(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)
|
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)
|
void Navigator::update(const osg::Vec3f& playerPosition)
|
||||||
|
@ -60,4 +96,14 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
return mSettings;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,17 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
|
struct ObjectShapes
|
||||||
|
{
|
||||||
|
const btCollisionShape& mShape;
|
||||||
|
const btCollisionShape* mAvoid;
|
||||||
|
|
||||||
|
ObjectShapes(const btCollisionShape& shape, const btCollisionShape* avoid)
|
||||||
|
: mShape(shape), mAvoid(avoid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Navigator
|
class Navigator
|
||||||
{
|
{
|
||||||
public:
|
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 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 btCollisionShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
bool updateObject(std::size_t id, const ObjectShapes& shapes, const btTransform& transform);
|
||||||
|
|
||||||
bool removeObject(std::size_t id);
|
bool removeObject(std::size_t id);
|
||||||
|
|
||||||
void update(const osg::Vec3f& playerPosition);
|
void update(const osg::Vec3f& playerPosition);
|
||||||
|
@ -44,6 +59,9 @@ namespace DetourNavigator
|
||||||
Settings mSettings;
|
Settings mSettings;
|
||||||
NavMeshManager mNavMeshManager;
|
NavMeshManager mNavMeshManager;
|
||||||
std::map<osg::Vec3f, std::size_t> mAgents;
|
std::map<osg::Vec3f, std::size_t> mAgents;
|
||||||
|
std::unordered_map<std::size_t, std::size_t> mAvoidIds;
|
||||||
|
|
||||||
|
void updateAvoidShapeId(std::size_t id, std::size_t avoidId);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,20 +29,21 @@ namespace DetourNavigator
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
, mRecastMeshManager(settings)
|
, mRecastMeshManager(settings)
|
||||||
, mAsyncNavMeshUpdater(settings, mRecastMeshManager)
|
, 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;
|
return false;
|
||||||
addChangedTiles(shape, transform, ChangeType::add);
|
addChangedTiles(shape, transform, ChangeType::add);
|
||||||
return true;
|
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;
|
return false;
|
||||||
addChangedTiles(shape, transform, ChangeType::mixed);
|
addChangedTiles(shape, transform, ChangeType::mixed);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -23,9 +23,11 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
NavMeshManager(const Settings& settings);
|
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);
|
bool removeObject(std::size_t id);
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
#include "recastmesh.hpp"
|
#include "recastmesh.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "exceptions.hpp"
|
||||||
|
|
||||||
#include <Recast.h>
|
#include <Recast.h>
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastMesh::RecastMesh(std::vector<int> indices, std::vector<float> vertices, const Settings& settings)
|
RecastMesh::RecastMesh(std::vector<int> indices, std::vector<float> vertices,
|
||||||
|
std::vector<unsigned char> flags, const Settings& settings)
|
||||||
: mIndices(std::move(indices))
|
: mIndices(std::move(indices))
|
||||||
, mVertices(std::move(vertices))
|
, 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())
|
if (getVerticesCount())
|
||||||
rcCalcBounds(mVertices.data(), static_cast<int>(getVerticesCount()), mBoundsMin.ptr(), mBoundsMax.ptr());
|
rcCalcBounds(mVertices.data(), static_cast<int>(getVerticesCount()), mBoundsMin.ptr(), mBoundsMax.ptr());
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ namespace DetourNavigator
|
||||||
class RecastMesh
|
class RecastMesh
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RecastMesh(std::vector<int> indices, std::vector<float> vertices, const Settings& settings);
|
RecastMesh(std::vector<int> indices, std::vector<float> vertices,
|
||||||
|
std::vector<unsigned char> flags, const Settings& settings);
|
||||||
|
|
||||||
const std::vector<int>& getIndices() const
|
const std::vector<int>& getIndices() const
|
||||||
{
|
{
|
||||||
|
@ -27,6 +28,11 @@ namespace DetourNavigator
|
||||||
return mVertices;
|
return mVertices;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<unsigned char>& getFlags() const
|
||||||
|
{
|
||||||
|
return mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t getVerticesCount() const
|
std::size_t getVerticesCount() const
|
||||||
{
|
{
|
||||||
return mVertices.size() / 3;
|
return mVertices.size() / 3;
|
||||||
|
@ -55,6 +61,7 @@ namespace DetourNavigator
|
||||||
private:
|
private:
|
||||||
std::vector<int> mIndices;
|
std::vector<int> mIndices;
|
||||||
std::vector<float> mVertices;
|
std::vector<float> mVertices;
|
||||||
|
std::vector<unsigned char> mFlags;
|
||||||
ChunkyTriMesh mChunkyTriMesh;
|
ChunkyTriMesh mChunkyTriMesh;
|
||||||
osg::Vec3f mBoundsMin;
|
osg::Vec3f mBoundsMin;
|
||||||
osg::Vec3f mBoundsMax;
|
osg::Vec3f mBoundsMax;
|
||||||
|
|
|
@ -35,46 +35,52 @@ namespace DetourNavigator
|
||||||
mBounds.mMax /= mSettings.get().mRecastScaleFactor;
|
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())
|
if (shape.isCompound())
|
||||||
return addObject(static_cast<const btCompoundShape&>(shape), transform);
|
return addObject(static_cast<const btCompoundShape&>(shape), transform, flags);
|
||||||
else if (shape.getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
else if (shape.getShapeType() == TERRAIN_SHAPE_PROXYTYPE)
|
||||||
return addObject(static_cast<const btHeightfieldTerrainShape&>(shape), transform);
|
return addObject(static_cast<const btHeightfieldTerrainShape&>(shape), transform, flags);
|
||||||
else if (shape.isConcave())
|
else if (shape.isConcave())
|
||||||
return addObject(static_cast<const btConcaveShape&>(shape), transform);
|
return addObject(static_cast<const btConcaveShape&>(shape), transform, flags);
|
||||||
else if (shape.getShapeType() == BOX_SHAPE_PROXYTYPE)
|
else if (shape.getShapeType() == BOX_SHAPE_PROXYTYPE)
|
||||||
return addObject(static_cast<const btBoxShape&>(shape), transform);
|
return addObject(static_cast<const btBoxShape&>(shape), transform, flags);
|
||||||
std::ostringstream message;
|
std::ostringstream message;
|
||||||
message << "Unsupported shape type: " << BroadphaseNativeTypes(shape.getShapeType());
|
message << "Unsupported shape type: " << BroadphaseNativeTypes(shape.getShapeType());
|
||||||
throw InvalidArgument(message.str());
|
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)
|
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)
|
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 3; i > 0; --i)
|
for (std::size_t i = 3; i > 0; --i)
|
||||||
addTriangleVertex(transform(triangle[i - 1]));
|
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)
|
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < 3; ++i)
|
for (std::size_t i = 0; i < 3; ++i)
|
||||||
addTriangleVertex(transform(triangle[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);
|
const auto indexOffset = int(mVertices.size() / 3);
|
||||||
|
|
||||||
|
@ -85,6 +91,9 @@ namespace DetourNavigator
|
||||||
addVertex(transform(position));
|
addVertex(transform(position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < 12; ++vertex)
|
||||||
|
mFlags.push_back(flags);
|
||||||
|
|
||||||
static const std::array<int, 36> indices {{
|
static const std::array<int, 36> indices {{
|
||||||
0, 2, 3,
|
0, 2, 3,
|
||||||
3, 1, 0,
|
3, 1, 0,
|
||||||
|
@ -106,13 +115,14 @@ namespace DetourNavigator
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> RecastMeshBuilder::create() const
|
std::shared_ptr<RecastMesh> RecastMeshBuilder::create() const
|
||||||
{
|
{
|
||||||
return std::make_shared<RecastMesh>(mIndices, mVertices, mSettings);
|
return std::make_shared<RecastMesh>(mIndices, mVertices, mFlags, mSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::reset()
|
void RecastMeshBuilder::reset()
|
||||||
{
|
{
|
||||||
mIndices.clear();
|
mIndices.clear();
|
||||||
mVertices.clear();
|
mVertices.clear();
|
||||||
|
mFlags.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform,
|
void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform,
|
||||||
|
|
|
@ -20,15 +20,15 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
RecastMeshBuilder(const Settings& settings, const TileBounds& bounds);
|
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<RecastMesh> create() const;
|
std::shared_ptr<RecastMesh> create() const;
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ namespace DetourNavigator
|
||||||
TileBounds mBounds;
|
TileBounds mBounds;
|
||||||
std::vector<int> mIndices;
|
std::vector<int> mIndices;
|
||||||
std::vector<float> mVertices;
|
std::vector<float> mVertices;
|
||||||
|
std::vector<unsigned char> mFlags;
|
||||||
|
|
||||||
void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
return false;
|
||||||
mShouldRebuild = true;
|
mShouldRebuild = true;
|
||||||
return mShouldRebuild;
|
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);
|
const auto object = mObjects.find(id);
|
||||||
if (object == mObjects.end())
|
if (object == mObjects.end())
|
||||||
return false;
|
return false;
|
||||||
if (!object->second.update(transform))
|
if (!object->second.update(transform, flags))
|
||||||
return false;
|
return false;
|
||||||
mShouldRebuild = true;
|
mShouldRebuild = true;
|
||||||
return mShouldRebuild;
|
return mShouldRebuild;
|
||||||
|
@ -58,7 +59,7 @@ namespace DetourNavigator
|
||||||
return;
|
return;
|
||||||
mMeshBuilder.reset();
|
mMeshBuilder.reset();
|
||||||
for (const auto& v : mObjects)
|
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;
|
mShouldRebuild = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,10 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
RecastMeshManager(const Settings& settings, const TileBounds& bounds);
|
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<RemovedRecastMeshObject> removeObject(std::size_t id);
|
boost::optional<RemovedRecastMeshObject> removeObject(std::size_t id);
|
||||||
|
|
||||||
|
|
|
@ -8,14 +8,16 @@
|
||||||
|
|
||||||
namespace DetourNavigator
|
namespace DetourNavigator
|
||||||
{
|
{
|
||||||
RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform)
|
RecastMeshObject::RecastMeshObject(const btCollisionShape& shape, const btTransform& transform,
|
||||||
|
const unsigned char flags)
|
||||||
: mShape(shape)
|
: mShape(shape)
|
||||||
, mTransform(transform)
|
, 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;
|
bool result = false;
|
||||||
if (!(mTransform == transform))
|
if (!(mTransform == transform))
|
||||||
|
@ -23,36 +25,42 @@ namespace DetourNavigator
|
||||||
mTransform = transform;
|
mTransform = transform;
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
if (mFlags != flags)
|
||||||
|
{
|
||||||
|
mFlags = flags;
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
if (mShape.get().isCompound())
|
if (mShape.get().isCompound())
|
||||||
result = updateCompoundObject(static_cast<const btCompoundShape&>(mShape.get()), mChildren) || result;
|
result = updateCompoundObject(static_cast<const btCompoundShape&>(mShape.get()), mFlags, mChildren) || result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecastMeshObject::updateCompoundObject(const btCompoundShape& shape, std::vector<RecastMeshObject>& children)
|
bool RecastMeshObject::updateCompoundObject(const btCompoundShape& shape,
|
||||||
|
const unsigned char flags, std::vector<RecastMeshObject>& children)
|
||||||
{
|
{
|
||||||
assert(static_cast<std::size_t>(shape.getNumChildShapes()) == children.size());
|
assert(static_cast<std::size_t>(shape.getNumChildShapes()) == children.size());
|
||||||
bool result = false;
|
bool result = false;
|
||||||
for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i)
|
for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i)
|
||||||
{
|
{
|
||||||
assert(shape.getChildShape(i) == std::addressof(children[static_cast<std::size_t>(i)].mShape.get()));
|
assert(shape.getChildShape(i) == std::addressof(children[static_cast<std::size_t>(i)].mShape.get()));
|
||||||
result = children[static_cast<std::size_t>(i)].update(shape.getChildTransform(i)) || result;
|
result = children[static_cast<std::size_t>(i)].update(shape.getChildTransform(i), flags) || result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape)
|
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape, const unsigned char flags)
|
||||||
{
|
{
|
||||||
if (shape.isCompound())
|
if (shape.isCompound())
|
||||||
return makeChildrenObjects(static_cast<const btCompoundShape&>(shape));
|
return makeChildrenObjects(static_cast<const btCompoundShape&>(shape), flags);
|
||||||
else
|
else
|
||||||
return std::vector<RecastMeshObject>();
|
return std::vector<RecastMeshObject>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape)
|
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape, const unsigned char flags)
|
||||||
{
|
{
|
||||||
std::vector<RecastMeshObject> result;
|
std::vector<RecastMeshObject> result;
|
||||||
for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace DetourNavigator
|
||||||
class RecastMeshObject
|
class RecastMeshObject
|
||||||
{
|
{
|
||||||
public:
|
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
|
const btCollisionShape& getShape() const
|
||||||
{
|
{
|
||||||
|
@ -28,17 +28,24 @@ namespace DetourNavigator
|
||||||
return mTransform;
|
return mTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char getFlags() const
|
||||||
|
{
|
||||||
|
return mFlags;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::reference_wrapper<const btCollisionShape> mShape;
|
std::reference_wrapper<const btCollisionShape> mShape;
|
||||||
btTransform mTransform;
|
btTransform mTransform;
|
||||||
|
unsigned char mFlags;
|
||||||
std::vector<RecastMeshObject> mChildren;
|
std::vector<RecastMeshObject> mChildren;
|
||||||
|
|
||||||
static bool updateCompoundObject(const btCompoundShape& shape, std::vector<RecastMeshObject>& children);
|
static bool updateCompoundObject(const btCompoundShape& shape, const unsigned char flags,
|
||||||
|
std::vector<RecastMeshObject>& children);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape);
|
std::vector<RecastMeshObject> makeChildrenObjects(const btCollisionShape& shape, const unsigned char flags);
|
||||||
|
|
||||||
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape);
|
std::vector<RecastMeshObject> makeChildrenObjects(const btCompoundShape& shape, const unsigned char flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -7,11 +7,10 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const Settings& settings)
|
TileCachedRecastMeshManager::TileCachedRecastMeshManager(const Settings& settings)
|
||||||
: mSettings(settings)
|
: mSettings(settings)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
bool TileCachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape,
|
bool TileCachedRecastMeshManager::addObject(std::size_t id, const btCollisionShape& shape,
|
||||||
const btTransform& transform)
|
const btTransform& transform, const unsigned char flags)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
auto& tilesPositions = mObjectsTilesPositions[id];
|
auto& tilesPositions = mObjectsTilesPositions[id];
|
||||||
|
@ -28,7 +27,7 @@ namespace DetourNavigator
|
||||||
tile = mTiles.insert(std::make_pair(tilePosition,
|
tile = mTiles.insert(std::make_pair(tilePosition,
|
||||||
CachedRecastMeshManager(mSettings, tileBounds))).first;
|
CachedRecastMeshManager(mSettings, tileBounds))).first;
|
||||||
}
|
}
|
||||||
if (tile->second.addObject(id, shape, transform))
|
if (tile->second.addObject(id, shape, transform, flags))
|
||||||
{
|
{
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
tilesPositions.push_back(tilePosition);
|
tilesPositions.push_back(tilePosition);
|
||||||
|
@ -40,7 +39,8 @@ namespace DetourNavigator
|
||||||
return result;
|
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);
|
const auto object = mObjectsTilesPositions.find(id);
|
||||||
if (object == mObjectsTilesPositions.end())
|
if (object == mObjectsTilesPositions.end())
|
||||||
|
@ -51,7 +51,7 @@ namespace DetourNavigator
|
||||||
{
|
{
|
||||||
const auto tile = mTiles.find(tilePosition);
|
const auto tile = mTiles.find(tilePosition);
|
||||||
if (tile != mTiles.end())
|
if (tile != mTiles.end())
|
||||||
result = tile->second.updateObject(id, transform) || result;
|
result = tile->second.updateObject(id, transform, flags) || result;
|
||||||
}
|
}
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
if (result)
|
if (result)
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace DetourNavigator
|
||||||
public:
|
public:
|
||||||
TileCachedRecastMeshManager(const Settings& settings);
|
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<RemovedRecastMeshObject> removeObject(std::size_t id);
|
boost::optional<RemovedRecastMeshObject> removeObject(std::size_t id);
|
||||||
|
|
||||||
|
|
|
@ -80,16 +80,23 @@ btCollisionShape* BulletShape::duplicateCollisionShape(const btCollisionShape *s
|
||||||
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
|
throw std::logic_error(std::string("Unhandled Bullet shape duplication: ")+shape->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionShape *BulletShape::getCollisionShape()
|
btCollisionShape *BulletShape::getCollisionShape() const
|
||||||
{
|
{
|
||||||
return mCollisionShape;
|
return mCollisionShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
btCollisionShape *BulletShape::getAvoidCollisionShape()
|
btCollisionShape *BulletShape::getAvoidCollisionShape() const
|
||||||
{
|
{
|
||||||
return mAvoidCollisionShape;
|
return mAvoidCollisionShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BulletShape::setLocalScaling(const btVector3& scale)
|
||||||
|
{
|
||||||
|
mCollisionShape->setLocalScaling(scale);
|
||||||
|
if (mAvoidCollisionShape)
|
||||||
|
mAvoidCollisionShape->setLocalScaling(scale);
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
|
osg::ref_ptr<BulletShapeInstance> BulletShape::makeInstance() const
|
||||||
{
|
{
|
||||||
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
|
osg::ref_ptr<BulletShapeInstance> instance (new BulletShapeInstance(this));
|
||||||
|
|
|
@ -43,9 +43,11 @@ namespace Resource
|
||||||
|
|
||||||
btCollisionShape* duplicateCollisionShape(const btCollisionShape* shape) const;
|
btCollisionShape* duplicateCollisionShape(const btCollisionShape* shape) const;
|
||||||
|
|
||||||
btCollisionShape* getCollisionShape();
|
btCollisionShape* getCollisionShape() const;
|
||||||
|
|
||||||
btCollisionShape* getAvoidCollisionShape();
|
btCollisionShape* getAvoidCollisionShape() const;
|
||||||
|
|
||||||
|
void setLocalScaling(const btVector3& scale);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue