From 5a6b39f8e054bf9280cf4300f6271d700b77bf64 Mon Sep 17 00:00:00 2001 From: elsid Date: Thu, 4 Nov 2021 01:57:27 +0100 Subject: [PATCH] Store mesh source data in recast mesh --- .../detournavigator/navmeshtilescache.cpp | 2 +- apps/openmw/mwphysics/ptrholder.hpp | 2 +- apps/openmw/mwworld/scene.cpp | 25 +++++++---- apps/openmw/mwworld/worldimp.cpp | 4 +- .../detournavigator/navigator.cpp | 37 +++++++++-------- .../detournavigator/navmeshtilescache.cpp | 41 ++++++++++--------- .../detournavigator/recastmeshbuilder.cpp | 35 +++++++++------- .../detournavigator/recastmeshobject.cpp | 8 ++-- .../tilecachedrecastmeshmanager.cpp | 41 ++++++++++--------- components/CMakeLists.txt | 1 + components/detournavigator/areatype.hpp | 15 +++++++ components/detournavigator/navigator.hpp | 13 ++++-- components/detournavigator/navigatorimpl.cpp | 8 ++-- .../detournavigator/objecttransform.hpp | 27 ++++++++++++ components/detournavigator/recastmesh.cpp | 4 +- components/detournavigator/recastmesh.hpp | 15 ++++++- .../detournavigator/recastmeshbuilder.cpp | 10 ++++- .../detournavigator/recastmeshbuilder.hpp | 8 +++- .../detournavigator/recastmeshmanager.cpp | 10 +++-- .../detournavigator/recastmeshobject.cpp | 3 +- .../detournavigator/recastmeshobject.hpp | 22 +++++++--- components/esm/defs.hpp | 8 ++++ components/misc/convert.hpp | 5 +++ 23 files changed, 236 insertions(+), 108 deletions(-) create mode 100644 components/detournavigator/objecttransform.hpp diff --git a/apps/benchmarks/detournavigator/navmeshtilescache.cpp b/apps/benchmarks/detournavigator/navmeshtilescache.cpp index 9d41b62597..c27fdc4289 100644 --- a/apps/benchmarks/detournavigator/navmeshtilescache.cpp +++ b/apps/benchmarks/detournavigator/navmeshtilescache.cpp @@ -145,7 +145,7 @@ namespace std::vector water; generateWater(std::back_inserter(water), 1, random); RecastMesh recastMesh(generation, revision, std::move(mesh), std::move(water), - {generateHeightfield(random)}, {generateFlatHeightfield(random)}); + {generateHeightfield(random)}, {generateFlatHeightfield(random)}, {}); return Key {agentHalfExtents, tilePosition, std::move(recastMesh)}; } diff --git a/apps/openmw/mwphysics/ptrholder.hpp b/apps/openmw/mwphysics/ptrholder.hpp index fcd6ce203a..e194f8e934 100644 --- a/apps/openmw/mwphysics/ptrholder.hpp +++ b/apps/openmw/mwphysics/ptrholder.hpp @@ -20,7 +20,7 @@ namespace MWPhysics mPtr = updated; } - MWWorld::Ptr getPtr() + MWWorld::Ptr getPtr() const { return mPtr; } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 15b3477cb8..c3db62b5a9 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -64,14 +64,23 @@ namespace * osg::Quat(zr, osg::Vec3(0, 0, -1)); } - osg::Quat makeNodeRotation(const MWWorld::Ptr& ptr, RotationOrder order) + osg::Quat makeInverseNodeRotation(const MWWorld::Ptr& ptr) { const auto pos = ptr.getRefData().getPosition(); + return ptr.getClass().isActor() ? makeActorOsgQuat(pos) : makeInversedOrderObjectOsgQuat(pos); + } - const auto rot = ptr.getClass().isActor() ? makeActorOsgQuat(pos) - : (order == RotationOrder::inverse ? makeInversedOrderObjectOsgQuat(pos) : Misc::Convert::makeOsgQuat(pos)); + osg::Quat makeDirectNodeRotation(const MWWorld::Ptr& ptr) + { + const auto pos = ptr.getRefData().getPosition(); + return ptr.getClass().isActor() ? makeActorOsgQuat(pos) : Misc::Convert::makeOsgQuat(pos); + } - return rot; + osg::Quat makeNodeRotation(const MWWorld::Ptr& ptr, RotationOrder order) + { + if (order == RotationOrder::inverse) + return makeInverseNodeRotation(ptr); + return makeDirectNodeRotation(ptr); } void setNodeRotation(const MWWorld::Ptr& ptr, MWRender::RenderingManager& rendering, const osg::Quat &rotation) @@ -101,7 +110,7 @@ namespace } std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS()); - const auto rotation = makeNodeRotation(ptr, RotationOrder::direct); + const auto rotation = makeDirectNodeRotation(ptr); const ESM::RefNum& refnum = ptr.getCellRef().getRefNum(); if (!refnum.hasContentFile() || pagedRefs.find(refnum) == pagedRefs.end()) @@ -128,6 +137,8 @@ namespace { if (const auto object = physics.getObject(ptr)) { + const DetourNavigator::ObjectTransform objectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()}; + if (ptr.getClass().isDoor() && !ptr.getCellRef().getTeleport()) { btVector3 aabbMin; @@ -159,7 +170,7 @@ namespace navigator.addObject( DetourNavigator::ObjectId(object), - DetourNavigator::DoorShapes(object->getShapeInstance(), connectionStart, connectionEnd), + DetourNavigator::DoorShapes(object->getShapeInstance(), objectTransform, connectionStart, connectionEnd), transform ); } @@ -167,7 +178,7 @@ namespace { navigator.addObject( DetourNavigator::ObjectId(object), - DetourNavigator::ObjectShapes(object->getShapeInstance()), + DetourNavigator::ObjectShapes(object->getShapeInstance(), objectTransform), object->getTransform() ); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index f0ac894cfc..d08eef2904 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1533,7 +1533,9 @@ namespace MWWorld void World::updateNavigatorObject(const MWPhysics::Object& object) { - const DetourNavigator::ObjectShapes shapes(object.getShapeInstance()); + const MWWorld::Ptr ptr = object.getPtr(); + const DetourNavigator::ObjectShapes shapes(object.getShapeInstance(), + DetourNavigator::ObjectTransform {ptr.getRefData().getPosition(), ptr.getCellRef().getScale()}); mShouldUpdateNavigator = mNavigator->updateObject(DetourNavigator::ObjectId(&object), shapes, object.getTransform()) || mShouldUpdateNavigator; } diff --git a/apps/openmw_test_suite/detournavigator/navigator.cpp b/apps/openmw_test_suite/detournavigator/navigator.cpp index 4e2b7758ff..07dcbb2002 100644 --- a/apps/openmw_test_suite/detournavigator/navigator.cpp +++ b/apps/openmw_test_suite/detournavigator/navigator.cpp @@ -49,6 +49,7 @@ namespace const int mHeightfieldTileSize = ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1); const float mEndTolerance = 0; const btTransform mTransform {btMatrix3x3::getIdentity(), btVector3(256, 256, 0)}; + const ObjectTransform mObjectTransform {ESM::Position {{256, 256, 0}, {0, 0, 0}}, 0.0f}; DetourNavigatorNavigatorTest() : mPlayerPosition(256, 256, 0) @@ -258,7 +259,7 @@ namespace Vec3fEq(460, 56.66666412353515625, 1.99998295307159423828125) )) << mPath; - mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), mTransform); + mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -311,7 +312,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addHeightfield(mCellPosition, cellSize, surface); - mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), mTransform); + mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -346,7 +347,7 @@ namespace compound.shape().updateChildTransform(0, btTransform(btMatrix3x3::getIdentity(), btVector3(1000, 0, 0))); - mNavigator->updateObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), mTransform); + mNavigator->updateObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -404,8 +405,8 @@ namespace heightfield2.shape().setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance()), mTransform); - mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance()), mTransform); + mNavigator->addObject(ObjectId(&heightfield1.shape()), ObjectShapes(heightfield1.instance(), mObjectTransform), mTransform); + mNavigator->addObject(ObjectId(&heightfield2.shape()), ObjectShapes(heightfield2.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -494,7 +495,7 @@ namespace osg::ref_ptr instance(new Resource::BulletShapeInstance(bulletShape)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance), mTransform); + mNavigator->addObject(ObjectId(instance->mCollisionShape.get()), ObjectShapes(instance, mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -725,7 +726,7 @@ namespace heightfield.shape().setLocalScaling(btVector3(128, 128, 1)); mNavigator->addAgent(mAgentHalfExtents); - mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance()), mTransform); + mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -733,7 +734,7 @@ namespace mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); - mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance()), mTransform); + mNavigator->addObject(ObjectId(&heightfield.shape()), ObjectShapes(heightfield.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -876,7 +877,7 @@ namespace for (std::size_t i = 0; i < boxes.size(); ++i) { const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10, shift.y() + i * 10, i * 10)); - mNavigator->addObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance()), transform); + mNavigator->addObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform); } std::this_thread::sleep_for(std::chrono::microseconds(1)); @@ -884,7 +885,7 @@ namespace for (std::size_t i = 0; i < boxes.size(); ++i) { const btTransform transform(btMatrix3x3::getIdentity(), btVector3(shift.x() + i * 10 + 1, shift.y() + i * 10 + 1, i * 10 + 1)); - mNavigator->updateObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance()), transform); + mNavigator->updateObject(ObjectId(&boxes[i].shape()), ObjectShapes(boxes[i].instance(), mObjectTransform), transform); } mNavigator->update(mPlayerPosition); @@ -930,7 +931,7 @@ namespace for (std::size_t i = 0; i < shapes.size(); ++i) { const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32, i * 32, i * 32)); - mNavigator->addObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform); + mNavigator->addObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform); } mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -939,7 +940,7 @@ namespace for (std::size_t i = 0; i < shapes.size(); ++i) { const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 1, i * 32 + 1, i * 32 + 1)); - mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform); + mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform); } mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -947,7 +948,7 @@ namespace for (std::size_t i = 0; i < shapes.size(); ++i) { const btTransform transform(btMatrix3x3::getIdentity(), btVector3(i * 32 + 2, i * 32 + 2, i * 32 + 2)); - mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance()), transform); + mNavigator->updateObject(ObjectId(&shapes[i].shape()), ObjectShapes(shapes[i].instance(), mObjectTransform), transform); } mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -1001,10 +1002,10 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addHeightfield(mCellPosition, cellSize, surface); - mNavigator->addObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance()), + mNavigator->addObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform), btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition)); // add this box to make navmesh bound box independent from oscillatingBoxShape rotations - mNavigator->addObject(ObjectId(&borderBox.shape()), ObjectShapes(borderBox.instance()), + mNavigator->addObject(ObjectId(&borderBox.shape()), ObjectShapes(borderBox.instance(), mObjectTransform), btTransform(btMatrix3x3::getIdentity(), oscillatingBoxShapePosition + btVector3(0, 0, 200))); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -1019,7 +1020,7 @@ namespace { const btTransform transform(btQuaternion(btVector3(0, 0, 1), n * 2 * osg::PI / 10), oscillatingBoxShapePosition); - mNavigator->updateObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance()), transform); + mNavigator->updateObject(ObjectId(&oscillatingBox.shape()), ObjectShapes(oscillatingBox.instance(), mObjectTransform), transform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); } @@ -1085,7 +1086,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addHeightfield(mCellPosition, cellSize, surface); - mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), mTransform); + mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); @@ -1124,7 +1125,7 @@ namespace mNavigator->addAgent(mAgentHalfExtents); mNavigator->addHeightfield(mCellPosition, cellSize, surface); - mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance()), mTransform); + mNavigator->addObject(ObjectId(&compound.shape()), ObjectShapes(compound.instance(), mObjectTransform), mTransform); mNavigator->update(mPlayerPosition); mNavigator->wait(mListener, WaitConditionType::allJobsDone); diff --git a/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp b/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp index c56be440e3..2a7c5ac5a1 100644 --- a/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp +++ b/apps/openmw_test_suite/detournavigator/navmeshtilescache.cpp @@ -147,7 +147,8 @@ namespace const std::vector mWater {}; const std::vector mHeightfields {}; const std::vector mFlatHeightfields {}; - const RecastMesh mRecastMesh {mGeneration, mRevision, mMesh, mWater, mHeightfields, mFlatHeightfields}; + const std::vector mSources {}; + const RecastMesh mRecastMesh {mGeneration, mRevision, mMesh, mWater, mHeightfields, mFlatHeightfields, mSources}; std::unique_ptr mPreparedNavMeshData {makePeparedNavMeshData(3)}; const std::size_t mRecastMeshSize = sizeof(mRecastMesh) + getSize(mRecastMesh); @@ -235,7 +236,7 @@ namespace const std::size_t maxSize = 1; NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh unexistentRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; + const RecastMesh unexistentRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources); cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData)); EXPECT_FALSE(cache.get(mAgentHalfExtents, mTilePosition, unexistentRecastMesh)); @@ -247,7 +248,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; + const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources); auto anotherPreparedNavMeshData = makePeparedNavMeshData(3); const auto copy = clone(*anotherPreparedNavMeshData); @@ -265,7 +266,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; + const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources); auto anotherPreparedNavMeshData = makePeparedNavMeshData(3); const auto value = cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, @@ -281,13 +282,13 @@ namespace const auto copy = clone(*mPreparedNavMeshData); const std::vector leastRecentlySetWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh leastRecentlySetRecastMesh {mGeneration, mRevision, mMesh, leastRecentlySetWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh leastRecentlySetRecastMesh(mGeneration, mRevision, mMesh, leastRecentlySetWater, + mHeightfields, mFlatHeightfields, mSources); auto leastRecentlySetData = makePeparedNavMeshData(3); const std::vector mostRecentlySetWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}}); - const RecastMesh mostRecentlySetRecastMesh {mGeneration, mRevision, mMesh, mostRecentlySetWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh mostRecentlySetRecastMesh(mGeneration, mRevision, mMesh, mostRecentlySetWater, + mHeightfields, mFlatHeightfields, mSources); auto mostRecentlySetData = makePeparedNavMeshData(3); ASSERT_TRUE(cache.set(mAgentHalfExtents, mTilePosition, leastRecentlySetRecastMesh, @@ -309,14 +310,14 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector leastRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh leastRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, leastRecentlyUsedWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh leastRecentlyUsedRecastMesh(mGeneration, mRevision, mMesh, leastRecentlyUsedWater, + mHeightfields, mFlatHeightfields, mSources); auto leastRecentlyUsedData = makePeparedNavMeshData(3); const auto leastRecentlyUsedCopy = clone(*leastRecentlyUsedData); const std::vector mostRecentlyUsedWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}}); - const RecastMesh mostRecentlyUsedRecastMesh {mGeneration, mRevision, mMesh, mostRecentlyUsedWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh mostRecentlyUsedRecastMesh(mGeneration, mRevision, mMesh, mostRecentlyUsedWater, + mHeightfields, mFlatHeightfields, mSources); auto mostRecentlyUsedData = makePeparedNavMeshData(3); const auto mostRecentlyUsedCopy = clone(*mostRecentlyUsedData); @@ -350,8 +351,8 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, water, - mHeightfields, mFlatHeightfields}; + const RecastMesh tooLargeRecastMesh(mGeneration, mRevision, mMesh, water, + mHeightfields, mFlatHeightfields, mSources); auto tooLargeData = makePeparedNavMeshData(10); cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData)); @@ -365,13 +366,13 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector anotherWater(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, anotherWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, anotherWater, + mHeightfields, mFlatHeightfields, mSources); auto anotherData = makePeparedNavMeshData(3); const std::vector tooLargeWater(1, CellWater {osg::Vec2i(), Water {2, 0.0f}}); - const RecastMesh tooLargeRecastMesh {mGeneration, mRevision, mMesh, tooLargeWater, - mHeightfields, mFlatHeightfields}; + const RecastMesh tooLargeRecastMesh(mGeneration, mRevision, mMesh, tooLargeWater, + mHeightfields, mFlatHeightfields, mSources); auto tooLargeData = makePeparedNavMeshData(10); const auto value = cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, @@ -391,7 +392,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; + const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources); auto anotherData = makePeparedNavMeshData(3); const auto firstCopy = cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData)); @@ -410,7 +411,7 @@ namespace NavMeshTilesCache cache(maxSize); const std::vector water(1, CellWater {osg::Vec2i(), Water {1, 0.0f}}); - const RecastMesh anotherRecastMesh {mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields}; + const RecastMesh anotherRecastMesh(mGeneration, mRevision, mMesh, water, mHeightfields, mFlatHeightfields, mSources); auto anotherData = makePeparedNavMeshData(3); cache.set(mAgentHalfExtents, mTilePosition, mRecastMesh, std::move(mPreparedNavMeshData)); diff --git a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp index ad28bf4053..39e57234a3 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshbuilder.cpp @@ -89,6 +89,8 @@ namespace TileBounds mBounds; const std::size_t mGeneration = 0; const std::size_t mRevision = 0; + const osg::ref_ptr mSource {nullptr}; + const ObjectTransform mObjectTransform {ESM::Position {{0, 0, 0}, {0, 0, 0}}, 0.0f}; DetourNavigatorRecastMeshBuilderTest() { @@ -115,7 +117,8 @@ namespace btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); + builder.addObject(static_cast(shape), btTransform::getIdentity(), + AreaType_ground, mSource, mObjectTransform); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ -1, -1, 0, @@ -135,7 +138,7 @@ namespace builder.addObject( static_cast(shape), btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -152,7 +155,8 @@ namespace const std::array heightfieldData {{0, 0, 0, 0}}; btHeightfieldTerrainShape shape(2, 2, heightfieldData.data(), 1, 0, 0, 2, PHY_FLOAT, false); RecastMeshBuilder builder(mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); + builder.addObject(static_cast(shape), btTransform::getIdentity(), + AreaType_ground, mSource, mObjectTransform); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ -0.5, -0.5, 0, @@ -168,7 +172,8 @@ namespace { btBoxShape shape(btVector3(1, 1, 2)); RecastMeshBuilder builder(mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); + builder.addObject(static_cast(shape), btTransform::getIdentity(), + AreaType_ground, mSource, mObjectTransform); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ -1, -1, -2, @@ -214,7 +219,7 @@ namespace builder.addObject( static_cast(shape), btTransform::getIdentity(), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -261,7 +266,7 @@ namespace builder.addObject( static_cast(shape), btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -285,7 +290,7 @@ namespace builder.addObject( static_cast(shape), btTransform(btMatrix3x3::getIdentity().scaled(btVector3(1, 2, 3)), btVector3(1, 2, 3)), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -307,7 +312,7 @@ namespace builder.addObject( static_cast(shape), btTransform::getIdentity(), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -334,7 +339,7 @@ namespace builder.addObject( static_cast(shape), btTransform::getIdentity(), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -359,7 +364,7 @@ namespace static_cast(shape), btTransform(btQuaternion(btVector3(1, 0, 0), static_cast(-osg::PI_4))), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5), std::vector({ @@ -384,7 +389,7 @@ namespace static_cast(shape), btTransform(btQuaternion(btVector3(0, 1, 0), static_cast(osg::PI_4))), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5), std::vector({ @@ -409,7 +414,7 @@ namespace static_cast(shape), btTransform(btQuaternion(btVector3(0, 0, 1), static_cast(osg::PI_4))), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_THAT(recastMesh->getMesh().getVertices(), Pointwise(FloatNear(1e-5), std::vector({ @@ -433,12 +438,12 @@ namespace builder.addObject( static_cast(shape1), btTransform::getIdentity(), - AreaType_ground + AreaType_ground, mSource, mObjectTransform ); builder.addObject( static_cast(shape2), btTransform::getIdentity(), - AreaType_null + AreaType_null, mSource, mObjectTransform ); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ @@ -471,7 +476,7 @@ namespace btBvhTriangleMeshShape shape(&mesh, true); RecastMeshBuilder builder(mBounds); - builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground); + builder.addObject(static_cast(shape), btTransform::getIdentity(), AreaType_ground, mSource, mObjectTransform); const auto recastMesh = std::move(builder).create(mGeneration, mRevision); EXPECT_EQ(recastMesh->getMesh().getVertices(), std::vector({ -1, -1, 0, diff --git a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp index 7751d5220c..ff0d3e519c 100644 --- a/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp +++ b/apps/openmw_test_suite/detournavigator/recastmeshobject.cpp @@ -1,6 +1,7 @@ #include "operators.hpp" #include +#include #include #include @@ -15,10 +16,11 @@ namespace struct DetourNavigatorRecastMeshObjectTest : Test { btBoxShape mBoxShapeImpl {btVector3(1, 2, 3)}; - CollisionShape mBoxShape {nullptr, mBoxShapeImpl}; + const ObjectTransform mObjectTransform {ESM::Position {{1, 2, 3}, {1, 2, 3}}, 0.5f}; + CollisionShape mBoxShape {nullptr, mBoxShapeImpl, mObjectTransform}; btCompoundShape mCompoundShapeImpl {true}; - CollisionShape mCompoundShape {nullptr, mCompoundShapeImpl}; - btTransform mTransform {btQuaternion(btVector3(1, 2, 3), 1), btVector3(1, 2, 3)}; + CollisionShape mCompoundShape {nullptr, mCompoundShapeImpl, mObjectTransform}; + btTransform mTransform {Misc::Convert::makeBulletTransform(mObjectTransform.mPosition)}; DetourNavigatorRecastMeshObjectTest() { diff --git a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp index 3667e946e0..eac7f4abbd 100644 --- a/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp +++ b/apps/openmw_test_suite/detournavigator/tilecachedrecastmeshmanager.cpp @@ -17,6 +17,9 @@ namespace { Settings mSettings; std::vector mChangedTiles; + const ObjectTransform mObjectTransform {ESM::Position {{0, 0, 0}, {0, 0, 0}}, 0.0f}; + const osg::ref_ptr mShape = new Resource::BulletShape; + const osg::ref_ptr mInstance = new Resource::BulletShapeInstance(mShape); DetourNavigatorTileCachedRecastMeshManagerTest() { @@ -56,7 +59,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); EXPECT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); } @@ -64,7 +67,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_FALSE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); } @@ -73,7 +76,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); for (int x = -1; x < 1; ++x) for (int y = -1; y < 1; ++y) @@ -85,7 +88,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); EXPECT_TRUE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [&] (const auto& v) { onChangedTile(v); })); @@ -100,7 +103,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_FALSE(manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [&] (const auto& v) { onChangedTile(v); })); @@ -111,7 +114,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr); EXPECT_NE(manager.getMesh(TilePosition(-1, 0)), nullptr); @@ -123,7 +126,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_EQ(manager.getMesh(TilePosition(1, 0)), nullptr); } @@ -133,7 +136,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); EXPECT_NE(manager.getMesh(TilePosition(0, -1)), nullptr); @@ -153,7 +156,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); EXPECT_EQ(manager.getMesh(TilePosition(-1, -1)), nullptr); @@ -168,7 +171,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); manager.removeObject(ObjectId(&boxShape)); EXPECT_EQ(manager.getMesh(TilePosition(-1, -1)), nullptr); @@ -181,7 +184,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_NE(manager.getMesh(TilePosition(-1, -1)), nullptr); @@ -201,7 +204,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const auto initialRevision = manager.getRevision(); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); EXPECT_EQ(manager.getRevision(), initialRevision + 1); } @@ -210,7 +213,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); const auto beforeAddRevision = manager.getRevision(); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); @@ -222,7 +225,7 @@ namespace TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); const btTransform transform(btMatrix3x3::getIdentity(), btVector3(getTileSize(mSettings) / mSettings.mRecastScaleFactor, 0, 0)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, transform, AreaType::AreaType_ground); const auto beforeUpdateRevision = manager.getRevision(); manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {}); @@ -233,7 +236,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); const auto beforeUpdateRevision = manager.getRevision(); manager.updateObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground, [] (auto) {}); @@ -244,7 +247,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground); const auto beforeRemoveRevision = manager.getRevision(); manager.removeObject(ObjectId(&boxShape)); @@ -282,7 +285,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); const osg::Vec2i cellPosition(0, 0); const int cellSize = std::numeric_limits::max(); @@ -325,7 +328,7 @@ namespace { TileCachedRecastMeshManager manager(mSettings); const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); const osg::Vec2i cellPosition(0, 0); const int cellSize = 8192; @@ -342,7 +345,7 @@ namespace const osg::Vec2i cellPosition(0, 0); const int cellSize = 8192; const btBoxShape boxShape(btVector3(20, 20, 100)); - const CollisionShape shape(nullptr, boxShape); + const CollisionShape shape(mInstance, boxShape, mObjectTransform); ASSERT_TRUE(manager.addObject(ObjectId(&boxShape), shape, btTransform::getIdentity(), AreaType::AreaType_ground)); ASSERT_TRUE(manager.addWater(cellPosition, cellSize, 0.0f)); ASSERT_TRUE(manager.removeObject(ObjectId(&boxShape))); diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index dd1ac36d91..b145f61332 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -203,6 +203,7 @@ add_component_dir(detournavigator preparednavmeshdata navmeshcacheitem navigatorutils + generatenavmeshtile ) add_component_dir(loadinglistener diff --git a/components/detournavigator/areatype.hpp b/components/detournavigator/areatype.hpp index 9d99421af0..125b7ed7b9 100644 --- a/components/detournavigator/areatype.hpp +++ b/components/detournavigator/areatype.hpp @@ -3,6 +3,8 @@ #include +#include + namespace DetourNavigator { enum AreaType : unsigned char @@ -21,6 +23,19 @@ namespace DetourNavigator float mPathgrid = 1.0f; float mGround = 1.0f; }; + + inline std::ostream& operator<<(std::ostream& stream, AreaType value) + { + switch (value) + { + case AreaType_null: return stream << "null"; + case AreaType_water: return stream << "water"; + case AreaType_door: return stream << "door"; + case AreaType_pathgrid: return stream << "pathgrid"; + case AreaType_ground: return stream << "ground"; + } + return stream << "unknown area type (" << static_cast>(value) << ")"; + } } #endif diff --git a/components/detournavigator/navigator.hpp b/components/detournavigator/navigator.hpp index 6070a19fa8..9ffe062fe5 100644 --- a/components/detournavigator/navigator.hpp +++ b/components/detournavigator/navigator.hpp @@ -6,6 +6,7 @@ #include "recastmeshtiles.hpp" #include "waitconditiontype.hpp" #include "heightfieldshape.hpp" +#include "objecttransform.hpp" #include @@ -27,10 +28,14 @@ namespace DetourNavigator struct ObjectShapes { osg::ref_ptr mShapeInstance; + ObjectTransform mTransform; - ObjectShapes(const osg::ref_ptr& shapeInstance) + ObjectShapes(const osg::ref_ptr& shapeInstance, const ObjectTransform& transform) : mShapeInstance(shapeInstance) - {} + , mTransform(transform) + { + assert(mShapeInstance != nullptr); + } }; struct DoorShapes : ObjectShapes @@ -39,8 +44,8 @@ namespace DetourNavigator osg::Vec3f mConnectionEnd; DoorShapes(const osg::ref_ptr& shapeInstance, - const osg::Vec3f& connectionStart,const osg::Vec3f& connectionEnd) - : ObjectShapes(shapeInstance) + const ObjectTransform& transform, const osg::Vec3f& connectionStart, const osg::Vec3f& connectionEnd) + : ObjectShapes(shapeInstance, transform) , mConnectionStart(connectionStart) , mConnectionEnd(connectionEnd) {} diff --git a/components/detournavigator/navigatorimpl.cpp b/components/detournavigator/navigatorimpl.cpp index f209a24c2c..9092624ca3 100644 --- a/components/detournavigator/navigatorimpl.cpp +++ b/components/detournavigator/navigatorimpl.cpp @@ -34,12 +34,12 @@ namespace DetourNavigator bool NavigatorImpl::addObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { - CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape}; + const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform); bool result = mNavMeshManager.addObject(id, collisionShape, transform, AreaType_ground); if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get()) { const ObjectId avoidId(avoidShape); - CollisionShape avoidCollisionShape {shapes.mShapeInstance, *avoidShape}; + const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform); if (mNavMeshManager.addObject(avoidId, avoidCollisionShape, transform, AreaType_null)) { updateAvoidShapeId(id, avoidId); @@ -64,12 +64,12 @@ namespace DetourNavigator bool NavigatorImpl::updateObject(const ObjectId id, const ObjectShapes& shapes, const btTransform& transform) { - const CollisionShape collisionShape {shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape}; + const CollisionShape collisionShape(shapes.mShapeInstance, *shapes.mShapeInstance->mCollisionShape, shapes.mTransform); bool result = mNavMeshManager.updateObject(id, collisionShape, transform, AreaType_ground); if (const btCollisionShape* const avoidShape = shapes.mShapeInstance->mAvoidCollisionShape.get()) { const ObjectId avoidId(avoidShape); - const CollisionShape avoidCollisionShape {shapes.mShapeInstance, *avoidShape}; + const CollisionShape avoidCollisionShape(shapes.mShapeInstance, *avoidShape, shapes.mTransform); if (mNavMeshManager.updateObject(avoidId, avoidCollisionShape, transform, AreaType_null)) { updateAvoidShapeId(id, avoidId); diff --git a/components/detournavigator/objecttransform.hpp b/components/detournavigator/objecttransform.hpp new file mode 100644 index 0000000000..2da9a25348 --- /dev/null +++ b/components/detournavigator/objecttransform.hpp @@ -0,0 +1,27 @@ +#ifndef OPENMW_COMPONENTS_DETOURNAVIGATOR_OBJECTTRANSFORM_H +#define OPENMW_COMPONENTS_DETOURNAVIGATOR_OBJECTTRANSFORM_H + +#include + +#include + +namespace DetourNavigator +{ + struct ObjectTransform + { + ESM::Position mPosition; + float mScale; + + friend inline auto tie(const ObjectTransform& v) + { + return std::tie(v.mPosition, v.mScale); + } + + friend inline bool operator<(const ObjectTransform& l, const ObjectTransform& r) + { + return tie(l) < tie(r); + } + }; +} + +#endif diff --git a/components/detournavigator/recastmesh.cpp b/components/detournavigator/recastmesh.cpp index 93a0e171a1..16220d74f1 100644 --- a/components/detournavigator/recastmesh.cpp +++ b/components/detournavigator/recastmesh.cpp @@ -19,13 +19,15 @@ namespace DetourNavigator } RecastMesh::RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector water, - std::vector heightfields, std::vector flatHeightfields) + std::vector heightfields, std::vector flatHeightfields, + std::vector meshSources) : mGeneration(generation) , mRevision(revision) , mMesh(std::move(mesh)) , mWater(std::move(water)) , mHeightfields(std::move(heightfields)) , mFlatHeightfields(std::move(flatHeightfields)) + , mMeshSources(std::move(meshSources)) { mWater.shrink_to_fit(); mHeightfields.shrink_to_fit(); diff --git a/components/detournavigator/recastmesh.hpp b/components/detournavigator/recastmesh.hpp index 3cfe9e1cab..df9d6414d5 100644 --- a/components/detournavigator/recastmesh.hpp +++ b/components/detournavigator/recastmesh.hpp @@ -4,8 +4,10 @@ #include "areatype.hpp" #include "bounds.hpp" #include "tilebounds.hpp" +#include "objecttransform.hpp" #include +#include #include #include @@ -119,11 +121,19 @@ namespace DetourNavigator return tie(lhs) < tie(rhs); } + struct MeshSource + { + osg::ref_ptr mShape; + ObjectTransform mObjectTransform; + AreaType mAreaType; + }; + class RecastMesh { public: RecastMesh(std::size_t generation, std::size_t revision, Mesh mesh, std::vector water, - std::vector heightfields, std::vector flatHeightfields); + std::vector heightfields, std::vector flatHeightfields, + std::vector sources); std::size_t getGeneration() const { @@ -152,6 +162,8 @@ namespace DetourNavigator return mFlatHeightfields; } + const std::vector& getMeshSources() const noexcept { return mMeshSources; } + private: std::size_t mGeneration; std::size_t mRevision; @@ -159,6 +171,7 @@ namespace DetourNavigator std::vector mWater; std::vector mHeightfields; std::vector mFlatHeightfields; + std::vector mMeshSources; friend inline std::size_t getSize(const RecastMesh& value) noexcept { diff --git a/components/detournavigator/recastmeshbuilder.cpp b/components/detournavigator/recastmeshbuilder.cpp index b54b927696..0f7552aa77 100644 --- a/components/detournavigator/recastmeshbuilder.cpp +++ b/components/detournavigator/recastmeshbuilder.cpp @@ -133,6 +133,13 @@ namespace DetourNavigator { } + void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform, + const AreaType areaType, osg::ref_ptr source, const ObjectTransform& objectTransform) + { + addObject(shape, transform, areaType); + mSources.push_back(MeshSource {std::move(source), objectTransform, areaType}); + } + void RecastMeshBuilder::addObject(const btCollisionShape& shape, const btTransform& transform, const AreaType areaType) { @@ -261,7 +268,8 @@ namespace DetourNavigator std::sort(mWater.begin(), mWater.end()); Mesh mesh = makeMesh(std::move(mTriangles)); return std::make_shared(generation, revision, std::move(mesh), std::move(mWater), - std::move(mHeightfields), std::move(mFlatHeightfields)); + std::move(mHeightfields), std::move(mFlatHeightfields), + std::move(mSources)); } void RecastMeshBuilder::addObject(const btConcaveShape& shape, const btTransform& transform, diff --git a/components/detournavigator/recastmeshbuilder.hpp b/components/detournavigator/recastmeshbuilder.hpp index 4bdcb788e3..d0848c2a45 100644 --- a/components/detournavigator/recastmeshbuilder.hpp +++ b/components/detournavigator/recastmeshbuilder.hpp @@ -4,6 +4,8 @@ #include "recastmesh.hpp" #include "tilebounds.hpp" +#include + #include #include @@ -38,7 +40,8 @@ namespace DetourNavigator public: explicit RecastMeshBuilder(const TileBounds& bounds) noexcept; - void addObject(const btCollisionShape& shape, const btTransform& transform, const AreaType areaType); + void addObject(const btCollisionShape& shape, const btTransform& transform, const AreaType areaType, + osg::ref_ptr source, const ObjectTransform& objectTransform); void addObject(const btCompoundShape& shape, const btTransform& transform, const AreaType areaType); @@ -63,6 +66,9 @@ namespace DetourNavigator std::vector mWater; std::vector mHeightfields; std::vector mFlatHeightfields; + std::vector mSources; + + inline void addObject(const btCollisionShape& shape, const btTransform& transform, const AreaType areaType); void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback); diff --git a/components/detournavigator/recastmeshmanager.cpp b/components/detournavigator/recastmeshmanager.cpp index 4772ec74a9..a7b24766fc 100644 --- a/components/detournavigator/recastmeshmanager.cpp +++ b/components/detournavigator/recastmeshmanager.cpp @@ -122,7 +122,8 @@ namespace DetourNavigator { RecastMeshBuilder builder(mTileBounds); using Object = std::tuple< - osg::ref_ptr, + osg::ref_ptr, + ObjectTransform, std::reference_wrapper, btTransform, AreaType @@ -139,12 +140,13 @@ namespace DetourNavigator for (const auto& [k, object] : mObjects) { const RecastMeshObject& impl = object.getImpl(); - objects.emplace_back(impl.getHolder(), impl.getShape(), impl.getTransform(), impl.getAreaType()); + objects.emplace_back(impl.getInstance(), impl.getObjectTransform(), impl.getShape(), + impl.getTransform(), impl.getAreaType()); } revision = mRevision; } - for (const auto& [holder, shape, transform, areaType] : objects) - builder.addObject(shape, transform, areaType); + for (const auto& [instance, objectTransform, shape, transform, areaType] : objects) + builder.addObject(shape, transform, areaType, instance->getSource(), objectTransform); return std::move(builder).create(mGeneration, revision); } diff --git a/components/detournavigator/recastmeshobject.cpp b/components/detournavigator/recastmeshobject.cpp index 31aa13a208..343aeeb39e 100644 --- a/components/detournavigator/recastmeshobject.cpp +++ b/components/detournavigator/recastmeshobject.cpp @@ -75,7 +75,8 @@ namespace DetourNavigator RecastMeshObject::RecastMeshObject(const CollisionShape& shape, const btTransform& transform, const AreaType areaType) - : mHolder(shape.getHolder()) + : mInstance(shape.getInstance()) + , mObjectTransform(shape.getObjectTransform()) , mImpl(shape.getShape(), transform, areaType) { } diff --git a/components/detournavigator/recastmeshobject.hpp b/components/detournavigator/recastmeshobject.hpp index e833ee37e3..760774353c 100644 --- a/components/detournavigator/recastmeshobject.hpp +++ b/components/detournavigator/recastmeshobject.hpp @@ -2,6 +2,9 @@ #define OPENMW_COMPONENTS_DETOURNAVIGATOR_RECASTMESHOBJECT_H #include "areatype.hpp" +#include "objecttransform.hpp" + +#include #include @@ -19,17 +22,21 @@ namespace DetourNavigator class CollisionShape { public: - CollisionShape(osg::ref_ptr holder, const btCollisionShape& shape) - : mHolder(std::move(holder)) + CollisionShape(osg::ref_ptr instance, const btCollisionShape& shape, + const ObjectTransform& transform) + : mInstance(std::move(instance)) , mShape(shape) + , mObjectTransform(transform) {} - const osg::ref_ptr& getHolder() const { return mHolder; } + const osg::ref_ptr& getInstance() const { return mInstance; } const btCollisionShape& getShape() const { return mShape; } + const ObjectTransform& getObjectTransform() const { return mObjectTransform; } private: - osg::ref_ptr mHolder; + osg::ref_ptr mInstance; std::reference_wrapper mShape; + ObjectTransform mObjectTransform; }; class ChildRecastMeshObject @@ -60,7 +67,7 @@ namespace DetourNavigator bool update(const btTransform& transform, const AreaType areaType) { return mImpl.update(transform, areaType); } - const osg::ref_ptr& getHolder() const { return mHolder; } + const osg::ref_ptr& getInstance() const { return mInstance; } const btCollisionShape& getShape() const { return mImpl.getShape(); } @@ -68,8 +75,11 @@ namespace DetourNavigator AreaType getAreaType() const { return mImpl.getAreaType(); } + const ObjectTransform& getObjectTransform() const { return mObjectTransform; } + private: - osg::ref_ptr mHolder; + osg::ref_ptr mInstance; + ObjectTransform mObjectTransform; ChildRecastMeshObject mImpl; }; } diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index 254e66ec3a..e793c6fea7 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -3,6 +3,8 @@ #include +#include + #include namespace ESM @@ -59,6 +61,12 @@ struct Position { return osg::Vec3f(rot[0], rot[1], rot[2]); } + + friend inline bool operator<(const Position& l, const Position& r) + { + const auto tuple = [] (const Position& v) { return std::tuple(v.asVec3(), v.asRotationVec3()); }; + return tuple(l) < tuple(r); + } }; #pragma pack(pop) diff --git a/components/misc/convert.hpp b/components/misc/convert.hpp index 6f4a55cfcc..45f3504dc1 100644 --- a/components/misc/convert.hpp +++ b/components/misc/convert.hpp @@ -67,6 +67,11 @@ namespace Convert { return makeBulletQuaternion(position.rot); } + + inline btTransform makeBulletTransform(const ESM::Position& position) + { + return btTransform(makeBulletQuaternion(position), toBullet(position.asVec3())); + } } }