mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 08:45:32 +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();
|
const auto recastMesh = builder.create();
|
||||||
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
EXPECT_EQ(recastMesh->getVertices(), std::vector<float>({
|
||||||
0.707107067108154296875, 0, -3.535533905029296875,
|
1.41421353816986083984375, 0, 1.1920928955078125e-07,
|
||||||
-0.70710659027099609375, 0, -3.535533905029296875,
|
-1.41421353816986083984375, 0, -1.1920928955078125e-07,
|
||||||
2.384185791015625e-07, 0, -4.24264049530029296875,
|
1.1920928955078125e-07, 0, -1.41421353816986083984375,
|
||||||
}));
|
}));
|
||||||
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
EXPECT_EQ(recastMesh->getIndices(), std::vector<int>({0, 1, 2}));
|
||||||
EXPECT_EQ(recastMesh->getAreaTypes(), std::vector<AreaType>({AreaType_ground}));
|
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)
|
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";
|
Log(Debug::Debug) << "Stop navigator jobs processing";
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "settingsutils.hpp"
|
#include "settingsutils.hpp"
|
||||||
#include "exceptions.hpp"
|
#include "exceptions.hpp"
|
||||||
|
|
||||||
|
#include <components/bullethelpers/transformboundingbox.hpp>
|
||||||
#include <components/bullethelpers/processtrianglecallback.hpp>
|
#include <components/bullethelpers/processtrianglecallback.hpp>
|
||||||
#include <components/misc/convert.hpp>
|
#include <components/misc/convert.hpp>
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@
|
||||||
#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 <LinearMath/btTransform.h>
|
||||||
|
#include <LinearMath/btAabbUtil2.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ namespace DetourNavigator
|
||||||
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(triangle[i - 1]);
|
||||||
mAreaTypes.push_back(areaType);
|
mAreaTypes.push_back(areaType);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -68,7 +70,7 @@ namespace DetourNavigator
|
||||||
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(triangle[i]);
|
||||||
mAreaTypes.push_back(areaType);
|
mAreaTypes.push_back(areaType);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -131,8 +133,34 @@ namespace DetourNavigator
|
||||||
|
|
||||||
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
shape.getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||||
|
|
||||||
aabbMin = transform(aabbMin);
|
const btVector3 boundsMin(mBounds.mMin.x(), mBounds.mMin.y(),
|
||||||
aabbMax = transform(aabbMax);
|
-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::max(mBounds.mMin.x(), aabbMin.x()));
|
||||||
aabbMin.setX(std::min(mBounds.mMax.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::max(mBounds.mMin.y(), aabbMax.y()));
|
||||||
aabbMax.setY(std::min(mBounds.mMax.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);
|
auto wrapper = makeProcessTriangleCallback([&] (btVector3* triangle, int partId, int triangleIndex)
|
||||||
aabbMax = inversedTransform(aabbMax);
|
{
|
||||||
|
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()));
|
shape.processAllTriangles(&wrapper, aabbMin, aabbMax);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecastMeshBuilder::addTriangleVertex(const btVector3& worldPosition)
|
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 btConcaveShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||||
|
|
||||||
|
void addObject(const btHeightfieldTerrainShape& shape, const btTransform& transform, btTriangleCallback&& callback);
|
||||||
|
|
||||||
void addTriangleVertex(const btVector3& worldPosition);
|
void addTriangleVertex(const btVector3& worldPosition);
|
||||||
|
|
||||||
void addVertex(const btVector3& worldPosition);
|
void addVertex(const btVector3& worldPosition);
|
||||||
|
|
|
@ -176,12 +176,12 @@ recast scale factor
|
||||||
|
|
||||||
:Type: floating point
|
:Type: floating point
|
||||||
:Range: > 0.0
|
:Range: > 0.0
|
||||||
:Default: 0.023529411764705882
|
:Default: 0.029411764705882353
|
||||||
|
|
||||||
Scale of nav mesh coordinates to world coordinates. Recastnavigation builds voxels for world geometry.
|
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
|
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:
|
"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.
|
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.
|
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.
|
# 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
|
# 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:
|
# "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)
|
||||||
recast scale factor = 0.023529411764705882
|
recast scale factor = 0.029411764705882353
|
||||||
|
|
||||||
# The z-axis cell size to use for fields. (value > 0.0)
|
# The z-axis cell size to use for fields. (value > 0.0)
|
||||||
# Defines voxel/grid/cell size. So their values have significant
|
# 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
|
max simplification error = 1.3
|
||||||
|
|
||||||
# The width and height of each tile. (value > 0)
|
# 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)
|
# The size of the non-navigable border around the heightfield. (value >= 0)
|
||||||
border size = 16
|
border size = 16
|
||||||
|
|
Loading…
Reference in a new issue