#include "recastmeshbuilder.hpp" #include "chunkytrimesh.hpp" #include "debug.hpp" #include "settings.hpp" #include "settingsutils.hpp" #include "exceptions.hpp" #include #include #include #include namespace { osg::Vec3f makeOsgVec3f(const btVector3& value) { return osg::Vec3f(value.x(), value.y(), value.z()); } } namespace DetourNavigator { using BulletHelpers::makeProcessTriangleCallback; RecastMeshBuilder::RecastMeshBuilder(const Settings& settings) : mSettings(settings) {} void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform) { if (shape.isCompound()) return addObject(static_cast(shape), transform); else if (shape.getShapeType() == TERRAIN_SHAPE_PROXYTYPE) return addObject(static_cast(shape), transform); else if (shape.isConcave()) return addObject(static_cast(shape), transform); std::ostringstream message; message << "Unsupported shape type: " << BroadphaseNativeTypes(shape.getShapeType()); throw InvalidArgument(message.str()); } void RecastMeshBuilder::addObject(const btCompoundShape& shape, const btTransform& transform) { for (int i = 0, num = shape.getNumChildShapes(); i < num; ++i) addObject(*shape.getChildShape(i), transform * shape.getChildTransform(i)); } void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform) { return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int) { for (std::size_t i = 3; i > 0; --i) addVertex(transform(triangle[i - 1])); })); } void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform) { return addObject(shape, makeProcessTriangleCallback([&] (btVector3* triangle, int, int) { for (std::size_t i = 0; i < 3; ++i) addVertex(transform(triangle[i])); })); } std::shared_ptr RecastMeshBuilder::create() const { return std::make_shared(mIndices, mVertices, mSettings); } void RecastMeshBuilder::reset() { mIndices.clear(); mVertices.clear(); } void RecastMeshBuilder::addObject(const btConcaveShape& shape, btTriangleCallback&& callback) { btVector3 aabbMin; btVector3 aabbMax; shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax); shape.processAllTriangles(&callback, aabbMin, aabbMax); } void RecastMeshBuilder::addVertex(const btVector3& worldPosition) { const auto navMeshPosition = toNavMeshCoordinates(mSettings, makeOsgVec3f(worldPosition)); mIndices.push_back(static_cast(mIndices.size())); mVertices.push_back(navMeshPosition.x()); mVertices.push_back(navMeshPosition.y()); mVertices.push_back(navMeshPosition.z()); } }