mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 06:53:52 +00:00
Merge pull request #2618 from elsid/fix_rope_bridge
Fix objects culling for recast mesh tiles (bug #5216)
This commit is contained in:
commit
ae80d8e490
7 changed files with 90 additions and 25 deletions
|
@ -361,9 +361,9 @@ namespace
|
|||
);
|
||||
const auto recastMesh = builder.create();
|
||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||
0.707107067108154296875, 0, -3.535533905029296875,
|
||||
-0.70710659027099609375, 0, -3.535533905029296875,
|
||||
2.384185791015625e-07, 0, -4.24264049530029296875,
|
||||
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
||||
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
||||
1.1920928955078125e-07, 0, -1.41421353816986083984375,
|
||||
}));
|
||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>({AreaType_ground}));
|
||||
|
|
38
components/bullethelpers/transformboundingbox.hpp
Normal file
38
components/bullethelpers/transformboundingbox.hpp
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef OPENMW_COMPONENTS_BULLETHELPERS_TRANSFORMBOUNDINGBOX_H
|
||||
#define OPENMW_COMPONENTS_BULLETHELPERS_TRANSFORMBOUNDINGBOX_H
|
||||
|
||||
#include <LinearMath/btVector3.h>
|
||||
#include <LinearMath/btTransform.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace BulletHelpers
|
||||
{
|
||||
inline btVector3 min(const btVector3& a, const btVector3& b)
|
||||
{
|
||||
return btVector3(std::min(a.x(), b.x()), std::min(a.y(), b.y()), std::min(a.z(), b.z()));
|
||||
}
|
||||
|
||||
inline btVector3 max(const btVector3& a, const btVector3& b)
|
||||
{
|
||||
return btVector3(std::max(a.x(), b.x()), std::max(a.y(), b.y()), std::max(a.z(), b.z()));
|
||||
}
|
||||
|
||||
// http://dev.theomader.com/transform-bounding-boxes/
|
||||
inline void transformBoundingBox(const btTransform& transform, btVector3& aabbMin, btVector3& aabbMax)
|
||||
{
|
||||
const btVector3 xa(transform.getBasis().getColumn(0) * aabbMin.x());
|
||||
const btVector3 xb(transform.getBasis().getColumn(0) * aabbMax.x());
|
||||
|
||||
const btVector3 ya(transform.getBasis().getColumn(1) * aabbMin.y());
|
||||
const btVector3 yb(transform.getBasis().getColumn(1) * aabbMax.y());
|
||||
|
||||
const btVector3 za(transform.getBasis().getColumn(2) * aabbMin.z());
|
||||
const btVector3 zb(transform.getBasis().getColumn(2) * aabbMax.z());
|
||||
|
||||
aabbMin = min(xa, xb) + min(ya, yb) + min(za, zb) + transform.getOrigin();
|
||||
aabbMax = max(xa, xb) + max(ya, yb) + max(za, zb) + transform.getOrigin();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -135,7 +135,7 @@ namespace DetourNavigator
|
|||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
Log(Debug::Error) << "AsyncNavMeshUpdater::process exception: ", e.what();
|
||||
Log(Debug::Error) << "AsyncNavMeshUpdater::process exception: " << e.what();
|
||||
}
|
||||
}
|
||||
Log(Debug::Debug) << "Stop navigator jobs processing";
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "settingsutils.hpp"
|
||||
#include "exceptions.hpp"
|
||||
|
||||
#include <components/bullethelpers/transformboundingbox.hpp>
|
||||
#include <components/bullethelpers/processtrianglecallback.hpp>
|
||||
#include <components/misc/convert.hpp>
|
||||
|
||||
|
@ -13,6 +14,7 @@
|
|||
#include <BulletCollision/CollisionShapes/btConcaveShape.h>
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
#include <LinearMath/btTransform.h>
|
||||
#include <LinearMath/btAabbUtil2.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -57,7 +59,7 @@ namespace DetourNavigator
|
|||
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||
{
|
||||
for (std::size_t i = 3; i > 0; --i)
|
||||
addTriangleVertex(transform(triangle[i - 1]));
|
||||
addTriangleVertex(triangle[i - 1]);
|
||||
mAreaTypes.push_back(areaType);
|
||||
}));
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ namespace DetourNavigator
|
|||
return addObject(shape, transform, makeProcessTriangleCallback([&] (btVector3* triangle, int, int)
|
||||
{
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
addTriangleVertex(transform(triangle[i]));
|
||||
addTriangleVertex(triangle[i]);
|
||||
mAreaTypes.push_back(areaType);
|
||||
}));
|
||||
}
|
||||
|
@ -131,8 +133,34 @@ namespace DetourNavigator
|
|||
|
||||
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||
|
||||
aabbMin = transform(aabbMin);
|
||||
aabbMax = transform(aabbMax);
|
||||
const btVector3 boundsMin(mBounds.mMin.x(), mBounds.mMin.y(),
|
||||
-std::numeric_limits<btScalar>::max() * std::numeric_limits<btScalar>::epsilon());
|
||||
const btVector3 boundsMax(mBounds.mMax.x(), mBounds.mMax.y(),
|
||||
std::numeric_limits<btScalar>::max() * std::numeric_limits<btScalar>::epsilon());
|
||||
|
||||
auto wrapper = makeProcessTriangleCallback([&] (btVector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
std::array<btVector3, 3> transformed;
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
transformed[i] = transform(triangle[i]);
|
||||
if (TestTriangleAgainstAabb2(transformed.data(), boundsMin, boundsMax))
|
||||
callback.processTriangle(transformed.data(), partId, triangleIndex);
|
||||
});
|
||||
|
||||
shape.processAllTriangles(&wrapper, aabbMin, aabbMax);
|
||||
}
|
||||
|
||||
void RecastMeshBuilder::addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform,
|
||||
btTriangleCallback&& callback)
|
||||
{
|
||||
using BulletHelpers::transformBoundingBox;
|
||||
|
||||
btVector3 aabbMin;
|
||||
btVector3 aabbMax;
|
||||
|
||||
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||
|
||||
transformBoundingBox(transform, aabbMin, aabbMax);
|
||||
|
||||
aabbMin.setX(std::max(mBounds.mMin.x(), aabbMin.x()));
|
||||
aabbMin.setX(std::min(mBounds.mMax.x(), aabbMin.x()));
|
||||
|
@ -144,20 +172,17 @@ namespace DetourNavigator
|
|||
aabbMax.setY(std::max(mBounds.mMin.y(), aabbMax.y()));
|
||||
aabbMax.setY(std::min(mBounds.mMax.y(), aabbMax.y()));
|
||||
|
||||
const auto inversedTransform = transform.inverse();
|
||||
transformBoundingBox(transform.inverse(), aabbMin, aabbMax);
|
||||
|
||||
aabbMin = inversedTransform(aabbMin);
|
||||
aabbMax = inversedTransform(aabbMax);
|
||||
auto wrapper = makeProcessTriangleCallback([&] (btVector3* triangle, int partId, int triangleIndex)
|
||||
{
|
||||
std::array<btVector3, 3> transformed;
|
||||
for (std::size_t i = 0; i < 3; ++i)
|
||||
transformed[i] = transform(triangle[i]);
|
||||
callback.processTriangle(transformed.data(), partId, triangleIndex);
|
||||
});
|
||||
|
||||
aabbMin.setX(std::min(aabbMin.x(), aabbMax.x()));
|
||||
aabbMin.setY(std::min(aabbMin.y(), aabbMax.y()));
|
||||
aabbMin.setZ(std::min(aabbMin.z(), aabbMax.z()));
|
||||
|
||||
aabbMax.setX(std::max(aabbMin.x(), aabbMax.x()));
|
||||
aabbMax.setY(std::max(aabbMin.y(), aabbMax.y()));
|
||||
aabbMax.setZ(std::max(aabbMin.z(), aabbMax.z()));
|
||||
|
||||
shape.processAllTriangles(&callback, aabbMin, aabbMax);
|
||||
shape.processAllTriangles(&wrapper, aabbMin, aabbMax);
|
||||
}
|
||||
|
||||
void RecastMeshBuilder::addTriangleVertex(const btVector3& worldPosition)
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace DetourNavigator
|
|||
|
||||
void addObject(const btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||
|
||||
void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||
|
||||
void addTriangleVertex(const btVector3& worldPosition);
|
||||
|
||||
void addVertex(const btVector3& worldPosition);
|
||||
|
|
|
@ -176,12 +176,12 @@ recast scale factor
|
|||
|
||||
:Type: floating point
|
||||
:Range: > 0.0
|
||||
:Default: 0.023529411764705882
|
||||
:Default: 0.029411764705882353
|
||||
|
||||
Scale of nav mesh coordinates to world coordinates. Recastnavigation builds voxels for world geometry.
|
||||
Basically voxel size is 1 / "cell size". To reduce amount of voxels we apply scale factor, to make voxel size
|
||||
"recast scale factor" / "cell size". Default value calculates by this equation:
|
||||
sStepSizeUp * "recast scale factor" / "cell size" = 4 (max climb height should be equal to 4 voxels).
|
||||
sStepSizeUp * "recast scale factor" / "cell size" = 5 (max climb height should be equal to 4 voxels).
|
||||
Changing this value will change generated nav mesh. Some locations may become unavailable for NPC and creatures.
|
||||
Pay attention to slopes and roofs when change it. Increasing this value will reduce nav mesh update latency.
|
||||
|
||||
|
|
|
@ -642,8 +642,8 @@ enable = true
|
|||
# Scale of NavMesh coordinates to world coordinates (value > 0.0). Recastnavigation builds voxels for world geometry.
|
||||
# Basically voxel size is 1 / "cell size". To reduce amount of voxels we apply scale factor, to make voxel size
|
||||
# "recast scale factor" / "cell size". Default value calculates by this equation:
|
||||
# sStepSizeUp * "recast scale factor" / "cell size" = 4 (max climb height should be equal to 4 voxels)
|
||||
recast scale factor = 0.023529411764705882
|
||||
# sStepSizeUp * "recast scale factor" / "cell size" = 5 (max climb height should be equal to 4 voxels)
|
||||
recast scale factor = 0.029411764705882353
|
||||
|
||||
# The z-axis cell size to use for fields. (value > 0.0)
|
||||
# Defines voxel/grid/cell size. So their values have significant
|
||||
|
@ -671,7 +671,7 @@ detail sample max error = 1.0
|
|||
max simplification error = 1.3
|
||||
|
||||
# The width and height of each tile. (value > 0)
|
||||
tile size = 64
|
||||
tile size = 128
|
||||
|
||||
# The size of the non-navigable border around the heightfield. (value >= 0)
|
||||
border size = 16
|
||||
|
|
Loading…
Reference in a new issue