Working on triangles mesh raycasting
This commit is contained in:
parent
3ebb00fd68
commit
6ebad66acf
|
@ -252,7 +252,6 @@ void CollisionDetection::computeNarrowPhaseBetweenShapes(CollisionCallback* call
|
||||||
// For each possible collision pair of bodies
|
// For each possible collision pair of bodies
|
||||||
map<overlappingpairid, OverlappingPair*>::iterator it;
|
map<overlappingpairid, OverlappingPair*>::iterator it;
|
||||||
for (it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
for (it = mOverlappingPairs.begin(); it != mOverlappingPairs.end(); ) {
|
||||||
ContactPointInfo* contactInfo = NULL;
|
|
||||||
|
|
||||||
OverlappingPair* pair = it->second;
|
OverlappingPair* pair = it->second;
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,7 @@ class ProxyShape {
|
||||||
friend class EPAAlgorithm;
|
friend class EPAAlgorithm;
|
||||||
friend class GJKAlgorithm;
|
friend class GJKAlgorithm;
|
||||||
friend class ConvexMeshShape;
|
friend class ConvexMeshShape;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the pointer to the cached collision data
|
// Return the pointer to the cached collision data
|
||||||
|
|
|
@ -68,6 +68,12 @@ struct RaycastInfo {
|
||||||
/// The hit point "p" is such that p = point1 + hitFraction * (point2 - point1)
|
/// The hit point "p" is such that p = point1 + hitFraction * (point2 - point1)
|
||||||
decimal hitFraction;
|
decimal hitFraction;
|
||||||
|
|
||||||
|
/// Mesh subpart index that has been hit (only used for triangles mesh and -1 otherwise)
|
||||||
|
int meshSubpart;
|
||||||
|
|
||||||
|
/// Hit triangle index (only used for triangles mesh and -1 otherwise)
|
||||||
|
int triangleIndex;
|
||||||
|
|
||||||
/// Pointer to the hit collision body
|
/// Pointer to the hit collision body
|
||||||
CollisionBody* body;
|
CollisionBody* body;
|
||||||
|
|
||||||
|
@ -77,7 +83,7 @@ struct RaycastInfo {
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
RaycastInfo() : body(NULL), proxyShape(NULL) {
|
RaycastInfo() : meshSubpart(-1), triangleIndex(-1), body(NULL), proxyShape(NULL) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +114,7 @@ class RaycastCallback {
|
||||||
/// This method will be called for each ProxyShape that is hit by the
|
/// This method will be called for each ProxyShape that is hit by the
|
||||||
/// ray. You cannot make any assumptions about the order of the
|
/// ray. You cannot make any assumptions about the order of the
|
||||||
/// calls. You should use the return value to control the continuation
|
/// calls. You should use the return value to control the continuation
|
||||||
/// of the ray. The return value is the next maxFraction value to use.
|
/// of the ray. The returned value is the next maxFraction value to use.
|
||||||
/// If you return a fraction of 0.0, it means that the raycast should
|
/// If you return a fraction of 0.0, it means that the raycast should
|
||||||
/// terminate. If you return a fraction of 1.0, it indicates that the
|
/// terminate. If you return a fraction of 1.0, it indicates that the
|
||||||
/// ray is not clipped and the ray cast should continue as if no hit
|
/// ray is not clipped and the ray cast should continue as if no hit
|
||||||
|
|
|
@ -264,10 +264,15 @@ void BroadPhaseAlgorithm::notifyOverlappingNodes(int node1ID, int node2ID) {
|
||||||
mNbPotentialPairs++;
|
mNbPotentialPairs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called when a overlapping node has been found during the call to
|
||||||
|
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||||
|
void AABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
||||||
|
|
||||||
|
mBroadPhaseAlgorithm.notifyOverlappingNodes(mReferenceNodeId, nodeId);
|
||||||
|
}
|
||||||
|
|
||||||
// Called for a broad-phase shape that has to be tested for raycast
|
// Called for a broad-phase shape that has to be tested for raycast
|
||||||
decimal BroadPhaseAlgorithm::raycastBroadPhaseShape(int32 nodeId, RaycastTest& raycastTest,
|
decimal BroadPhaseRaycastCallback::raycastBroadPhaseShape(int32 nodeId, const Ray& ray) {
|
||||||
const Ray& ray,
|
|
||||||
unsigned short raycastWithCategoryMaskBits) const {
|
|
||||||
|
|
||||||
decimal hitFraction = decimal(-1.0);
|
decimal hitFraction = decimal(-1.0);
|
||||||
|
|
||||||
|
@ -275,20 +280,13 @@ decimal BroadPhaseAlgorithm::raycastBroadPhaseShape(int32 nodeId, RaycastTest& r
|
||||||
ProxyShape* proxyShape = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(nodeId));
|
ProxyShape* proxyShape = static_cast<ProxyShape*>(mDynamicAABBTree.getNodeDataPointer(nodeId));
|
||||||
|
|
||||||
// Check if the raycast filtering mask allows raycast against this shape
|
// Check if the raycast filtering mask allows raycast against this shape
|
||||||
if ((raycastWithCategoryMaskBits & proxyShape->getCollisionCategoryBits()) != 0) {
|
if ((mRaycastWithCategoryMaskBits & proxyShape->getCollisionCategoryBits()) != 0) {
|
||||||
|
|
||||||
// Ask the collision detection to perform a ray cast test against
|
// Ask the collision detection to perform a ray cast test against
|
||||||
// the proxy shape of this node because the ray is overlapping
|
// the proxy shape of this node because the ray is overlapping
|
||||||
// with the shape in the broad-phase
|
// with the shape in the broad-phase
|
||||||
hitFraction = raycastTest.raycastAgainstShape(proxyShape, ray);
|
hitFraction = mRaycastTest.raycastAgainstShape(proxyShape, ray);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hitFraction;
|
return hitFraction;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when a overlapping node has been found during the call to
|
|
||||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
|
||||||
void AABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
|
||||||
|
|
||||||
mBroadPhaseAlgorithm.notifyOverlappingNodes(mReferenceNodeId, nodeId);
|
|
||||||
}
|
|
||||||
|
|
|
@ -83,18 +83,33 @@ class AABBOverlapCallback : public DynamicAABBTreeOverlapCallback {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Class BroadPhaseRaycastTestCallback
|
// Class BroadPhaseRaycastCallback
|
||||||
/**
|
/**
|
||||||
* Callback method called to raycast against a given broad-phase shape
|
* Callback called when the AABB of a leaf node is hit by a ray the
|
||||||
|
* broad-phase Dynamic AABB Tree.
|
||||||
*/
|
*/
|
||||||
class BroadPhaseRaycastTestCallback {
|
class BroadPhaseRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
const DynamicAABBTree& mDynamicAABBTree;
|
||||||
|
|
||||||
|
unsigned short mRaycastWithCategoryMaskBits;
|
||||||
|
|
||||||
|
RaycastTest& mRaycastTest;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
BroadPhaseRaycastCallback(const DynamicAABBTree& dynamicAABBTree, unsigned short raycastWithCategoryMaskBits,
|
||||||
|
RaycastTest& raycastTest)
|
||||||
|
: mDynamicAABBTree(dynamicAABBTree), mRaycastWithCategoryMaskBits(raycastWithCategoryMaskBits),
|
||||||
|
mRaycastTest(raycastTest) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Called for a broad-phase shape that has to be tested for raycast
|
// Called for a broad-phase shape that has to be tested for raycast
|
||||||
virtual decimal raycastBroadPhaseShape(int32 nodeId, RaycastTest& raycastTest,
|
virtual decimal raycastBroadPhaseShape(int32 nodeId, const Ray& ray);
|
||||||
const Ray& ray,
|
|
||||||
unsigned short raycastWithCategoryMaskBits) const=0;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,7 +121,7 @@ class BroadPhaseRaycastTestCallback {
|
||||||
* later for collision during the narrow-phase collision detection. A dynamic AABB
|
* later for collision during the narrow-phase collision detection. A dynamic AABB
|
||||||
* tree data structure is used for fast broad-phase collision detection.
|
* tree data structure is used for fast broad-phase collision detection.
|
||||||
*/
|
*/
|
||||||
class BroadPhaseAlgorithm : BroadPhaseRaycastTestCallback {
|
class BroadPhaseAlgorithm {
|
||||||
|
|
||||||
protected :
|
protected :
|
||||||
|
|
||||||
|
@ -183,11 +198,6 @@ class BroadPhaseAlgorithm : BroadPhaseRaycastTestCallback {
|
||||||
/// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
|
/// Notify the broad-phase about a potential overlapping pair in the dynamic AABB tree
|
||||||
void notifyOverlappingNodes(int broadPhaseId1, int broadPhaseId2);
|
void notifyOverlappingNodes(int broadPhaseId1, int broadPhaseId2);
|
||||||
|
|
||||||
/// Called for a broad-phase shape that has to be tested for raycast
|
|
||||||
virtual decimal raycastBroadPhaseShape(int32 nodeId, RaycastTest& raycastTest,
|
|
||||||
const Ray& ray,
|
|
||||||
unsigned short raycastWithCategoryMaskBits) const;
|
|
||||||
|
|
||||||
/// Compute all the overlapping pairs of collision shapes
|
/// Compute all the overlapping pairs of collision shapes
|
||||||
void computeOverlappingPairs();
|
void computeOverlappingPairs();
|
||||||
|
|
||||||
|
@ -223,7 +233,10 @@ inline bool BroadPhaseAlgorithm::testOverlappingShapes(const ProxyShape* shape1,
|
||||||
// Ray casting method
|
// Ray casting method
|
||||||
inline void BroadPhaseAlgorithm::raycast(const Ray& ray, RaycastTest& raycastTest,
|
inline void BroadPhaseAlgorithm::raycast(const Ray& ray, RaycastTest& raycastTest,
|
||||||
unsigned short raycastWithCategoryMaskBits) const {
|
unsigned short raycastWithCategoryMaskBits) const {
|
||||||
mDynamicAABBTree.raycast(ray, raycastTest, raycastWithCategoryMaskBits, *this);
|
|
||||||
|
BroadPhaseRaycastCallback broadPhaseRaycastCallback(mDynamicAABBTree, raycastWithCategoryMaskBits, raycastTest);
|
||||||
|
|
||||||
|
mDynamicAABBTree.raycast(ray, broadPhaseRaycastCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -631,9 +631,7 @@ void DynamicAABBTree::reportAllShapesOverlappingWithAABB(const AABB& aabb,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ray casting method
|
// Ray casting method
|
||||||
void DynamicAABBTree::raycast(const Ray& ray, RaycastTest& raycastTest,
|
void DynamicAABBTree::raycast(const Ray& ray, DynamicAABBTreeRaycastCallback &callback) const {
|
||||||
unsigned short raycastWithCategoryMaskBits,
|
|
||||||
const BroadPhaseRaycastTestCallback& callback) const {
|
|
||||||
|
|
||||||
decimal maxFraction = ray.maxFraction;
|
decimal maxFraction = ray.maxFraction;
|
||||||
|
|
||||||
|
@ -668,8 +666,7 @@ void DynamicAABBTree::raycast(const Ray& ray, RaycastTest& raycastTest,
|
||||||
Ray rayTemp(ray.point1, ray.point2, maxFraction);
|
Ray rayTemp(ray.point1, ray.point2, maxFraction);
|
||||||
|
|
||||||
// Call the callback that will raycast again the broad-phase shape
|
// Call the callback that will raycast again the broad-phase shape
|
||||||
decimal hitFraction = callback.raycastBroadPhaseShape(nodeID, raycastTest, rayTemp,
|
decimal hitFraction = callback.raycastBroadPhaseShape(nodeID, rayTemp);
|
||||||
raycastWithCategoryMaskBits);
|
|
||||||
|
|
||||||
// If the user returned a hitFraction of zero, it means that
|
// If the user returned a hitFraction of zero, it means that
|
||||||
// the raycasting should stop here
|
// the raycasting should stop here
|
||||||
|
|
|
@ -103,6 +103,20 @@ class DynamicAABBTreeOverlapCallback {
|
||||||
virtual void notifyOverlappingNode(int nodeId)=0;
|
virtual void notifyOverlappingNode(int nodeId)=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Class DynamicAABBTreeRaycastCallback
|
||||||
|
/**
|
||||||
|
* Raycast callback in the Dynamic AABB Tree called when the AABB of a leaf
|
||||||
|
* node is hit by the ray.
|
||||||
|
*/
|
||||||
|
class DynamicAABBTreeRaycastCallback {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Called when the AABB of a leaf node is hit by a ray
|
||||||
|
virtual decimal raycastBroadPhaseShape(int32 nodeId, const Ray& ray)=0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// Class DynamicAABBTree
|
// Class DynamicAABBTree
|
||||||
/**
|
/**
|
||||||
* This class implements a dynamic AABB tree that is used for broad-phase
|
* This class implements a dynamic AABB tree that is used for broad-phase
|
||||||
|
@ -208,9 +222,7 @@ class DynamicAABBTree {
|
||||||
DynamicAABBTreeOverlapCallback& callback) const;
|
DynamicAABBTreeOverlapCallback& callback) const;
|
||||||
|
|
||||||
/// Ray casting method
|
/// Ray casting method
|
||||||
void raycast(const Ray& ray, RaycastTest& raycastTest,
|
void raycast(const Ray& ray, DynamicAABBTreeRaycastCallback& callback) const;
|
||||||
unsigned short raycastWithCategoryMaskBits,
|
|
||||||
const BroadPhaseRaycastTestCallback& callback) const;
|
|
||||||
|
|
||||||
/// Compute the height of the tree
|
/// Compute the height of the tree
|
||||||
int computeHeight();
|
int computeHeight();
|
||||||
|
|
|
@ -85,7 +85,6 @@ void ConcaveVsConvexAlgorithm::testCollision(const CollisionShapeInfo& shape1Inf
|
||||||
void ConvexVsTriangleCallback::testTriangle(const Vector3* trianglePoints) {
|
void ConvexVsTriangleCallback::testTriangle(const Vector3* trianglePoints) {
|
||||||
|
|
||||||
// Create a triangle collision shape
|
// Create a triangle collision shape
|
||||||
// TODO : Do we need to use a collision margin for a triangle ?
|
|
||||||
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2]);
|
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2]);
|
||||||
|
|
||||||
// Select the collision algorithm to use between the triangle and the convex shape
|
// Select the collision algorithm to use between the triangle and the convex shape
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
// Libraries
|
// Libraries
|
||||||
#include "ConcaveMeshShape.h"
|
#include "ConcaveMeshShape.h"
|
||||||
|
#include "collision/shapes/TriangleShape.h"
|
||||||
|
|
||||||
using namespace reactphysics3d;
|
using namespace reactphysics3d;
|
||||||
|
|
||||||
|
@ -157,10 +158,67 @@ void ConcaveMeshShape::testAllTriangles(TriangleCallback& callback, const AABB&
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raycast method with feedback information
|
// Raycast method with feedback information
|
||||||
|
/// Note that only the first triangle hit by the ray in the mesh will be returned, even if
|
||||||
|
/// the ray hits many triangles.
|
||||||
bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
bool ConcaveMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||||
|
|
||||||
|
// Create the callback object that will compute ray casting against triangles
|
||||||
|
ConcaveMeshRaycastCallback raycastCallback(mDynamicAABBTree, *this, proxyShape, raycastInfo, ray);
|
||||||
|
|
||||||
// TODO : Implement this
|
// Ask the Dynamic AABB Tree to report all AABB nodes that are hit by the ray.
|
||||||
|
// The raycastCallback object will then compute ray casting against the triangles
|
||||||
|
// in the hit AABBs.
|
||||||
|
mDynamicAABBTree.raycast(ray, raycastCallback);
|
||||||
|
|
||||||
return false;
|
return raycastCallback.getIsHit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect all the AABB nodes that are hit by the ray in the Dynamic AABB Tree
|
||||||
|
decimal ConcaveMeshRaycastCallback::raycastBroadPhaseShape(int32 nodeId, const Ray& ray) {
|
||||||
|
|
||||||
|
// Add the id of the hit AABB node into
|
||||||
|
mHitAABBNodes.push_back(nodeId);
|
||||||
|
|
||||||
|
return ray.maxFraction;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Raycast all collision shapes that have been collected
|
||||||
|
void ConcaveMeshRaycastCallback::raycastTriangles() {
|
||||||
|
|
||||||
|
std::vector<int>::const_iterator it;
|
||||||
|
decimal smallestHitFraction = mRay.maxFraction;
|
||||||
|
|
||||||
|
for (it = mHitAABBNodes.begin(); it != mHitAABBNodes.end(); ++it) {
|
||||||
|
|
||||||
|
// Get the node data (triangle index and mesh subpart index)
|
||||||
|
int32* data = mDynamicAABBTree.getNodeDataInt(*it);
|
||||||
|
|
||||||
|
// Get the triangle vertices for this node from the concave mesh shape
|
||||||
|
Vector3 trianglePoints[3];
|
||||||
|
mConcaveMeshShape.getTriangleVerticesWithIndexPointer(data[0], data[1], trianglePoints);
|
||||||
|
|
||||||
|
// Create a triangle collision shape
|
||||||
|
TriangleShape triangleShape(trianglePoints[0], trianglePoints[1], trianglePoints[2]);
|
||||||
|
|
||||||
|
// 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 <= smallestHitFraction) {
|
||||||
|
|
||||||
|
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 = data[0];
|
||||||
|
mRaycastInfo.triangleIndex = data[1];
|
||||||
|
|
||||||
|
smallestHitFraction = raycastInfo.hitFraction;
|
||||||
|
mIsHit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,41 @@ class ConvexTriangleAABBOverlapCallback : public DynamicAABBTreeOverlapCallback
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Class ConcaveMeshRaycastCallback
|
||||||
|
class ConcaveMeshRaycastCallback : public DynamicAABBTreeRaycastCallback {
|
||||||
|
|
||||||
|
private :
|
||||||
|
|
||||||
|
std::vector<int32> mHitAABBNodes;
|
||||||
|
const DynamicAABBTree& mDynamicAABBTree;
|
||||||
|
const ConcaveMeshShape& mConcaveMeshShape;
|
||||||
|
ProxyShape* mProxyShape;
|
||||||
|
RaycastInfo& mRaycastInfo;
|
||||||
|
const Ray& mRay;
|
||||||
|
bool mIsHit;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
ConcaveMeshRaycastCallback(const DynamicAABBTree& dynamicAABBTree, const ConcaveMeshShape& concaveMeshShape,
|
||||||
|
ProxyShape* proxyShape, RaycastInfo& raycastInfo, const Ray& ray)
|
||||||
|
: mDynamicAABBTree(dynamicAABBTree), mConcaveMeshShape(concaveMeshShape), mProxyShape(proxyShape),
|
||||||
|
mRaycastInfo(raycastInfo), mRay(ray), mIsHit(false) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect all the AABB nodes that are hit by the ray in the Dynamic AABB Tree
|
||||||
|
virtual decimal raycastBroadPhaseShape(int32 nodeId, const Ray& ray);
|
||||||
|
|
||||||
|
/// Raycast all collision shapes that have been collected
|
||||||
|
void raycastTriangles();
|
||||||
|
|
||||||
|
/// Return true if a raycast hit has been found
|
||||||
|
bool getIsHit() const {
|
||||||
|
return mIsHit;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TODO : Implement raycasting with this collision shape
|
// TODO : Implement raycasting with this collision shape
|
||||||
|
|
||||||
// TODO : Make possible for the user to have a scaling factor on the mesh
|
// TODO : Make possible for the user to have a scaling factor on the mesh
|
||||||
|
@ -101,9 +136,6 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||||
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
virtual Vector3 getLocalSupportPointWithoutMargin(const Vector3& direction,
|
||||||
void** cachedCollisionData) const;
|
void** cachedCollisionData) const;
|
||||||
|
|
||||||
/// Return true if a point is inside the collision shape
|
|
||||||
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
|
||||||
|
|
||||||
/// Raycast method with feedback information
|
/// Raycast method with feedback information
|
||||||
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const;
|
||||||
|
|
||||||
|
@ -141,6 +173,7 @@ class ConcaveMeshShape : public ConcaveShape {
|
||||||
// ---------- Friendship ----------- //
|
// ---------- Friendship ----------- //
|
||||||
|
|
||||||
friend class ConvexTriangleAABBOverlapCallback;
|
friend class ConvexTriangleAABBOverlapCallback;
|
||||||
|
friend class ConcaveMeshRaycastCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the number of bytes used by the collision shape
|
// Return the number of bytes used by the collision shape
|
||||||
|
@ -209,13 +242,6 @@ inline void ConcaveMeshShape::computeLocalInertiaTensor(Matrix3x3& tensor, decim
|
||||||
0, 0, mass);
|
0, 0, mass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if a point is inside the collision shape
|
|
||||||
inline bool ConcaveMeshShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
|
||||||
|
|
||||||
// TODO : Implement this
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when a overlapping node has been found during the call to
|
// Called when a overlapping node has been found during the call to
|
||||||
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
// DynamicAABBTree:reportAllShapesOverlappingWithAABB()
|
||||||
inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
inline void ConvexTriangleAABBOverlapCallback::notifyOverlappingNode(int nodeId) {
|
||||||
|
|
|
@ -68,6 +68,9 @@ class ConcaveShape : public CollisionShape {
|
||||||
/// Private assignment operator
|
/// Private assignment operator
|
||||||
ConcaveShape& operator=(const ConcaveShape& shape);
|
ConcaveShape& operator=(const ConcaveShape& shape);
|
||||||
|
|
||||||
|
/// Return true if a point is inside the collision shape
|
||||||
|
virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
// -------------------- Methods -------------------- //
|
// -------------------- Methods -------------------- //
|
||||||
|
@ -90,6 +93,11 @@ inline bool ConcaveShape::isConvex() const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return true if a point is inside the collision shape
|
||||||
|
inline bool ConcaveShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -97,7 +97,7 @@ class SphereShape : public ConvexShape {
|
||||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
|
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
|
||||||
|
|
||||||
/// Update the AABB of a body using its collision shape
|
/// Update the AABB of a body using its collision shape
|
||||||
virtual void computeAABB(AABB& aabb, const Transform& transform);
|
virtual void computeAABB(AABB& aabb, const Transform& transform) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the radius of the sphere
|
// Get the radius of the sphere
|
||||||
|
@ -183,7 +183,7 @@ inline void SphereShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal ma
|
||||||
* computed in world-space coordinates
|
* computed in world-space coordinates
|
||||||
* @param transform Transform used to compute the AABB of the collision shape
|
* @param transform Transform used to compute the AABB of the collision shape
|
||||||
*/
|
*/
|
||||||
inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) {
|
inline void SphereShape::computeAABB(AABB& aabb, const Transform& transform) const {
|
||||||
|
|
||||||
// Get the local extents in x,y and z direction
|
// Get the local extents in x,y and z direction
|
||||||
Vector3 extents(mMargin, mMargin, mMargin);
|
Vector3 extents(mMargin, mMargin, mMargin);
|
||||||
|
|
|
@ -51,10 +51,57 @@ TriangleShape::~TriangleShape() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raycast method with feedback information
|
// Raycast method with feedback information
|
||||||
|
/// This method use the line vs triangle raycasting technique described in
|
||||||
|
/// Real-time Collision Detection by Christer Ericson.
|
||||||
bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const {
|
||||||
|
|
||||||
// TODO : Implement this
|
// TODO : For all collision shape, try to perform raycasting in local-space and
|
||||||
|
// compute world-space hit point, normal in upper classes when local-space
|
||||||
|
// hit points are returned
|
||||||
|
const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform();
|
||||||
|
const Transform worldToLocalTransform = localToWorldTransform.getInverse();
|
||||||
|
const Vector3 point1 = worldToLocalTransform * ray.point1;
|
||||||
|
const Vector3 point2 = worldToLocalTransform * ray.point2;
|
||||||
|
|
||||||
return false;
|
const Vector3 pq = point2 - point1;
|
||||||
|
const Vector3 pa = mPoints[0] - point1;
|
||||||
|
const Vector3 pb = mPoints[1] - point1;
|
||||||
|
const Vector3 pc = mPoints[2] - point1;
|
||||||
|
|
||||||
|
// Test if the line PQ is inside the eges BC, CA and AB. We use the triple
|
||||||
|
// product for this test.
|
||||||
|
const Vector3 m = pq.cross(pc);
|
||||||
|
decimal u = pb.dot(m);
|
||||||
|
if (u < decimal(0.0)) return false;
|
||||||
|
|
||||||
|
decimal v = -pa.dot(m);
|
||||||
|
if (v < decimal(0.0)) return false;
|
||||||
|
|
||||||
|
decimal w = pa.dot(pq.cross(pb));
|
||||||
|
if (w < decimal(0.0)) return false;
|
||||||
|
|
||||||
|
// If the line PQ is in the triangle plane (case where u=v=w=0)
|
||||||
|
if (u < MACHINE_EPSILON && u < MACHINE_EPSILON && v < MACHINE_EPSILON) return false;
|
||||||
|
|
||||||
|
// Compute the barycentric coordinates (u, v, w) to determine the
|
||||||
|
// intersection point R, R = u * a + v * b + w * c
|
||||||
|
decimal denom = decimal(1.0) / (u + v + w);
|
||||||
|
u *= denom;
|
||||||
|
v *= denom;
|
||||||
|
w *= denom;
|
||||||
|
|
||||||
|
// Compute the local hit point using the barycentric coordinates
|
||||||
|
const Vector3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
|
||||||
|
|
||||||
|
const Vector3 localHitNormal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
|
||||||
|
|
||||||
|
raycastInfo.body = proxyShape->getBody();
|
||||||
|
raycastInfo.proxyShape = proxyShape;
|
||||||
|
raycastInfo.worldPoint = localToWorldTransform * localHitPoint;
|
||||||
|
raycastInfo.hitFraction = (localHitPoint - point1).length() / pq.length();
|
||||||
|
raycastInfo.worldNormal = localToWorldTransform.getOrientation() * localHitNormal;
|
||||||
|
raycastInfo.worldNormal.normalize();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -92,7 +92,11 @@ class TriangleShape : public ConvexShape {
|
||||||
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
|
virtual void computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const;
|
||||||
|
|
||||||
/// Update the AABB of a body using its collision shape
|
/// Update the AABB of a body using its collision shape
|
||||||
virtual void computeAABB(AABB& aabb, const Transform& transform);
|
virtual void computeAABB(AABB& aabb, const Transform& transform) const;
|
||||||
|
|
||||||
|
// ---------- Friendship ---------- //
|
||||||
|
|
||||||
|
friend class ConcaveMeshRaycastCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the number of bytes used by the collision shape
|
// Return the number of bytes used by the collision shape
|
||||||
|
@ -155,7 +159,7 @@ inline void TriangleShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal
|
||||||
* computed in world-space coordinates
|
* computed in world-space coordinates
|
||||||
* @param transform Transform used to compute the AABB of the collision shape
|
* @param transform Transform used to compute the AABB of the collision shape
|
||||||
*/
|
*/
|
||||||
inline void TriangleShape::computeAABB(AABB& aabb, const Transform& transform) {
|
inline void TriangleShape::computeAABB(AABB& aabb, const Transform& transform) const {
|
||||||
|
|
||||||
const Vector3 worldPoint1 = transform * mPoints[0];
|
const Vector3 worldPoint1 = transform * mPoints[0];
|
||||||
const Vector3 worldPoint2 = transform * mPoints[1];
|
const Vector3 worldPoint2 = transform * mPoints[1];
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "collision/shapes/ConeShape.h"
|
#include "collision/shapes/ConeShape.h"
|
||||||
#include "collision/shapes/ConvexMeshShape.h"
|
#include "collision/shapes/ConvexMeshShape.h"
|
||||||
#include "collision/shapes/CylinderShape.h"
|
#include "collision/shapes/CylinderShape.h"
|
||||||
|
#include "collision/shapes/TriangleShape.h"
|
||||||
|
|
||||||
// TODO : Add test for concave shape here
|
// TODO : Add test for concave shape here
|
||||||
|
|
||||||
|
@ -115,6 +116,7 @@ class TestRaycast : public Test {
|
||||||
CollisionBody* mConvexMeshBodyEdgesInfo;
|
CollisionBody* mConvexMeshBodyEdgesInfo;
|
||||||
CollisionBody* mCylinderBody;
|
CollisionBody* mCylinderBody;
|
||||||
CollisionBody* mCompoundBody;
|
CollisionBody* mCompoundBody;
|
||||||
|
CollisionBody* mTriangleBody;
|
||||||
|
|
||||||
// Transform
|
// Transform
|
||||||
Transform mBodyTransform;
|
Transform mBodyTransform;
|
||||||
|
@ -130,7 +132,7 @@ class TestRaycast : public Test {
|
||||||
ConvexMeshShape* mConvexMeshShape;
|
ConvexMeshShape* mConvexMeshShape;
|
||||||
ConvexMeshShape* mConvexMeshShapeEdgesInfo;
|
ConvexMeshShape* mConvexMeshShapeEdgesInfo;
|
||||||
CylinderShape* mCylinderShape;
|
CylinderShape* mCylinderShape;
|
||||||
|
TriangleShape* mTriangleShape;
|
||||||
|
|
||||||
// Proxy Shapes
|
// Proxy Shapes
|
||||||
ProxyShape* mBoxProxyShape;
|
ProxyShape* mBoxProxyShape;
|
||||||
|
@ -142,6 +144,7 @@ class TestRaycast : public Test {
|
||||||
ProxyShape* mCylinderProxyShape;
|
ProxyShape* mCylinderProxyShape;
|
||||||
ProxyShape* mCompoundSphereProxyShape;
|
ProxyShape* mCompoundSphereProxyShape;
|
||||||
ProxyShape* mCompoundCylinderProxyShape;
|
ProxyShape* mCompoundCylinderProxyShape;
|
||||||
|
ProxyShape* mTriangleProxyShape;
|
||||||
|
|
||||||
public :
|
public :
|
||||||
|
|
||||||
|
@ -156,8 +159,11 @@ class TestRaycast : public Test {
|
||||||
mWorld = new CollisionWorld();
|
mWorld = new CollisionWorld();
|
||||||
|
|
||||||
// Body transform
|
// Body transform
|
||||||
|
// TODO : Uncomment this
|
||||||
Vector3 position(-3, 2, 7);
|
Vector3 position(-3, 2, 7);
|
||||||
Quaternion orientation(PI / 5, PI / 6, PI / 7);
|
Quaternion orientation(PI / 5, PI / 6, PI / 7);
|
||||||
|
// Vector3 position(0, 0, 0);
|
||||||
|
// Quaternion orientation = Quaternion::identity();
|
||||||
mBodyTransform = Transform(position, orientation);
|
mBodyTransform = Transform(position, orientation);
|
||||||
|
|
||||||
// Create the bodies
|
// Create the bodies
|
||||||
|
@ -169,10 +175,14 @@ class TestRaycast : public Test {
|
||||||
mConvexMeshBodyEdgesInfo = mWorld->createCollisionBody(mBodyTransform);
|
mConvexMeshBodyEdgesInfo = mWorld->createCollisionBody(mBodyTransform);
|
||||||
mCylinderBody = mWorld->createCollisionBody(mBodyTransform);
|
mCylinderBody = mWorld->createCollisionBody(mBodyTransform);
|
||||||
mCompoundBody = mWorld->createCollisionBody(mBodyTransform);
|
mCompoundBody = mWorld->createCollisionBody(mBodyTransform);
|
||||||
|
mTriangleBody = mWorld->createCollisionBody(mBodyTransform);
|
||||||
|
|
||||||
// Collision shape transform
|
// Collision shape transform
|
||||||
|
// TODO : Uncomment this
|
||||||
Vector3 shapePosition(1, -4, -3);
|
Vector3 shapePosition(1, -4, -3);
|
||||||
Quaternion shapeOrientation(3 * PI / 6 , -PI / 8, PI / 3);
|
Quaternion shapeOrientation(3 * PI / 6 , -PI / 8, PI / 3);
|
||||||
|
// Vector3 shapePosition(0, 0, 0);
|
||||||
|
// Quaternion shapeOrientation = Quaternion::identity();
|
||||||
mShapeTransform = Transform(shapePosition, shapeOrientation);
|
mShapeTransform = Transform(shapePosition, shapeOrientation);
|
||||||
|
|
||||||
// Compute the the transform from a local shape point to world-space
|
// Compute the the transform from a local shape point to world-space
|
||||||
|
@ -185,6 +195,12 @@ class TestRaycast : public Test {
|
||||||
mSphereShape = new SphereShape(3);
|
mSphereShape = new SphereShape(3);
|
||||||
mSphereProxyShape = mSphereBody->addCollisionShape(mSphereShape, mShapeTransform);
|
mSphereProxyShape = mSphereBody->addCollisionShape(mSphereShape, mShapeTransform);
|
||||||
|
|
||||||
|
const Vector3 triangleVertex1(100, 100, 0);
|
||||||
|
const Vector3 triangleVertex2(105, 100, 0);
|
||||||
|
const Vector3 triangleVertex3(100, 103, 0);
|
||||||
|
mTriangleShape = new TriangleShape(triangleVertex1, triangleVertex2, triangleVertex3);
|
||||||
|
mTriangleProxyShape = mTriangleBody->addCollisionShape(mTriangleShape, mShapeTransform);
|
||||||
|
|
||||||
mCapsuleShape = new CapsuleShape(2, 5);
|
mCapsuleShape = new CapsuleShape(2, 5);
|
||||||
mCapsuleProxyShape = mCapsuleBody->addCollisionShape(mCapsuleShape, mShapeTransform);
|
mCapsuleProxyShape = mCapsuleBody->addCollisionShape(mCapsuleShape, mShapeTransform);
|
||||||
|
|
||||||
|
@ -249,6 +265,7 @@ class TestRaycast : public Test {
|
||||||
mCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
mCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||||
mCompoundSphereProxyShape->setCollisionCategoryBits(CATEGORY2);
|
mCompoundSphereProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||||
mCompoundCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
mCompoundCylinderProxyShape->setCollisionCategoryBits(CATEGORY2);
|
||||||
|
mTriangleProxyShape->setCollisionCategoryBits(CATEGORY1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
|
@ -260,6 +277,7 @@ class TestRaycast : public Test {
|
||||||
delete mConvexMeshShape;
|
delete mConvexMeshShape;
|
||||||
delete mConvexMeshShapeEdgesInfo;
|
delete mConvexMeshShapeEdgesInfo;
|
||||||
delete mCylinderShape;
|
delete mCylinderShape;
|
||||||
|
delete mTriangleShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the tests
|
/// Run the tests
|
||||||
|
@ -271,6 +289,7 @@ class TestRaycast : public Test {
|
||||||
testConvexMesh();
|
testConvexMesh();
|
||||||
testCylinder();
|
testCylinder();
|
||||||
testCompound();
|
testCompound();
|
||||||
|
testTriangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test the ProxyBoxShape::raycast(), CollisionBody::raycast() and
|
/// Test the ProxyBoxShape::raycast(), CollisionBody::raycast() and
|
||||||
|
@ -935,6 +954,119 @@ class TestRaycast : public Test {
|
||||||
test(mCallback.isHit);
|
test(mCallback.isHit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Test the ProxySphereShape::raycast(), CollisionBody::raycast() and
|
||||||
|
/// CollisionWorld::raycast() methods.
|
||||||
|
void testTriangle() {
|
||||||
|
|
||||||
|
// ----- Test feedback data ----- //
|
||||||
|
Vector3 point1 = mLocalShapeToWorld * Vector3(101, 101, 400);
|
||||||
|
Vector3 point2 = mLocalShapeToWorld * Vector3(101, 101, -200);
|
||||||
|
Ray ray(point1, point2);
|
||||||
|
Vector3 hitPoint = mLocalShapeToWorld * Vector3(101, 101, 0);
|
||||||
|
|
||||||
|
mCallback.shapeToTest = mTriangleProxyShape;
|
||||||
|
|
||||||
|
// CollisionWorld::raycast()
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray, &mCallback);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
test(mCallback.raycastInfo.body == mTriangleBody);
|
||||||
|
test(mCallback.raycastInfo.proxyShape == mTriangleProxyShape);
|
||||||
|
test(approxEqual(mCallback.raycastInfo.hitFraction, 0.2, epsilon));
|
||||||
|
test(approxEqual(mCallback.raycastInfo.worldPoint.x, hitPoint.x, epsilon));
|
||||||
|
test(approxEqual(mCallback.raycastInfo.worldPoint.y, hitPoint.y, epsilon));
|
||||||
|
test(approxEqual(mCallback.raycastInfo.worldPoint.z, hitPoint.z, epsilon));
|
||||||
|
|
||||||
|
// Correct category filter mask
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray, &mCallback, CATEGORY1);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
|
||||||
|
// Wrong category filter mask
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray, &mCallback, CATEGORY2);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
|
||||||
|
// CollisionBody::raycast()
|
||||||
|
RaycastInfo raycastInfo2;
|
||||||
|
test(mTriangleBody->raycast(ray, raycastInfo2));
|
||||||
|
test(raycastInfo2.body == mTriangleBody);
|
||||||
|
test(raycastInfo2.proxyShape == mTriangleProxyShape);
|
||||||
|
test(approxEqual(raycastInfo2.hitFraction, 0.2, epsilon));
|
||||||
|
test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon));
|
||||||
|
test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon));
|
||||||
|
test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon));
|
||||||
|
|
||||||
|
// ProxyCollisionShape::raycast()
|
||||||
|
RaycastInfo raycastInfo3;
|
||||||
|
test(mTriangleProxyShape->raycast(ray, raycastInfo3));
|
||||||
|
test(raycastInfo3.body == mTriangleBody);
|
||||||
|
test(raycastInfo3.proxyShape == mTriangleProxyShape);
|
||||||
|
test(approxEqual(raycastInfo3.hitFraction, 0.2, epsilon));
|
||||||
|
test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon));
|
||||||
|
test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon));
|
||||||
|
test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon));
|
||||||
|
|
||||||
|
Ray ray1(mLocalShapeToWorld * Vector3(-10, 10, 4), mLocalShapeToWorld * Vector3(15, 6, -4));
|
||||||
|
Ray ray2(mLocalShapeToWorld * Vector3(102, 107, 5), mLocalShapeToWorld * Vector3(102, 107, -5));
|
||||||
|
Ray ray3(mLocalShapeToWorld * Vector3(106, 102, 6), mLocalShapeToWorld * Vector3(106, 102, -8));
|
||||||
|
|
||||||
|
Ray ray4(mLocalShapeToWorld * Vector3(100.2, 101, 5), mLocalShapeToWorld * Vector3(100.2, 101, -5));
|
||||||
|
Ray ray5(mLocalShapeToWorld * Vector3(100.5, 101.5, 4), mLocalShapeToWorld * Vector3(100.5, 101.5, -54));
|
||||||
|
Ray ray6(mLocalShapeToWorld * Vector3(102, 101, 1), mLocalShapeToWorld * Vector3(102, 102, -1));
|
||||||
|
|
||||||
|
// ----- Test raycast miss ----- //
|
||||||
|
test(!mTriangleBody->raycast(ray1, raycastInfo3));
|
||||||
|
test(!mTriangleProxyShape->raycast(ray1, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray1, &mCallback);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), &mCallback);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), &mCallback);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
|
||||||
|
test(!mTriangleBody->raycast(ray2, raycastInfo3));
|
||||||
|
test(!mTriangleProxyShape->raycast(ray2, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray2, &mCallback);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
|
||||||
|
test(!mTriangleBody->raycast(ray3, raycastInfo3));
|
||||||
|
test(!mTriangleProxyShape->raycast(ray3, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray3, &mCallback);
|
||||||
|
test(!mCallback.isHit);
|
||||||
|
|
||||||
|
// ----- Test raycast hits ----- //
|
||||||
|
test(mTriangleBody->raycast(ray4, raycastInfo3));
|
||||||
|
test(mTriangleProxyShape->raycast(ray4, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray4, &mCallback);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(Ray(ray4.point1, ray4.point2, decimal(0.8)), &mCallback);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
|
||||||
|
test(mTriangleBody->raycast(ray5, raycastInfo3));
|
||||||
|
test(mTriangleProxyShape->raycast(ray5, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray5, &mCallback);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(Ray(ray5.point1, ray5.point2, decimal(0.8)), &mCallback);
|
||||||
|
test(mCallback.isHit);
|
||||||
|
|
||||||
|
test(mTriangleBody->raycast(ray6, raycastInfo3));
|
||||||
|
test(mTriangleProxyShape->raycast(ray6, raycastInfo3));
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(ray6, &mCallback);
|
||||||
|
mCallback.reset();
|
||||||
|
mWorld->raycast(Ray(ray6.point1, ray6.point2, decimal(0.8)), &mCallback);
|
||||||
|
}
|
||||||
|
|
||||||
/// Test the ProxyConeShape::raycast(), CollisionBody::raycast() and
|
/// Test the ProxyConeShape::raycast(), CollisionBody::raycast() and
|
||||||
/// CollisionWorld::raycast() methods.
|
/// CollisionWorld::raycast() methods.
|
||||||
void testCone() {
|
void testCone() {
|
||||||
|
|
|
@ -45,9 +45,6 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name)
|
||||||
// Gravity vector in the dynamics world
|
// Gravity vector in the dynamics world
|
||||||
rp3d::Vector3 gravity(0, -9.81, 0);
|
rp3d::Vector3 gravity(0, -9.81, 0);
|
||||||
|
|
||||||
// Time step for the physics simulation
|
|
||||||
rp3d::decimal timeStep = 1.0f / 60.0f;
|
|
||||||
|
|
||||||
// Create the dynamics world for the physics simulation
|
// Create the dynamics world for the physics simulation
|
||||||
mDynamicsWorld = new rp3d::DynamicsWorld(gravity);
|
mDynamicsWorld = new rp3d::DynamicsWorld(gravity);
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ void ConcaveMeshScene::reset() {
|
||||||
// Reset the transform
|
// Reset the transform
|
||||||
mConcaveMesh->resetTransform(rp3d::Transform::identity());
|
mConcaveMesh->resetTransform(rp3d::Transform::identity());
|
||||||
|
|
||||||
rp3d::Vector3 spherePos(10.1, 10, 0);
|
rp3d::Vector3 spherePos(0, 15, 0);
|
||||||
rp3d::Transform sphereTransform(spherePos, rp3d::Quaternion::identity());
|
rp3d::Transform sphereTransform(spherePos, rp3d::Quaternion::identity());
|
||||||
mSphere->resetTransform(sphereTransform);
|
mSphere->resetTransform(sphereTransform);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,9 @@ using namespace raycastscene;
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
RaycastScene::RaycastScene(const std::string& name)
|
RaycastScene::RaycastScene(const std::string& name)
|
||||||
: SceneDemo(name, SCENE_RADIUS, false), mCurrentBodyIndex(-1), mAreNormalsDisplayed(false),
|
: SceneDemo(name, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
|
||||||
mMeshFolderPath("meshes/"), mRaycastManager(mPhongShader, mMeshFolderPath),
|
mRaycastManager(mPhongShader, mMeshFolderPath), mCurrentBodyIndex(-1),
|
||||||
mVBOVertices(GL_ARRAY_BUFFER) {
|
mAreNormalsDisplayed(false), mVBOVertices(GL_ARRAY_BUFFER) {
|
||||||
|
|
||||||
mIsContactPointsDisplayed = true;
|
mIsContactPointsDisplayed = true;
|
||||||
|
|
||||||
|
@ -122,6 +122,16 @@ RaycastScene::RaycastScene(const std::string& name)
|
||||||
mConvexMesh->setColor(mGreyColorDemo);
|
mConvexMesh->setColor(mGreyColorDemo);
|
||||||
mConvexMesh->setSleepingColor(mRedColorDemo);
|
mConvexMesh->setSleepingColor(mRedColorDemo);
|
||||||
|
|
||||||
|
// ---------- Concave Mesh ---------- //
|
||||||
|
openglframework::Vector3 position8(0, 0, 0);
|
||||||
|
|
||||||
|
// Create a convex mesh and a corresponding collision body in the dynamics world
|
||||||
|
mConcaveMesh = new ConcaveMesh(position8, mCollisionWorld, mMeshFolderPath);
|
||||||
|
|
||||||
|
// Set the color
|
||||||
|
mConcaveMesh->setColor(mGreyColorDemo);
|
||||||
|
mConcaveMesh->setSleepingColor(mRedColorDemo);
|
||||||
|
|
||||||
// Create the lines that will be used for raycasting
|
// Create the lines that will be used for raycasting
|
||||||
createLines();
|
createLines();
|
||||||
|
|
||||||
|
@ -173,6 +183,7 @@ void RaycastScene::changeBody() {
|
||||||
mCapsule->getCollisionBody()->setIsActive(false);
|
mCapsule->getCollisionBody()->setIsActive(false);
|
||||||
mConvexMesh->getCollisionBody()->setIsActive(false);
|
mConvexMesh->getCollisionBody()->setIsActive(false);
|
||||||
mDumbbell->getCollisionBody()->setIsActive(false);
|
mDumbbell->getCollisionBody()->setIsActive(false);
|
||||||
|
mConcaveMesh->getCollisionBody()->setIsActive(false);
|
||||||
|
|
||||||
switch(mCurrentBodyIndex) {
|
switch(mCurrentBodyIndex) {
|
||||||
case 0: mSphere->getCollisionBody()->setIsActive(true);
|
case 0: mSphere->getCollisionBody()->setIsActive(true);
|
||||||
|
@ -189,6 +200,8 @@ void RaycastScene::changeBody() {
|
||||||
break;
|
break;
|
||||||
case 6: mDumbbell->getCollisionBody()->setIsActive(true);
|
case 6: mDumbbell->getCollisionBody()->setIsActive(true);
|
||||||
break;
|
break;
|
||||||
|
case 7: mConcaveMesh->getCollisionBody()->setIsActive(true);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -237,9 +250,15 @@ RaycastScene::~RaycastScene() {
|
||||||
// Destroy the corresponding rigid body from the dynamics world
|
// Destroy the corresponding rigid body from the dynamics world
|
||||||
mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody());
|
mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody());
|
||||||
|
|
||||||
// Destroy the convex mesh
|
// Destroy the dumbbell
|
||||||
delete mDumbbell;
|
delete mDumbbell;
|
||||||
|
|
||||||
|
// Destroy the corresponding rigid body from the dynamics world
|
||||||
|
mCollisionWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody());
|
||||||
|
|
||||||
|
// Destroy the convex mesh
|
||||||
|
delete mConcaveMesh;
|
||||||
|
|
||||||
mRaycastManager.resetPoints();
|
mRaycastManager.resetPoints();
|
||||||
|
|
||||||
// Destroy the static data for the visual contact points
|
// Destroy the static data for the visual contact points
|
||||||
|
@ -345,8 +364,8 @@ void RaycastScene::renderSinglePass(openglframework::Shader& shader,
|
||||||
if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix);
|
if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix);
|
||||||
if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix);
|
if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix);
|
||||||
if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix);
|
if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix);
|
||||||
|
if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix);
|
||||||
|
|
||||||
//mPhongShader.unbind();
|
|
||||||
shader.unbind();
|
shader.unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "Capsule.h"
|
#include "Capsule.h"
|
||||||
#include "Line.h"
|
#include "Line.h"
|
||||||
#include "ConvexMesh.h"
|
#include "ConvexMesh.h"
|
||||||
|
#include "ConcaveMesh.h"
|
||||||
#include "Dumbbell.h"
|
#include "Dumbbell.h"
|
||||||
#include "VisualContactPoint.h"
|
#include "VisualContactPoint.h"
|
||||||
#include "../common/Viewer.h"
|
#include "../common/Viewer.h"
|
||||||
|
@ -58,7 +59,7 @@ const float CAPSULE_HEIGHT = 5.0f;
|
||||||
const float DUMBBELL_HEIGHT = 5.0f;
|
const float DUMBBELL_HEIGHT = 5.0f;
|
||||||
const int NB_RAYS = 100;
|
const int NB_RAYS = 100;
|
||||||
const float RAY_LENGTH = 30.0f;
|
const float RAY_LENGTH = 30.0f;
|
||||||
const int NB_BODIES = 7;
|
const int NB_BODIES = 8;
|
||||||
|
|
||||||
// Raycast manager
|
// Raycast manager
|
||||||
class RaycastManager : public rp3d::RaycastCallback {
|
class RaycastManager : public rp3d::RaycastCallback {
|
||||||
|
@ -145,6 +146,7 @@ class RaycastScene : public SceneDemo {
|
||||||
Capsule* mCapsule;
|
Capsule* mCapsule;
|
||||||
ConvexMesh* mConvexMesh;
|
ConvexMesh* mConvexMesh;
|
||||||
Dumbbell* mDumbbell;
|
Dumbbell* mDumbbell;
|
||||||
|
ConcaveMesh* mConcaveMesh;
|
||||||
|
|
||||||
/// Collision world used for the physics simulation
|
/// Collision world used for the physics simulation
|
||||||
rp3d::CollisionWorld* mCollisionWorld;
|
rp3d::CollisionWorld* mCollisionWorld;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user