mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-29 16:06:44 +00:00
Support btBoxShape for RecastMesh
This commit is contained in:
parent
70a369f70e
commit
d1e71f9322
4 changed files with 176 additions and 7 deletions
|
@ -31,12 +31,17 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, create_for_empty_should_throw_exception)
|
||||||
|
{
|
||||||
|
EXPECT_THROW(mBuilder.create(), std::invalid_argument);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_bhv_triangle_mesh_shape)
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_bhv_triangle_mesh_shape)
|
||||||
{
|
{
|
||||||
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));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
mBuilder.addObject(shape, btTransform::getIdentity());
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
const auto recastMesh = mBuilder.create();
|
const auto recastMesh = mBuilder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
1, 0, -1,
|
1, 0, -1,
|
||||||
|
@ -51,7 +56,7 @@ namespace
|
||||||
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));
|
||||||
btBvhTriangleMeshShape shape(&mesh, true);
|
btBvhTriangleMeshShape shape(&mesh, true);
|
||||||
mBuilder.addObject(shape,
|
mBuilder.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)));
|
||||||
const auto recastMesh = mBuilder.create();
|
const auto recastMesh = mBuilder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
@ -66,7 +71,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);
|
||||||
mBuilder.addObject(shape, btTransform::getIdentity());
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
const auto recastMesh = mBuilder.create();
|
const auto recastMesh = mBuilder.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,
|
||||||
|
@ -78,4 +83,121 @@ namespace
|
||||||
}));
|
}));
|
||||||
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}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_box_shape_should_produce_12_triangles)
|
||||||
|
{
|
||||||
|
btBoxShape shape(btVector3(1, 1, 2));
|
||||||
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = mBuilder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
1, 2, 1,
|
||||||
|
-1, 2, 1,
|
||||||
|
1, 2, -1,
|
||||||
|
-1, 2, -1,
|
||||||
|
1, -2, 1,
|
||||||
|
-1, -2, 1,
|
||||||
|
1, -2, -1,
|
||||||
|
-1, -2, -1,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({
|
||||||
|
0, 2, 3,
|
||||||
|
3, 1, 0,
|
||||||
|
0, 4, 6,
|
||||||
|
6, 2, 0,
|
||||||
|
0, 1, 5,
|
||||||
|
5, 4, 0,
|
||||||
|
7, 5, 1,
|
||||||
|
1, 3, 7,
|
||||||
|
7, 3, 2,
|
||||||
|
2, 6, 7,
|
||||||
|
7, 6, 4,
|
||||||
|
4, 5, 7,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_compound_shape)
|
||||||
|
{
|
||||||
|
btTriangleMesh mesh1;
|
||||||
|
mesh1.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
btBvhTriangleMeshShape triangle1(&mesh1, true);
|
||||||
|
btBoxShape box(btVector3(1, 1, 2));
|
||||||
|
btTriangleMesh mesh2;
|
||||||
|
mesh2.addTriangle(btVector3(1, 1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
btBvhTriangleMeshShape triangle2(&mesh2, true);
|
||||||
|
btCompoundShape shape;
|
||||||
|
shape.addChildShape(btTransform::getIdentity(), &triangle1);
|
||||||
|
shape.addChildShape(btTransform::getIdentity(), &box);
|
||||||
|
shape.addChildShape(btTransform::getIdentity(), &triangle2);
|
||||||
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape), btTransform::getIdentity());
|
||||||
|
const auto recastMesh = mBuilder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
1, 0, -1,
|
||||||
|
-1, 0, 1,
|
||||||
|
-1, 0, -1,
|
||||||
|
1, 2, 1,
|
||||||
|
-1, 2, 1,
|
||||||
|
1, 2, -1,
|
||||||
|
-1, 2, -1,
|
||||||
|
1, -2, 1,
|
||||||
|
-1, -2, 1,
|
||||||
|
1, -2, -1,
|
||||||
|
-1, -2, -1,
|
||||||
|
1, 0, -1,
|
||||||
|
-1, 0, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({
|
||||||
|
0, 1, 2,
|
||||||
|
3, 5, 6,
|
||||||
|
6, 4, 3,
|
||||||
|
3, 7, 9,
|
||||||
|
9, 5, 3,
|
||||||
|
3, 4, 8,
|
||||||
|
8, 7, 3,
|
||||||
|
10, 8, 4,
|
||||||
|
4, 6, 10,
|
||||||
|
10, 6, 5,
|
||||||
|
5, 9, 10,
|
||||||
|
10, 9, 7,
|
||||||
|
7, 8, 10,
|
||||||
|
11, 12, 13,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape)
|
||||||
|
{
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
btBvhTriangleMeshShape triangle(&mesh, true);
|
||||||
|
btCompoundShape shape;
|
||||||
|
shape.addChildShape(btTransform::getIdentity(), &triangle);
|
||||||
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
||||||
|
const auto recastMesh = mBuilder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
2, 3, 0,
|
||||||
|
0, 3, 4,
|
||||||
|
0, 3, 0,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(DetourNavigatorRecastMeshBuilderTest, add_transformed_compound_shape_with_transformed_bhv_triangle_shape)
|
||||||
|
{
|
||||||
|
btTriangleMesh mesh;
|
||||||
|
mesh.addTriangle(btVector3(-1, -1, 0), btVector3(-1, 1, 0), btVector3(1, -1, 0));
|
||||||
|
btBvhTriangleMeshShape triangle(&mesh, true);
|
||||||
|
btCompoundShape shape;
|
||||||
|
shape.addChildShape(btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)),
|
||||||
|
&triangle);
|
||||||
|
mBuilder.addObject(static_cast<const btCollisionShape&>(shape),
|
||||||
|
btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)));
|
||||||
|
const auto recastMesh = mBuilder.create();
|
||||||
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
|
3, 12, 2,
|
||||||
|
1, 12, 10,
|
||||||
|
1, 12, 2,
|
||||||
|
}));
|
||||||
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "chunkytrimesh.hpp"
|
#include "chunkytrimesh.hpp"
|
||||||
|
#include "exceptions.hpp"
|
||||||
|
|
||||||
#include <osg/Vec2f>
|
#include <osg/Vec2f>
|
||||||
|
|
||||||
|
@ -119,7 +120,7 @@ namespace DetourNavigator
|
||||||
const auto trianglesCount = indices.size() / 3;
|
const auto trianglesCount = indices.size() / 3;
|
||||||
|
|
||||||
if (trianglesCount == 0)
|
if (trianglesCount == 0)
|
||||||
return;
|
throw InvalidArgument("ChunkyTriMesh tris should contain at least 3 values");
|
||||||
|
|
||||||
const auto nchunks = (trianglesCount + trisPerChunk - 1) / trisPerChunk;
|
const auto nchunks = (trianglesCount + trisPerChunk - 1) / trisPerChunk;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,13 @@
|
||||||
|
|
||||||
#include <components/bullethelpers/processtrianglecallback.hpp>
|
#include <components/bullethelpers/processtrianglecallback.hpp>
|
||||||
|
|
||||||
|
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
#include <BulletCollision/CollisionShapes/btCompoundShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btConcaveShape.h>
|
#include <BulletCollision/CollisionShapes/btConcaveShape.h>
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
|
#include <LinearMath/btTransform.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -35,6 +39,8 @@ namespace DetourNavigator
|
||||||
return addObject(static_cast<const btHeightfieldTerrainShape&>(shape), transform);
|
return addObject(static_cast<const btHeightfieldTerrainShape&>(shape), transform);
|
||||||
else if (shape.isConcave())
|
else if (shape.isConcave())
|
||||||
return addObject(static_cast<const btConcaveShape&>(shape), transform);
|
return addObject(static_cast<const btConcaveShape&>(shape), transform);
|
||||||
|
else if (shape.getShapeType() == BOX_SHAPE_PROXYTYPE)
|
||||||
|
return addObject(static_cast<const btBoxShape&>(shape), transform);
|
||||||
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());
|
||||||
|
@ -51,7 +57,7 @@ namespace DetourNavigator
|
||||||
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 3; i > 0; --i)
|
for (std::size_t i = 3; i > 0; --i)
|
||||||
addVertex(transform(triangle[i - 1]));
|
addTriangleVertex(transform(triangle[i - 1]));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +66,40 @@ namespace DetourNavigator
|
||||||
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < 3; ++i)
|
for (std::size_t i = 0; i < 3; ++i)
|
||||||
addVertex(transform(triangle[i]));
|
addTriangleVertex(transform(triangle[i]));
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecastMeshBuilder::addObject(const btBoxShape& shape, const btTransform& transform)
|
||||||
|
{
|
||||||
|
const auto indexOffset = int(mVertices.size() / 3);
|
||||||
|
|
||||||
|
for (int vertex = 0; vertex < shape.getNumVertices(); ++vertex)
|
||||||
|
{
|
||||||
|
btVector3 position;
|
||||||
|
shape.getVertex(vertex, position);
|
||||||
|
addVertex(transform(position));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::array<int, 36> indices {{
|
||||||
|
0, 2, 3,
|
||||||
|
3, 1, 0,
|
||||||
|
0, 4, 6,
|
||||||
|
6, 2, 0,
|
||||||
|
0, 1, 5,
|
||||||
|
5, 4, 0,
|
||||||
|
7, 5, 1,
|
||||||
|
1, 3, 7,
|
||||||
|
7, 3, 2,
|
||||||
|
2, 6, 7,
|
||||||
|
7, 6, 4,
|
||||||
|
4, 5, 7,
|
||||||
|
}};
|
||||||
|
|
||||||
|
std::transform(indices.begin(), indices.end(), std::back_inserter(mIndices),
|
||||||
|
[&] (int index) { return index + indexOffset; });
|
||||||
|
}
|
||||||
|
|
||||||
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, mSettings);
|
||||||
|
@ -83,10 +119,15 @@ namespace DetourNavigator
|
||||||
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RecastMeshBuilder::addTriangleVertex(const btVector3& worldPosition)
|
||||||
|
{
|
||||||
|
mIndices.push_back(static_cast<int>(mVertices.size() / 3));
|
||||||
|
addVertex(worldPosition);
|
||||||
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::addVertex(const btVector3& worldPosition)
|
void RecastMeshBuilder::addVertex(const btVector3& worldPosition)
|
||||||
{
|
{
|
||||||
const auto navMeshPosition = toNavMeshCoordinates(mSettings, makeOsgVec3f(worldPosition));
|
const auto navMeshPosition = toNavMeshCoordinates(mSettings, makeOsgVec3f(worldPosition));
|
||||||
mIndices.push_back(static_cast<int>(mIndices.size()));
|
|
||||||
mVertices.push_back(navMeshPosition.x());
|
mVertices.push_back(navMeshPosition.x());
|
||||||
mVertices.push_back(navMeshPosition.y());
|
mVertices.push_back(navMeshPosition.y());
|
||||||
mVertices.push_back(navMeshPosition.z());
|
mVertices.push_back(navMeshPosition.z());
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "recastmesh.hpp"
|
#include "recastmesh.hpp"
|
||||||
|
|
||||||
|
class btBoxShape;
|
||||||
class btCollisionShape;
|
class btCollisionShape;
|
||||||
class btCompoundShape;
|
class btCompoundShape;
|
||||||
class btConcaveShape;
|
class btConcaveShape;
|
||||||
|
@ -26,6 +27,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform);
|
void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
|
void addObject(const btBoxShape& shape, const btTransform& transform);
|
||||||
|
|
||||||
std::shared_ptr<RecastMesh> create() const;
|
std::shared_ptr<RecastMesh> create() const;
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
@ -37,6 +40,8 @@ namespace DetourNavigator
|
||||||
|
|
||||||
void addObject(const btConcaveShape& shape, btTriangleCallback&& callback);
|
void addObject(const btConcaveShape& shape, btTriangleCallback&& callback);
|
||||||
|
|
||||||
|
void addTriangleVertex(const btVector3& worldPosition);
|
||||||
|
|
||||||
void addVertex(const btVector3& worldPosition);
|
void addVertex(const btVector3& worldPosition);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue