Fix issues in HeightFieldShape
This commit is contained in:
parent
be4cbbffd9
commit
4931e1450a
|
@ -76,7 +76,7 @@ void AABB::mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if the current AABB contains the AABB given in parameter
|
// Return true if the current AABB contains the AABB given in parameter
|
||||||
bool AABB::contains(const AABB& aabb) {
|
bool AABB::contains(const AABB& aabb) const {
|
||||||
|
|
||||||
bool isInside = true;
|
bool isInside = true;
|
||||||
isInside = isInside && mMinCoordinates.x <= aabb.mMinCoordinates.x;
|
isInside = isInside && mMinCoordinates.x <= aabb.mMinCoordinates.x;
|
||||||
|
|
|
@ -101,7 +101,10 @@ class AABB {
|
||||||
void mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2);
|
void mergeTwoAABBs(const AABB& aabb1, const AABB& aabb2);
|
||||||
|
|
||||||
/// Return true if the current AABB contains the AABB given in parameter
|
/// Return true if the current AABB contains the AABB given in parameter
|
||||||
bool contains(const AABB& aabb);
|
bool contains(const AABB& aabb) const;
|
||||||
|
|
||||||
|
/// Return true if a point is inside the AABB
|
||||||
|
bool contains(const Vector3& point) const;
|
||||||
|
|
||||||
/// Return true if the AABB of a triangle intersects the AABB
|
/// Return true if the AABB of a triangle intersects the AABB
|
||||||
bool testCollisionTriangleAABB(const Vector3* trianglePoints) const;
|
bool testCollisionTriangleAABB(const Vector3* trianglePoints) const;
|
||||||
|
@ -188,6 +191,14 @@ inline bool AABB::testCollisionTriangleAABB(const Vector3* trianglePoints) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true if a point is inside the AABB
|
||||||
|
inline bool AABB::contains(const Vector3& point) const {
|
||||||
|
|
||||||
|
return (point.x >= mMinCoordinates.x - MACHINE_EPSILON && point.x <= mMaxCoordinates.x + MACHINE_EPSILON &&
|
||||||
|
point.y >= mMinCoordinates.y - MACHINE_EPSILON && point.y <= mMaxCoordinates.y + MACHINE_EPSILON &&
|
||||||
|
point.z >= mMinCoordinates.z - MACHINE_EPSILON && point.z <= mMaxCoordinates.z + MACHINE_EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
// Assignment operator
|
// Assignment operator
|
||||||
inline AABB& AABB::operator=(const AABB& aabb) {
|
inline AABB& AABB::operator=(const AABB& aabb) {
|
||||||
if (this != &aabb) {
|
if (this != &aabb) {
|
||||||
|
|
|
@ -118,9 +118,6 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||||
/// Dynamic AABB tree to accelerate collision with the triangles
|
/// Dynamic AABB tree to accelerate collision with the triangles
|
||||||
DynamicAABBTree mDynamicAABBTree;
|
DynamicAABBTree mDynamicAABBTree;
|
||||||
|
|
||||||
/// Raycast test type for the triangle (front, back, front-back)
|
|
||||||
TriangleRaycastSide mRaycastTestType;
|
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Private copy-constructor
|
/// Private copy-constructor
|
||||||
|
@ -163,12 +160,6 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||||
/// Use a callback method on all triangles of the concave shape inside a given AABB
|
/// Use a callback method on all triangles of the concave shape inside a given AABB
|
||||||
virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const;
|
virtual void testAllTriangles(TriangleCallback& callback, const AABB& localAABB) const;
|
||||||
|
|
||||||
/// Return the raycast test type (front, back, front-back)
|
|
||||||
TriangleRaycastSide getRaycastTestType() const;
|
|
||||||
|
|
||||||
// Set the raycast test type (front, back, front-back)
|
|
||||||
void setRaycastTestType(TriangleRaycastSide testType);
|
|
||||||
|
|
||||||
// ---------- Friendship ----------- //
|
// ---------- Friendship ----------- //
|
||||||
|
|
||||||
friend class ConvexTriangleAABBOverlapCallback;
|
friend class ConvexTriangleAABBOverlapCallback;
|
||||||
|
@ -239,19 +230,6 @@ inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId)
|
||||||
mTriangleTestCallback.testTriangle(trianglePoints);
|
mTriangleTestCallback.testTriangle(trianglePoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the raycast test type (front, back, front-back)
|
|
||||||
inline TriangleRaycastSide ConcaveMeshShape::getRaycastTestType() const {
|
|
||||||
return mRaycastTestType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the raycast test type (front, back, front-back)
|
|
||||||
/**
|
|
||||||
* @param testType Raycast test type for the triangle (front, back, front-back)
|
|
||||||
*/
|
|
||||||
inline void ConcaveMeshShape::setRaycastTestType(TriangleRaycastSide testType) {
|
|
||||||
mRaycastTestType = testType;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ using namespace reactphysics3d;
|
||||||
// Constructor
|
// Constructor
|
||||||
ConcaveShape::ConcaveShape(CollisionShapeType type)
|
ConcaveShape::ConcaveShape(CollisionShapeType type)
|
||||||
: CollisionShape(type), mIsSmoothMeshCollisionEnabled(false),
|
: CollisionShape(type), mIsSmoothMeshCollisionEnabled(false),
|
||||||
mTriangleMargin(0) {
|
mTriangleMargin(0), mRaycastTestType(FRONT) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
#include "CollisionShape.h"
|
#include "CollisionShape.h"
|
||||||
|
#include "TriangleShape.h"
|
||||||
|
|
||||||
// ReactPhysics3D namespace
|
// ReactPhysics3D namespace
|
||||||
namespace reactphysics3d {
|
namespace reactphysics3d {
|
||||||
|
@ -64,6 +65,9 @@ class ConcaveShape : public CollisionShape {
|
||||||
// Margin use for collision detection for each triangle
|
// Margin use for collision detection for each triangle
|
||||||
decimal mTriangleMargin;
|
decimal mTriangleMargin;
|
||||||
|
|
||||||
|
/// Raycast test type for the triangle (front, back, front-back)
|
||||||
|
TriangleRaycastSide mRaycastTestType;
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Private copy-constructor
|
/// Private copy-constructor
|
||||||
|
@ -88,6 +92,12 @@ class ConcaveShape : public CollisionShape {
|
||||||
/// Return the triangle margin
|
/// Return the triangle margin
|
||||||
decimal getTriangleMargin() const;
|
decimal getTriangleMargin() const;
|
||||||
|
|
||||||
|
/// Return the raycast test type (front, back, front-back)
|
||||||
|
TriangleRaycastSide getRaycastTestType() const;
|
||||||
|
|
||||||
|
// Set the raycast test type (front, back, front-back)
|
||||||
|
void setRaycastTestType(TriangleRaycastSide testType);
|
||||||
|
|
||||||
/// Return true if the collision shape is convex, false if it is concave
|
/// Return true if the collision shape is convex, false if it is concave
|
||||||
virtual bool isConvex() const;
|
virtual bool isConvex() const;
|
||||||
|
|
||||||
|
@ -129,6 +139,19 @@ inline void ConcaveShape::setIsSmoothMeshCollisionEnabled(bool isEnabled) {
|
||||||
mIsSmoothMeshCollisionEnabled = isEnabled;
|
mIsSmoothMeshCollisionEnabled = isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the raycast test type (front, back, front-back)
|
||||||
|
inline TriangleRaycastSide ConcaveShape::getRaycastTestType() const {
|
||||||
|
return mRaycastTestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the raycast test type (front, back, front-back)
|
||||||
|
/**
|
||||||
|
* @param testType Raycast test type for the triangle (front, back, front-back)
|
||||||
|
*/
|
||||||
|
inline void ConcaveShape::setRaycastTestType(TriangleRaycastSide testType) {
|
||||||
|
mRaycastTestType = testType;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -192,7 +192,48 @@ void HeightFieldShape::computeMinMaxGridCoordinates(int* minCoords, int* maxCoor
|
||||||
/// the ray hits many triangles.
|
/// the ray hits many triangles.
|
||||||
bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
bool HeightFieldShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||||
|
|
||||||
|
// TODO : Implement raycasting without using an AABB for the ray
|
||||||
|
// but using a dynamic AABB tree or octree instead
|
||||||
|
|
||||||
PROFILE("HeightFieldShape::raycast()");
|
PROFILE("HeightFieldShape::raycast()");
|
||||||
|
|
||||||
// TODO : Implement this
|
TriangleOverlapCallback triangleCallback(ray, proxyShape, raycastInfo, *this);
|
||||||
|
|
||||||
|
// Compute the AABB for the ray
|
||||||
|
const Vector3 rayEnd = ray.point1 + ray.maxFraction * (ray.point2 - ray.point1);
|
||||||
|
const AABB rayAABB(Vector3::min(ray.point1, rayEnd), Vector3::max(ray.point1, rayEnd));
|
||||||
|
|
||||||
|
testAllTriangles(triangleCallback, rayAABB);
|
||||||
|
|
||||||
|
return triangleCallback.getIsHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raycast test between a ray and a triangle of the heightfield
|
||||||
|
void TriangleOverlapCallback::testTriangle(const Vector3* trianglePoints) {
|
||||||
|
|
||||||
|
// Create a triangle collision shape
|
||||||
|
decimal margin = mHeightFieldShape.getTriangleMargin();
|
||||||
|
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2], margin);
|
||||||
|
triangleShape.setRaycastTestType(mHeightFieldShape.getRaycastTestType());
|
||||||
|
|
||||||
|
// Ray casting test against the collision shape
|
||||||
|
RaycastInfo raycastInfo;
|
||||||
|
bool isTriangleHit = triangleShape.raycast(mRay, raycastInfo, mProxyShape);
|
||||||
|
|
||||||
|
// If the ray hit the collision shape
|
||||||
|
if (isTriangleHit && raycastInfo.hitFraction <= mSmallestHitFraction) {
|
||||||
|
|
||||||
|
assert(raycastInfo.hitFraction >= decimal(0.0));
|
||||||
|
|
||||||
|
mRaycastInfo.body = raycastInfo.body;
|
||||||
|
mRaycastInfo.proxyShape = raycastInfo.proxyShape;
|
||||||
|
mRaycastInfo.hitFraction = raycastInfo.hitFraction;
|
||||||
|
mRaycastInfo.worldPoint = raycastInfo.worldPoint;
|
||||||
|
mRaycastInfo.worldNormal = raycastInfo.worldNormal;
|
||||||
|
mRaycastInfo.meshSubpart = -1;
|
||||||
|
mRaycastInfo.triangleIndex = -1;
|
||||||
|
|
||||||
|
mSmallestHitFraction = raycastInfo.hitFraction;
|
||||||
|
mIsHit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,40 @@
|
||||||
|
|
||||||
namespace reactphysics3d {
|
namespace reactphysics3d {
|
||||||
|
|
||||||
|
class HeightFieldShape;
|
||||||
|
|
||||||
|
// Class TriangleOverlapCallback
|
||||||
|
/**
|
||||||
|
* This class is used for testing AABB and triangle overlap for raycasting
|
||||||
|
*/
|
||||||
|
class TriangleOverlapCallback : public TriangleCallback {
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const Ray& mRay;
|
||||||
|
ProxyShape* mProxyShape;
|
||||||
|
RaycastInfo& mRaycastInfo;
|
||||||
|
bool mIsHit;
|
||||||
|
decimal mSmallestHitFraction;
|
||||||
|
const HeightFieldShape& mHeightFieldShape;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
TriangleOverlapCallback(const Ray& ray, ProxyShape* proxyShape, RaycastInfo& raycastInfo,
|
||||||
|
const HeightFieldShape& heightFieldShape)
|
||||||
|
: mRay(ray), mProxyShape(proxyShape), mRaycastInfo(raycastInfo),
|
||||||
|
mHeightFieldShape (heightFieldShape) {
|
||||||
|
mIsHit = false;
|
||||||
|
mSmallestHitFraction = mRay.maxFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getIsHit() const {return mIsHit;}
|
||||||
|
|
||||||
|
/// Raycast test between a ray and a triangle of the heightfield
|
||||||
|
virtual void testTriangle(const Vector3* trianglePoints);
|
||||||
|
};
|
||||||
|
|
||||||
// TODO : Implement raycasting for this shape
|
// TODO : Implement raycasting for this shape
|
||||||
|
|
||||||
// TODO : Implement smooth collision mesh for this shape
|
// TODO : Implement smooth collision mesh for this shape
|
||||||
|
@ -167,13 +201,19 @@ inline Vector3 HeightFieldShape::getVertexAt(int x, int y) const {
|
||||||
// Get the difference between the center of AABB and zero level of the height field
|
// Get the difference between the center of AABB and zero level of the height field
|
||||||
const decimal originToZeroHeight = (mMaxHeight - mMinHeight) * decimal(0.5);
|
const decimal originToZeroHeight = (mMaxHeight - mMinHeight) * decimal(0.5);
|
||||||
|
|
||||||
|
Vector3 vertex;
|
||||||
switch (mUpAxis) {
|
switch (mUpAxis) {
|
||||||
case 0: return Vector3(height - originToZeroHeight, -mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y) * mScaling;
|
case 0: vertex = Vector3(height - originToZeroHeight, -mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y) * mScaling;
|
||||||
case 1: return Vector3(-mWidth * decimal(0.5) + x, height - originToZeroHeight, -mLength * decimal(0.5) + y) * mScaling;
|
break;
|
||||||
case 2: return Vector3(-mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y, height - originToZeroHeight) * mScaling;
|
case 1: vertex = Vector3(-mWidth * decimal(0.5) + x, height - originToZeroHeight, -mLength * decimal(0.5) + y) * mScaling;
|
||||||
|
break;
|
||||||
|
case 2: vertex = Vector3(-mWidth * decimal(0.5) + x, -mLength * decimal(0.5) + y, height - originToZeroHeight) * mScaling;
|
||||||
|
break;
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(mAABB.contains(vertex));
|
||||||
|
return vertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the height of a given (x,y) point in the height field
|
// Return the height of a given (x,y) point in the height field
|
||||||
|
|
|
@ -119,6 +119,7 @@ class TriangleShape : public ConvexShape {
|
||||||
// ---------- Friendship ---------- //
|
// ---------- Friendship ---------- //
|
||||||
|
|
||||||
friend class ConcaveMeshRaycastCallback;
|
friend class ConcaveMeshRaycastCallback;
|
||||||
|
friend class TriangleOverlapCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the number of bytes used by the collision shape
|
// Return the number of bytes used by the collision shape
|
||||||
|
|
|
@ -229,13 +229,23 @@ class TestAABB : public Test {
|
||||||
|
|
||||||
void testIntersection() {
|
void testIntersection() {
|
||||||
|
|
||||||
// -------- Test contains() -------- //
|
// -------- Test contains(AABB) -------- //
|
||||||
test(!mAABB1.contains(mAABB2));
|
test(!mAABB1.contains(mAABB2));
|
||||||
test(mAABB3.contains(mAABB1));
|
test(mAABB3.contains(mAABB1));
|
||||||
test(!mAABB1.contains(mAABB3));
|
test(!mAABB1.contains(mAABB3));
|
||||||
test(!mAABB1.contains(mAABB4));
|
test(!mAABB1.contains(mAABB4));
|
||||||
test(!mAABB4.contains(mAABB1));
|
test(!mAABB4.contains(mAABB1));
|
||||||
|
|
||||||
|
// -------- Test contains(Vector3) -------- //
|
||||||
|
test(mAABB1.contains(Vector3(0, 0, 0)));
|
||||||
|
test(mAABB1.contains(Vector3(-5, 6, 9)));
|
||||||
|
test(mAABB1.contains(Vector3(-9, -4, -9)));
|
||||||
|
test(mAABB1.contains(Vector3(9, 4, 7)));
|
||||||
|
test(!mAABB1.contains(Vector3(-11, -4, -9)));
|
||||||
|
test(!mAABB1.contains(Vector3(1, 12, -9)));
|
||||||
|
test(!mAABB1.contains(Vector3(1, 8, -13)));
|
||||||
|
test(!mAABB1.contains(Vector3(-14, 82, -13)));
|
||||||
|
|
||||||
// -------- Test testCollision() -------- //
|
// -------- Test testCollision() -------- //
|
||||||
test(mAABB1.testCollision(mAABB2));
|
test(mAABB1.testCollision(mAABB2));
|
||||||
test(mAABB2.testCollision(mAABB1));
|
test(mAABB2.testCollision(mAABB1));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user