Skip to content

Commit ff20874

Browse files
Fix issue with raycasting the HeightFieldShape with a scaling factor
1 parent cef8338 commit ff20874

File tree

8 files changed

+30
-25
lines changed

8 files changed

+30
-25
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
### Fixed
66

7+
- Issue [#378](https://github.com/DanielChappuis/reactphysics3d/issues/378) Fix issue with raycasting of HeightFieldShape
78
- Fix crash within testbed application in raycasting scene
89

910
## [0.10.0] - 2024-03-10

include/reactphysics3d/collision/HeightField.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class HeightField {
124124

125125
/// Raycast method with feedback information
126126
bool raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, TriangleRaycastSide testSide,
127-
MemoryAllocator& allocator, const Vector3& scale) const;
127+
MemoryAllocator& allocator) const;
128128

129129
/// Compute the min/max grid coords corresponding to the intersection of the AABB of the height field and the AABB to collide
130130
void computeMinMaxGridCoordinates(uint32* minCoords, uint32* maxCoords, const AABB& aabbToCollide) const;

include/reactphysics3d/collision/shapes/AABB.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
// Libraries
3030
#include <reactphysics3d/mathematics/mathematics.h>
31+
#include <reactphysics3d/configuration.h>>
3132

3233
/// ReactPhysics3D namespace
3334
namespace reactphysics3d {
@@ -101,7 +102,7 @@ class AABB {
101102
bool contains(const AABB& aabb) const;
102103

103104
/// Return true if a point is inside the AABB
104-
bool contains(const Vector3& point) const;
105+
bool contains(const Vector3& point, decimal epsilon = MACHINE_EPSILON) const;
105106

106107
/// Return true if the AABB of a triangle intersects the AABB
107108
bool testCollisionTriangleAABB(const Vector3* trianglePoints) const;
@@ -206,11 +207,11 @@ RP3D_FORCE_INLINE bool AABB::testCollisionTriangleAABB(const Vector3* trianglePo
206207
}
207208

208209
// Return true if a point is inside the AABB
209-
RP3D_FORCE_INLINE bool AABB::contains(const Vector3& point) const {
210+
RP3D_FORCE_INLINE bool AABB::contains(const Vector3& point, decimal epsilon) const {
210211

211-
return (point.x >= mMinCoordinates.x - MACHINE_EPSILON && point.x <= mMaxCoordinates.x + MACHINE_EPSILON &&
212-
point.y >= mMinCoordinates.y - MACHINE_EPSILON && point.y <= mMaxCoordinates.y + MACHINE_EPSILON &&
213-
point.z >= mMinCoordinates.z - MACHINE_EPSILON && point.z <= mMaxCoordinates.z + MACHINE_EPSILON);
212+
return (point.x >= mMinCoordinates.x - epsilon && point.x <= mMaxCoordinates.x + epsilon &&
213+
point.y >= mMinCoordinates.y - epsilon && point.y <= mMaxCoordinates.y + epsilon &&
214+
point.z >= mMinCoordinates.z - epsilon && point.z <= mMaxCoordinates.z + epsilon);
214215
}
215216

216217
// Apply a scale factor to the AABB

include/reactphysics3d/collision/shapes/ConcaveMeshShape.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
7878
const Ray& mRay;
7979
bool mIsHit;
8080
MemoryAllocator& mAllocator;
81-
const Vector3& mMeshScale;
8281

8382
#ifdef IS_RP3D_PROFILING_ENABLED
8483

@@ -91,9 +90,9 @@ class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
9190

9291
// Constructor
9392
ConcaveMeshRaycastCallback(const ConcaveMeshShape& concaveMeshShape,
94-
Collider* collider, RaycastInfo& raycastInfo, const Ray& ray, const Vector3& meshScale, MemoryAllocator& allocator)
93+
Collider* collider, RaycastInfo& raycastInfo, const Ray& ray, MemoryAllocator& allocator)
9594
: mHitAABBNodes(allocator), mConcaveMeshShape(concaveMeshShape), mCollider(collider),
96-
mRaycastInfo(raycastInfo), mRay(ray), mIsHit(false), mAllocator(allocator), mMeshScale(meshScale) {
95+
mRaycastInfo(raycastInfo), mRay(ray), mIsHit(false), mAllocator(allocator) {
9796

9897
}
9998

src/collision/HeightField.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ void HeightField::computeMinMaxGridCoordinates(uint32* minCoords, uint32* maxCoo
256256
/// Note that only the first triangle hit by the ray in the mesh will be returned, even if
257257
/// the ray hits many triangles.
258258
bool HeightField::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, TriangleRaycastSide testSide,
259-
MemoryAllocator& allocator, const Vector3& scale) const {
259+
MemoryAllocator& allocator) const {
260260

261261
RP3D_PROFILE("HeightField::raycast()", mProfiler);
262262

@@ -290,10 +290,10 @@ bool HeightField::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* co
290290
while (i >= 0 && i < nbCellsI && j >= 0 && j < nbCellsJ) {
291291

292292
// Compute the four point of the current quad
293-
const Vector3 p1 = getVertexAt(i, j) * scale;
294-
const Vector3 p2 = getVertexAt(i, j + 1) * scale;
295-
const Vector3 p3 = getVertexAt(i + 1, j) * scale;
296-
const Vector3 p4 = getVertexAt(i + 1, j + 1) * scale;
293+
const Vector3 p1 = getVertexAt(i, j);
294+
const Vector3 p2 = getVertexAt(i, j + 1);
295+
const Vector3 p3 = getVertexAt(i + 1, j);
296+
const Vector3 p4 = getVertexAt(i + 1, j + 1);
297297

298298
// Raycast against the first triangle of the cell
299299
uint32 shapeId = computeTriangleShapeId(i, j, 0);
@@ -403,7 +403,7 @@ Vector3 HeightField::getVertexAt(uint32 x, uint32 y) const {
403403

404404
const Vector3 vertex = Vector3(-mWidth * decimal(0.5) + x, mHeightOrigin + height, -mLength * decimal(0.5) + y);
405405

406-
assert(mBounds.contains(vertex));
406+
assert(mBounds.contains(vertex, decimal(0.0001)));
407407

408408
return vertex;
409409
}

src/collision/shapes/ConcaveMeshShape.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collide
186186
Ray scaledRay(ray.point1 * inverseScale, ray.point2 * inverseScale, ray.maxFraction);
187187

188188
// Create the callback object that will compute ray casting against triangles
189-
ConcaveMeshRaycastCallback raycastCallback(*this, collider, raycastInfo, scaledRay, mScale, allocator);
189+
ConcaveMeshRaycastCallback raycastCallback(*this, collider, raycastInfo, ray, allocator);
190190

191191
#ifdef IS_RP3D_PROFILING_ENABLED
192192

@@ -197,7 +197,8 @@ bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collide
197197

198198
// Ask the Dynamic AABB Tree to report all AABB nodes that are hit by the ray.
199199
// The raycastCallback object will then compute ray casting against the triangles
200-
// in the hit AABBs.
200+
// in the hit AABBs. Note that we use the inverse scaled ray here because AABBs of the TriangleMesh
201+
// are stored without scaling
201202
mTriangleMesh->raycast(scaledRay, raycastCallback);
202203

203204
raycastCallback.raycastTriangles();
@@ -239,7 +240,6 @@ void ConcaveMeshRaycastCallback::raycastTriangles() {
239240

240241
#ifdef IS_RP3D_PROFILING_ENABLED
241242

242-
243243
// Set the profiler to the triangle shape
244244
triangleShape.setProfiler(mProfiler);
245245

@@ -257,7 +257,7 @@ void ConcaveMeshRaycastCallback::raycastTriangles() {
257257
mRaycastInfo.body = raycastInfo.body;
258258
mRaycastInfo.collider = raycastInfo.collider;
259259
mRaycastInfo.hitFraction = raycastInfo.hitFraction;
260-
mRaycastInfo.worldPoint = raycastInfo.worldPoint * mMeshScale;
260+
mRaycastInfo.worldPoint = raycastInfo.worldPoint;
261261
mRaycastInfo.worldNormal = raycastInfo.worldNormal;
262262
mRaycastInfo.triangleIndex = data;
263263

src/collision/shapes/HeightFieldShape.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,20 @@ bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collide
7777

7878
RP3D_PROFILE("HeightFieldShape::raycast()", mProfiler);
7979

80-
// Apply the collision shape inverse scaling factor because the height-field is stored without scaling
80+
// Apply the height-field scale inverse scale factor because the mesh is stored without scaling
8181
// inside the dynamic AABB tree
8282
const Vector3 inverseScale(decimal(1.0) / mScale.x, decimal(1.0) / mScale.y, decimal(1.0) / mScale.z);
8383
Ray scaledRay(ray.point1 * inverseScale, ray.point2 * inverseScale, ray.maxFraction);
8484

85-
return mHeightField->raycast(scaledRay, raycastInfo, collider, getRaycastTestType(), allocator, mScale);
85+
if (mHeightField->raycast(scaledRay, raycastInfo, collider, getRaycastTestType(), allocator)) {
86+
87+
// Scale back the contact point because we used a ray scale with inverse height-field scale
88+
raycastInfo.worldPoint = raycastInfo.worldPoint * mScale;
89+
90+
return true;
91+
}
92+
93+
return false;
8694
}
8795

8896
// Return the string representation of the shape

src/systems/BroadPhaseSystem.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@ void BroadPhaseSystem::raycast(const Ray& ray, RaycastTest& raycastTest, unsigne
7373

7474
BroadPhaseRaycastCallback broadPhaseRaycastCallback(mDynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);
7575

76-
// Compute the inverse ray direction
77-
const Vector3 rayDirection = ray.point2 - ray.point1;
78-
const Vector3 rayDirectionInverse(decimal(1.0) / rayDirection.x, decimal(1.0) / rayDirection.y, decimal(1.0) / rayDirection.z);
79-
8076
mDynamicAABBTree.raycast(ray, broadPhaseRaycastCallback);
8177
}
8278

0 commit comments

Comments
 (0)