Add capsule/capsule and capsule/sphere collision algorithm

This commit is contained in:
Daniel Chappuis 2017-02-02 23:10:01 +01:00
parent e9f2f94f64
commit 30e0132e15
10 changed files with 1500 additions and 1173 deletions

View File

@ -78,6 +78,8 @@ SET (REACTPHYSICS3D_SOURCES
"src/collision/narrowphase/SphereVsSphereAlgorithm.cpp"
"src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.h"
"src/collision/narrowphase/CapsuleVsCapsuleAlgorithm.cpp"
"src/collision/narrowphase/SphereVsCapsuleAlgorithm.h"
"src/collision/narrowphase/SphereVsCapsuleAlgorithm.cpp"
"src/collision/narrowphase/ConcaveVsConvexAlgorithm.h"
"src/collision/narrowphase/ConcaveVsConvexAlgorithm.cpp"
"src/collision/narrowphase/SphereVsConvexMeshAlgorithm.h"

View File

@ -1,37 +1,151 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "CapsuleVsCapsuleAlgorithm.h"
#include "collision/shapes/CapsuleShape.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
bool CapsuleVsCapsuleAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) {
}
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "CapsuleVsCapsuleAlgorithm.h"
#include "collision/shapes/CapsuleShape.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
bool CapsuleVsCapsuleAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo, ContactPointInfo& contactPointInfo) {
const decimal parallelEpsilon = decimal(0.001);
// Get the capsule collision shapes
const CapsuleShape* capsuleShape1 = static_cast<const CapsuleShape*>(narrowPhaseInfo->collisionShape1);
const CapsuleShape* capsuleShape2 = static_cast<const CapsuleShape*>(narrowPhaseInfo->collisionShape2);
// Get the transform from capsule 1 local-space to capsule 2 local-space
const Transform capsule1ToCapsule2SpaceTransform = narrowPhaseInfo->shape1ToWorldTransform * narrowPhaseInfo->shape2ToWorldTransform.getInverse();
// Compute the end-points of the inner segment of the first capsule
Vector3 capsule1SegA(0, -capsuleShape1->getHeight() * decimal(0.5), 0);
Vector3 capsule1SegB(0, capsuleShape1->getHeight() * decimal(0.5), 0);
capsule1SegA = capsule1ToCapsule2SpaceTransform * capsule1SegA;
capsule1SegB = capsule1ToCapsule2SpaceTransform * capsule1SegB;
// Compute the end-points of the inner segment of the second capsule
const Vector3 capsule2SegA(0, -capsuleShape2->getHeight() * decimal(0.5), 0);
const Vector3 capsule2SegB(0, capsuleShape2->getHeight() * decimal(0.5), 0);
// The two inner capsule segments
const Vector3 seg1 = capsule1SegB - capsule1SegA;
const Vector3 seg2 = capsule2SegB - capsule2SegA;
// Compute the sum of the radius of the two capsules (virtual spheres)
decimal sumRadius = capsuleShape2->getRadius() + capsuleShape1->getRadius();
// If the two capsules are parallel (we create two contact points)
if (seg1.cross(seg2).lengthSquare() < parallelEpsilon * parallelEpsilon) {
// If the distance between the two segments is larger than the sum of the capsules radius (we do not have overlapping)
const decimal segmentsDistance = computeDistancePointToLineDistance(capsule1SegA, capsule1SegB, capsule2SegA);
if (segmentsDistance > sumRadius || segmentsDistance < MACHINE_EPSILON) {
// The capsule are parallel but their inner segment distance is larger than the sum of the capsules radius.
// Therefore, we do not have overlap. If the inner segments overlap, we do not report any collision.
return false;
}
// Compute the planes that goes through the extrem points of the inner segment of capsule 1
decimal d1 = seg1.dot(capsule1SegA);
decimal d2 = -seg1.dot(capsule1SegB);
// Clip the inner segment of capsule 2 with the two planes that go through extreme points of inner
// segment of capsule 1
decimal t1 = computePlaneSegmentIntersection(capsule2SegB, capsule2SegA, d1, seg1);
decimal t2 = computePlaneSegmentIntersection(capsule2SegA, capsule2SegB, d2, -seg1);
bool isClipValid = false; // True if the segments were overlapping (the clip segment is valid)
// Clip the inner segment of capsule 2
Vector3 clipPointA, clipPointB;
if (t1 >= decimal(0.0)) {
if (t1 > decimal(1.0)) t1 = decimal(1.0);
clipPointA = capsule2SegB - t1 * seg2;
isClipValid = true;
}
if (t2 >= decimal(0.0) && t2 <= decimal(1.0)) {
if (t2 > decimal(1.0)) t2 = decimal(1.0);
clipPointB = capsule2SegA + t2 * seg2;
isClipValid = true;
}
// If we have a valid clip segment
if (isClipValid) {
Vector3 segment1ToSegment2 = (capsule2SegA - capsule1SegA);
Vector3 segment1ToSegment2Normalized = segment1ToSegment2.getUnit();
const Vector3 contactPointACapsule1Local = capsule1ToCapsule2SpaceTransform.getInverse() * (clipPointA - segment1ToSegment2 + segment1ToSegment2Normalized * capsuleShape1->getRadius());
const Vector3 contactPointBCapsule1Local = capsule1ToCapsule2SpaceTransform.getInverse() * (clipPointB - segment1ToSegment2 + segment1ToSegment2Normalized * capsuleShape1->getRadius());
const Vector3 contactPointACapsule2Local = clipPointA - segment1ToSegment2Normalized * capsuleShape2->getRadius();
const Vector3 contactPointBCapsule2Local = clipPointB - segment1ToSegment2Normalized * capsuleShape2->getRadius();
const Vector3 normalWorld = narrowPhaseInfo->shape2ToWorldTransform.getOrientation() * segment1ToSegment2Normalized;
decimal penetrationDepth = sumRadius - segmentsDistance;
// Create the contact info object
// TODO : Make sure we create two contact points at the same time (same method here)
contactPointInfo.init(normalWorld, penetrationDepth, contactPointACapsule1Local, contactPointBCapsule1Local);
contactPointInfo.init(normalWorld, penetrationDepth, contactPointACapsule2Local, contactPointBCapsule2Local);
}
}
// Compute the closest points between the two inner capsule segments
Vector3 closestPointCapsule1Seg;
Vector3 closestPointCapsule2Seg;
computeClosestPointBetweenTwoSegments(capsule1SegA, capsule1SegB, capsule2SegA, capsule2SegB,
closestPointCapsule1Seg, closestPointCapsule2Seg);
// Compute the distance between the sphere center and the closest point on the segment
Vector3 closestPointsSeg1ToSeg2 = (closestPointCapsule2Seg - closestPointCapsule1Seg);
const decimal closestPointsDistanceSquare = closestPointsSeg1ToSeg2.lengthSquare();
// If the collision shapes overlap
if (closestPointsDistanceSquare <= sumRadius * sumRadius && closestPointsDistanceSquare > MACHINE_EPSILON) {
decimal closestPointsDistance = std::sqrt(closestPointsDistanceSquare);
closestPointsSeg1ToSeg2 /= closestPointsDistance;
const Vector3 contactPointCapsule1Local = capsule1ToCapsule2SpaceTransform.getInverse() * (closestPointCapsule1Seg + closestPointsSeg1ToSeg2 * capsuleShape1->getRadius());
const Vector3 contactPointCapsule2Local = closestPointCapsule2Seg - closestPointsSeg1ToSeg2 * capsuleShape2->getRadius();
const Vector3 normalWorld = narrowPhaseInfo->shape2ToWorldTransform.getOrientation() * closestPointsSeg1ToSeg2;
decimal penetrationDepth = sumRadius - closestPointsDistance;
// Create the contact info object
contactPointInfo.init(normalWorld, penetrationDepth, contactPointCapsule1Local, contactPointCapsule2Local);
return true;
}
return false;
}

View File

@ -1,71 +1,71 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_CAPSULE_VS_CAPSULE_ALGORITHM_H
#define REACTPHYSICS3D_CAPSULE_VS_CAPSULE_ALGORITHM_H
// Libraries
#include "body/Body.h"
#include "constraint/ContactPoint.h"
#include "NarrowPhaseAlgorithm.h"
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Class CapsuleVsCapsuleAlgorithm
/**
* This class is used to compute the narrow-phase collision detection
* between two capsule collision shapes.
*/
class CapsuleVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
protected :
public :
// -------------------- Methods -------------------- //
/// Constructor
CapsuleVsCapsuleAlgorithm() = default;
/// Destructor
virtual ~CapsuleVsCapsuleAlgorithm() override = default;
/// Deleted copy-constructor
CapsuleVsCapsuleAlgorithm(const CapsuleVsCapsuleAlgorithm& algorithm) = delete;
/// Deleted assignment operator
CapsuleVsCapsuleAlgorithm& operator=(const CapsuleVsCapsuleAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volume collide
virtual bool testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) override;
};
}
#endif
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_CAPSULE_VS_CAPSULE_ALGORITHM_H
#define REACTPHYSICS3D_CAPSULE_VS_CAPSULE_ALGORITHM_H
// Libraries
#include "body/Body.h"
#include "constraint/ContactPoint.h"
#include "NarrowPhaseAlgorithm.h"
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Class CapsuleVsCapsuleAlgorithm
/**
* This class is used to compute the narrow-phase collision detection
* between two capsules collision shapes.
*/
class CapsuleVsCapsuleAlgorithm : public NarrowPhaseAlgorithm {
protected :
public :
// -------------------- Methods -------------------- //
/// Constructor
CapsuleVsCapsuleAlgorithm() = default;
/// Destructor
virtual ~CapsuleVsCapsuleAlgorithm() override = default;
/// Deleted copy-constructor
CapsuleVsCapsuleAlgorithm(const CapsuleVsCapsuleAlgorithm& algorithm) = delete;
/// Deleted assignment operator
CapsuleVsCapsuleAlgorithm& operator=(const CapsuleVsCapsuleAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volume collide
virtual bool testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) override;
};
}
#endif

View File

@ -1,69 +1,69 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "SphereVsSphereAlgorithm.h"
#include "collision/shapes/SphereShape.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
bool SphereVsSphereAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) {
// Get the sphere collision shapes
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(narrowPhaseInfo->collisionShape1);
const SphereShape* sphereShape2 = static_cast<const SphereShape*>(narrowPhaseInfo->collisionShape2);
// Get the local-space to world-space transforms
const Transform& transform1 = narrowPhaseInfo->shape1ToWorldTransform;
const Transform& transform2 = narrowPhaseInfo->shape2ToWorldTransform;
// Compute the distance between the centers
Vector3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition();
decimal squaredDistanceBetweenCenters = vectorBetweenCenters.lengthSquare();
// Compute the sum of the radius
decimal sumRadius = sphereShape1->getRadius() + sphereShape2->getRadius();
// If the sphere collision shapes intersect
if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) {
Vector3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition();
Vector3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition();
Vector3 intersectionOnBody1 = sphereShape1->getRadius() *
centerSphere2InBody1LocalSpace.getUnit();
Vector3 intersectionOnBody2 = sphereShape2->getRadius() *
centerSphere1InBody2LocalSpace.getUnit();
decimal penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
// Create the contact info object
contactPointInfo.init(vectorBetweenCenters.getUnit(), penetrationDepth,
intersectionOnBody1, intersectionOnBody2);
return true;
}
return false;
}
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "SphereVsSphereAlgorithm.h"
#include "collision/shapes/SphereShape.h"
// We want to use the ReactPhysics3D namespace
using namespace reactphysics3d;
bool SphereVsSphereAlgorithm::testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) {
// Get the sphere collision shapes
const SphereShape* sphereShape1 = static_cast<const SphereShape*>(narrowPhaseInfo->collisionShape1);
const SphereShape* sphereShape2 = static_cast<const SphereShape*>(narrowPhaseInfo->collisionShape2);
// Get the local-space to world-space transforms
const Transform& transform1 = narrowPhaseInfo->shape1ToWorldTransform;
const Transform& transform2 = narrowPhaseInfo->shape2ToWorldTransform;
// Compute the distance between the centers
Vector3 vectorBetweenCenters = transform2.getPosition() - transform1.getPosition();
decimal squaredDistanceBetweenCenters = vectorBetweenCenters.lengthSquare();
// Compute the sum of the radius
decimal sumRadius = sphereShape1->getRadius() + sphereShape2->getRadius();
// If the sphere collision shapes intersect
if (squaredDistanceBetweenCenters <= sumRadius * sumRadius) {
Vector3 centerSphere2InBody1LocalSpace = transform1.getInverse() * transform2.getPosition();
Vector3 centerSphere1InBody2LocalSpace = transform2.getInverse() * transform1.getPosition();
Vector3 intersectionOnBody1 = sphereShape1->getRadius() *
centerSphere2InBody1LocalSpace.getUnit();
Vector3 intersectionOnBody2 = sphereShape2->getRadius() *
centerSphere1InBody2LocalSpace.getUnit();
decimal penetrationDepth = sumRadius - std::sqrt(squaredDistanceBetweenCenters);
// Create the contact info object
contactPointInfo.init(vectorBetweenCenters.getUnit(), penetrationDepth,
intersectionOnBody1, intersectionOnBody2);
return true;
}
return false;
}

View File

@ -1,71 +1,71 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_SPHERE_VS_SPHERE_ALGORITHM_H
#define REACTPHYSICS3D_SPHERE_VS_SPHERE_ALGORITHM_H
// Libraries
#include "body/Body.h"
#include "constraint/ContactPoint.h"
#include "NarrowPhaseAlgorithm.h"
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Class SphereVsSphereAlgorithm
/**
* This class is used to compute the narrow-phase collision detection
* between two sphere collision shapes.
*/
class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
protected :
public :
// -------------------- Methods -------------------- //
/// Constructor
SphereVsSphereAlgorithm() = default;
/// Destructor
virtual ~SphereVsSphereAlgorithm() override = default;
/// Deleted copy-constructor
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Deleted assignment operator
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volume collide
virtual bool testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) override;
};
}
#endif
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_SPHERE_VS_SPHERE_ALGORITHM_H
#define REACTPHYSICS3D_SPHERE_VS_SPHERE_ALGORITHM_H
// Libraries
#include "body/Body.h"
#include "constraint/ContactPoint.h"
#include "NarrowPhaseAlgorithm.h"
/// Namespace ReactPhysics3D
namespace reactphysics3d {
// Class SphereVsSphereAlgorithm
/**
* This class is used to compute the narrow-phase collision detection
* between two sphere collision shapes.
*/
class SphereVsSphereAlgorithm : public NarrowPhaseAlgorithm {
protected :
public :
// -------------------- Methods -------------------- //
/// Constructor
SphereVsSphereAlgorithm() = default;
/// Destructor
virtual ~SphereVsSphereAlgorithm() override = default;
/// Deleted copy-constructor
SphereVsSphereAlgorithm(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Deleted assignment operator
SphereVsSphereAlgorithm& operator=(const SphereVsSphereAlgorithm& algorithm) = delete;
/// Compute a contact info if the two bounding volume collide
virtual bool testCollision(const NarrowPhaseInfo* narrowPhaseInfo,
ContactPointInfo& contactPointInfo) override;
};
}
#endif

View File

@ -1,59 +1,202 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "mathematics_functions.h"
#include "Vector3.h"
using namespace reactphysics3d;
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
/// This method uses the technique described in the book Real-Time collision detection by
/// Christer Ericson.
void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
const Vector3& p, decimal& u, decimal& v, decimal& w) {
const Vector3 v0 = b - a;
const Vector3 v1 = c - a;
const Vector3 v2 = p - a;
decimal d00 = v0.dot(v0);
decimal d01 = v0.dot(v1);
decimal d11 = v1.dot(v1);
decimal d20 = v2.dot(v0);
decimal d21 = v2.dot(v1);
decimal denom = d00 * d11 - d01 * d01;
v = (d11 * d20 - d01 * d21) / denom;
w = (d00 * d21 - d01 * d20) / denom;
u = decimal(1.0) - v - w;
}
// Clamp a vector such that it is no longer than a given maximum length
Vector3 reactphysics3d::clamp(const Vector3& vector, decimal maxLength) {
if (vector.lengthSquare() > maxLength * maxLength) {
return vector.getUnit() * maxLength;
}
return vector;
}
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "mathematics_functions.h"
#include "Vector3.h"
#include <cassert>
using namespace reactphysics3d;
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
/// This method uses the technique described in the book Real-Time collision detection by
/// Christer Ericson.
void reactphysics3d::computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
const Vector3& p, decimal& u, decimal& v, decimal& w) {
const Vector3 v0 = b - a;
const Vector3 v1 = c - a;
const Vector3 v2 = p - a;
decimal d00 = v0.dot(v0);
decimal d01 = v0.dot(v1);
decimal d11 = v1.dot(v1);
decimal d20 = v2.dot(v0);
decimal d21 = v2.dot(v1);
decimal denom = d00 * d11 - d01 * d01;
v = (d11 * d20 - d01 * d21) / denom;
w = (d00 * d21 - d01 * d20) / denom;
u = decimal(1.0) - v - w;
}
/// Clamp a vector such that it is no longer than a given maximum length
Vector3 reactphysics3d::clamp(const Vector3& vector, decimal maxLength) {
if (vector.lengthSquare() > maxLength * maxLength) {
return vector.getUnit() * maxLength;
}
return vector;
}
/// Compute and return a point on segment from "segPointA" and "segPointB" that is closest to point "pointC"
Vector3 reactphysics3d::computeClosestPointOnSegment(const Vector3& segPointA, const Vector3& segPointB, const Vector3& pointC) {
const Vector3 ab = segPointB - segPointA;
decimal abLengthSquare = ab.lengthSquare();
// If the segment has almost zero length
if (abLengthSquare < MACHINE_EPSILON) {
// Return one end-point of the segment as the closest point
return segPointA;
}
// Project point C onto "AB" line
decimal t = (pointC - segPointA).dot(ab) / abLengthSquare;
// If projected point onto the line is outside the segment, clamp it to the segment
if (t < decimal(0.0)) t = decimal(0.0);
if (t > decimal(1.0)) t = decimal(1.0);
// Return the closest point on the segment
return segPointA + t * ab;
}
/// Compute the closest points between two segments
/// This method uses the technique described in the book Real-Time
/// collision detection by Christer Ericson.
void computeClosestPointBetweenTwoSegments(const Vector3& seg1PointA, const Vector3& seg1PointB,
const Vector3& seg2PointA, const Vector3& seg2PointB,
Vector3& closestPointSeg1, Vector3& closestPointSeg2) {
const Vector3 d1 = seg1PointB - seg1PointA;
const Vector3 d2 = seg2PointB - seg2PointA;
const Vector3 r = seg1PointA - seg2PointA;
decimal a = d1.lengthSquare();
decimal e = d2.lengthSquare();
decimal f = d2.dot(r);
decimal s, t;
// If both segments degenerate into points
if (a <= MACHINE_EPSILON && e <= MACHINE_EPSILON) {
closestPointSeg1 = seg1PointA;
closestPointSeg2 = seg2PointA;
return;
}
if (a <= MACHINE_EPSILON) { // If first segment degenerates into a point
s = decimal(0.0);
// Compute the closest point on second segment
t = clamp(f / e, decimal(0.0), decimal(1.0));
}
else {
decimal c = d1.dot(r);
// If the second segment degenerates into a point
if (e <= MACHINE_EPSILON) {
t = decimal(0.0);
s = clamp(-c / a, decimal(0.0), decimal(1.0));
}
else {
decimal b = d1.dot(d2);
decimal denom = a * e - b * b;
// If the segments are not parallel
if (denom != decimal(0.0)) {
// Compute the closest point on line 1 to line 2 and
// clamp to first segment.
s = clamp((b * f - c * e) / denom, decimal(0.0), decimal(1.0));
}
else {
// Pick an arbitrary point on first segment
s = decimal(0.0);
}
// Compute the point on line 2 closest to the closest point
// we have just found
t = (b * s + f) / e;
// If this closest point is inside second segment (t in [0, 1]), we are done.
// Otherwise, we clamp the point to the second segment and compute again the
// closest point on segment 1
if (t < decimal(0.0)) {
t = decimal(0.0);
s = clamp(-c / a, decimal(0.0), decimal(1.0));
}
else if (t > decimal(1.0)) {
t = decimal(1.0);
s = clamp((b - c) / a, decimal(0.0), decimal(1.0));
}
}
}
// Compute the closest points on both segments
closestPointSeg1 = seg1PointA + d1 * s;
closestPointSeg2 = seg2PointA + d2 * t;
}
/// Compute the intersection between a plane and a segment
// Let the plane define by the equation planeNormal.dot(X) = planeD with X a point on the plane and "planeNormal" the plane normal. This method
// computes the intersection P between the plane and the segment (segA, segB). The method returns the value "t" such
// that P = segA + t * (segB - segA). Note that it only returns a value in [0, 1] if there is an intersection. Otherwise,
// there is no intersection between the plane and the segment.
decimal computePlaneSegmentIntersection(const Vector3& segA, const Vector3& segB, const decimal planeD, const Vector3& planeNormal) {
const decimal parallelEpsilon = decimal(0.0001);
decimal t = decimal(-1);
// Segment AB
const Vector3 ab = segB - segA;
decimal nDotAB = planeNormal.dot(ab);
// If the segment is not parallel to the plane
if (nDotAB > parallelEpsilon) {
t = (planeD - planeNormal.dot(segA)) / nDotAB;
}
return t;
}
/// Compute the distance between a point "point" and a line given by the points "linePointA" and "linePointB"
decimal computeDistancePointToLineDistance(const Vector3& linePointA, const Vector3& linePointB, const Vector3& point) {
decimal distAB = (linePointB - linePointA).length();
if (distAB < MACHINE_EPSILON) {
return (point - linePointA).length();
}
return ((point - linePointA).cross(point - linePointB)).length() / distAB;
}

View File

@ -1,87 +1,103 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_MATHEMATICS_FUNCTIONS_H
#define REACTPHYSICS3D_MATHEMATICS_FUNCTIONS_H
// Libraries
#include "configuration.h"
#include "decimal.h"
#include <algorithm>
#include <cassert>
#include <cmath>
/// ReactPhysics3D namespace
namespace reactphysics3d {
struct Vector3;
// ---------- Mathematics functions ---------- //
/// Function to test if two real numbers are (almost) equal
/// We test if two numbers a and b are such that (a-b) are in [-EPSILON; EPSILON]
inline bool approxEqual(decimal a, decimal b, decimal epsilon = MACHINE_EPSILON) {
return (std::fabs(a - b) < epsilon);
}
/// Function that returns the result of the "value" clamped by
/// two others values "lowerLimit" and "upperLimit"
inline int clamp(int value, int lowerLimit, int upperLimit) {
assert(lowerLimit <= upperLimit);
return std::min(std::max(value, lowerLimit), upperLimit);
}
/// Function that returns the result of the "value" clamped by
/// two others values "lowerLimit" and "upperLimit"
inline decimal clamp(decimal value, decimal lowerLimit, decimal upperLimit) {
assert(lowerLimit <= upperLimit);
return std::min(std::max(value, lowerLimit), upperLimit);
}
/// Return the minimum value among three values
inline decimal min3(decimal a, decimal b, decimal c) {
return std::min(std::min(a, b), c);
}
/// Return the maximum value among three values
inline decimal max3(decimal a, decimal b, decimal c) {
return std::max(std::max(a, b), c);
}
/// Return true if two values have the same sign
inline bool sameSign(decimal a, decimal b) {
return a * b >= decimal(0.0);
}
/// Clamp a vector such that it is no longer than a given maximum length
Vector3 clamp(const Vector3& vector, decimal maxLength);
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
void computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
const Vector3& p, decimal& u, decimal& v, decimal& w);
}
#endif
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef REACTPHYSICS3D_MATHEMATICS_FUNCTIONS_H
#define REACTPHYSICS3D_MATHEMATICS_FUNCTIONS_H
// Libraries
#include "configuration.h"
#include "decimal.h"
#include <algorithm>
#include <cassert>
#include <cmath>
/// ReactPhysics3D namespace
namespace reactphysics3d {
struct Vector3;
// ---------- Mathematics functions ---------- //
/// Function to test if two real numbers are (almost) equal
/// We test if two numbers a and b are such that (a-b) are in [-EPSILON; EPSILON]
inline bool approxEqual(decimal a, decimal b, decimal epsilon = MACHINE_EPSILON) {
return (std::fabs(a - b) < epsilon);
}
/// Function that returns the result of the "value" clamped by
/// two others values "lowerLimit" and "upperLimit"
inline int clamp(int value, int lowerLimit, int upperLimit) {
assert(lowerLimit <= upperLimit);
return std::min(std::max(value, lowerLimit), upperLimit);
}
/// Function that returns the result of the "value" clamped by
/// two others values "lowerLimit" and "upperLimit"
inline decimal clamp(decimal value, decimal lowerLimit, decimal upperLimit) {
assert(lowerLimit <= upperLimit);
return std::min(std::max(value, lowerLimit), upperLimit);
}
/// Return the minimum value among three values
inline decimal min3(decimal a, decimal b, decimal c) {
return std::min(std::min(a, b), c);
}
/// Return the maximum value among three values
inline decimal max3(decimal a, decimal b, decimal c) {
return std::max(std::max(a, b), c);
}
/// Return true if two values have the same sign
inline bool sameSign(decimal a, decimal b) {
return a * b >= decimal(0.0);
}
/// Clamp a vector such that it is no longer than a given maximum length
Vector3 clamp(const Vector3& vector, decimal maxLength);
// Compute and return a point on segment from "segPointA" and "segPointB" that is closest to point "pointC"
Vector3 computeClosestPointOnSegment(const Vector3& segPointA, const Vector3& segPointB, const Vector3& pointC);
// Compute the closest points between two segments
void computeClosestPointBetweenTwoSegments(const Vector3& seg1PointA, const Vector3& seg1PointB,
const Vector3& seg2PointA, const Vector3& seg2PointB,
Vector3& closestPointSeg1, Vector3& closestPointSeg2);
/// Compute the barycentric coordinates u, v, w of a point p inside the triangle (a, b, c)
void computeBarycentricCoordinatesInTriangle(const Vector3& a, const Vector3& b, const Vector3& c,
const Vector3& p, decimal& u, decimal& v, decimal& w);
/// Compute the intersection between a plane and a segment
decimal computePlaneSegmentIntersection(const Vector3& segA, const Vector3& segB, const decimal planeD, const Vector3& planeNormal);
/// Compute the distance between a point and a line
decimal computeDistancePointToLineDistance(const Vector3& linePointA, const Vector3& linePointB, const Vector3& point);
}
#endif

View File

@ -1,133 +1,179 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef TEST_MATHEMATICS_FUNCTIONS_H
#define TEST_MATHEMATICS_FUNCTIONS_H
// Libraries
#include "Test.h"
#include "mathematics/mathematics_functions.h"
/// Reactphysics3D namespace
namespace reactphysics3d {
// Class TestMathematicsFunctions
/**
* Unit test for mathematics functions
*/
class TestMathematicsFunctions : public Test {
private :
// ---------- Atributes ---------- //
public :
// ---------- Methods ---------- //
/// Constructor
TestMathematicsFunctions(const std::string& name): Test(name) {}
/// Run the tests
void run() {
// Test approxEqual()
test(approxEqual(2, 7, 5.2));
test(approxEqual(7, 2, 5.2));
test(approxEqual(6, 6));
test(!approxEqual(1, 5));
test(!approxEqual(1, 5, 3));
test(approxEqual(-2, -2));
test(approxEqual(-2, -7, 6));
test(!approxEqual(-2, 7, 2));
test(approxEqual(-3, 8, 12));
test(!approxEqual(-3, 8, 6));
// Test clamp()
test(clamp(4, -3, 5) == 4);
test(clamp(-3, 1, 8) == 1);
test(clamp(45, -6, 7) == 7);
test(clamp(-5, -2, -1) == -2);
test(clamp(-5, -9, -1) == -5);
test(clamp(6, 6, 9) == 6);
test(clamp(9, 6, 9) == 9);
test(clamp(decimal(4), decimal(-3), decimal(5)) == decimal(4));
test(clamp(decimal(-3), decimal(1), decimal(8)) == decimal(1));
test(clamp(decimal(45), decimal(-6), decimal(7)) == decimal(7));
test(clamp(decimal(-5), decimal(-2), decimal(-1)) == decimal(-2));
test(clamp(decimal(-5), decimal(-9), decimal(-1)) == decimal(-5));
test(clamp(decimal(6), decimal(6), decimal(9)) == decimal(6));
test(clamp(decimal(9), decimal(6), decimal(9)) == decimal(9));
// Test min3()
test(min3(1, 5, 7) == 1);
test(min3(-4, 2, 4) == -4);
test(min3(-1, -5, -7) == -7);
test(min3(13, 5, 47) == 5);
test(min3(4, 4, 4) == 4);
// Test max3()
test(max3(1, 5, 7) == 7);
test(max3(-4, 2, 4) == 4);
test(max3(-1, -5, -7) == -1);
test(max3(13, 5, 47) == 47);
test(max3(4, 4, 4) == 4);
// Test sameSign()
test(sameSign(4, 53));
test(sameSign(-4, -8));
test(!sameSign(4, -7));
test(!sameSign(-4, 53));
// Test computeBarycentricCoordinatesInTriangle()
Vector3 a(0, 0, 0);
Vector3 b(5, 0, 0);
Vector3 c(0, 0, 5);
Vector3 testPoint(4, 0, 1);
decimal u,v,w;
computeBarycentricCoordinatesInTriangle(a, b, c, a, u, v, w);
test(approxEqual(u, 1.0, 0.000001));
test(approxEqual(v, 0.0, 0.000001));
test(approxEqual(w, 0.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, b, u, v, w);
test(approxEqual(u, 0.0, 0.000001));
test(approxEqual(v, 1.0, 0.000001));
test(approxEqual(w, 0.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, c, u, v, w);
test(approxEqual(u, 0.0, 0.000001));
test(approxEqual(v, 0.0, 0.000001));
test(approxEqual(w, 1.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, testPoint, u, v, w);
test(approxEqual(u + v + w, 1.0, 0.000001));
}
};
}
#endif
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef TEST_MATHEMATICS_FUNCTIONS_H
#define TEST_MATHEMATICS_FUNCTIONS_H
// Libraries
#include "Test.h"
#include "mathematics/mathematics_functions.h"
/// Reactphysics3D namespace
namespace reactphysics3d {
// Class TestMathematicsFunctions
/**
* Unit test for mathematics functions
*/
class TestMathematicsFunctions : public Test {
private :
// ---------- Atributes ---------- //
public :
// ---------- Methods ---------- //
/// Constructor
TestMathematicsFunctions(const std::string& name): Test(name) {}
/// Run the tests
void run() {
// Test approxEqual()
test(approxEqual(2, 7, 5.2));
test(approxEqual(7, 2, 5.2));
test(approxEqual(6, 6));
test(!approxEqual(1, 5));
test(!approxEqual(1, 5, 3));
test(approxEqual(-2, -2));
test(approxEqual(-2, -7, 6));
test(!approxEqual(-2, 7, 2));
test(approxEqual(-3, 8, 12));
test(!approxEqual(-3, 8, 6));
// Test clamp()
test(clamp(4, -3, 5) == 4);
test(clamp(-3, 1, 8) == 1);
test(clamp(45, -6, 7) == 7);
test(clamp(-5, -2, -1) == -2);
test(clamp(-5, -9, -1) == -5);
test(clamp(6, 6, 9) == 6);
test(clamp(9, 6, 9) == 9);
test(clamp(decimal(4), decimal(-3), decimal(5)) == decimal(4));
test(clamp(decimal(-3), decimal(1), decimal(8)) == decimal(1));
test(clamp(decimal(45), decimal(-6), decimal(7)) == decimal(7));
test(clamp(decimal(-5), decimal(-2), decimal(-1)) == decimal(-2));
test(clamp(decimal(-5), decimal(-9), decimal(-1)) == decimal(-5));
test(clamp(decimal(6), decimal(6), decimal(9)) == decimal(6));
test(clamp(decimal(9), decimal(6), decimal(9)) == decimal(9));
// Test min3()
test(min3(1, 5, 7) == 1);
test(min3(-4, 2, 4) == -4);
test(min3(-1, -5, -7) == -7);
test(min3(13, 5, 47) == 5);
test(min3(4, 4, 4) == 4);
// Test max3()
test(max3(1, 5, 7) == 7);
test(max3(-4, 2, 4) == 4);
test(max3(-1, -5, -7) == -1);
test(max3(13, 5, 47) == 47);
test(max3(4, 4, 4) == 4);
// Test sameSign()
test(sameSign(4, 53));
test(sameSign(-4, -8));
test(!sameSign(4, -7));
test(!sameSign(-4, 53));
// Test computeBarycentricCoordinatesInTriangle()
Vector3 a(0, 0, 0);
Vector3 b(5, 0, 0);
Vector3 c(0, 0, 5);
Vector3 testPoint(4, 0, 1);
decimal u,v,w;
computeBarycentricCoordinatesInTriangle(a, b, c, a, u, v, w);
test(approxEqual(u, 1.0, 0.000001));
test(approxEqual(v, 0.0, 0.000001));
test(approxEqual(w, 0.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, b, u, v, w);
test(approxEqual(u, 0.0, 0.000001));
test(approxEqual(v, 1.0, 0.000001));
test(approxEqual(w, 0.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, c, u, v, w);
test(approxEqual(u, 0.0, 0.000001));
test(approxEqual(v, 0.0, 0.000001));
test(approxEqual(w, 1.0, 0.000001));
computeBarycentricCoordinatesInTriangle(a, b, c, testPoint, u, v, w);
test(approxEqual(u + v + w, 1.0, 0.000001));
// Test computeClosestPointBetweenTwoSegments()
Vector3 closestSeg1, closestSeg2;
computeClosestPointBetweenTwoSegments(Vector3(4, 0, 0), Vector3(6, 0, 0), Vector3(8, 0, 0), Vector3(8, 6, 0), closestSeg1, closestSeg2);
test(approxEqual(closestSeg1.x, 6.0, 0.000001));
test(approxEqual(closestSeg1.y, 0.0, 0.000001));
test(approxEqual(closestSeg1.z, 0.0, 0.000001));
test(approxEqual(closestSeg2.x, 8.0, 0.000001));
test(approxEqual(closestSeg2.y, 0.0, 0.000001));
test(approxEqual(closestSeg2.z, 0.0, 0.000001));
computeClosestPointBetweenTwoSegments(Vector3(4, 6, 5), Vector3(4, 6, 5), Vector3(8, 3, -9), Vector3(8, 3, -9), closestSeg1, closestSeg2);
test(approxEqual(closestSeg1.x, 4.0, 0.000001));
test(approxEqual(closestSeg1.y, 6.0, 0.000001));
test(approxEqual(closestSeg1.z, 5.0, 0.000001));
test(approxEqual(closestSeg2.x, 8.0, 0.000001));
test(approxEqual(closestSeg2.y, 3.0, 0.000001));
test(approxEqual(closestSeg2.z, -9.0, 0.000001));
computeClosestPointBetweenTwoSegments(Vector3(0, -5, 0), Vector3(0, 8, 0), Vector3(6, 3, 0), Vector3(10, -3, 0), closestSeg1, closestSeg2);
test(approxEqual(closestSeg1.x, 0.0, 0.000001));
test(approxEqual(closestSeg1.y, 3.0, 0.000001));
test(approxEqual(closestSeg1.z, 0.0, 0.000001));
test(approxEqual(closestSeg2.x, 6.0, 0.000001));
test(approxEqual(closestSeg2.y, 3.0, 0.000001));
test(approxEqual(closestSeg2.z, 0.0, 0.000001));
computeClosestPointBetweenTwoSegments(Vector3(1, -4, -5), Vector3(1, 4, -5), Vector3(-6, 5, -5), Vector3(6, 5, -5), closestSeg1, closestSeg2);
test(approxEqual(closestSeg1.x, 1.0, 0.000001));
test(approxEqual(closestSeg1.y, 5.0, 0.000001));
test(approxEqual(closestSeg1.z, -5.0, 0.000001));
test(approxEqual(closestSeg2.x, 1.0, 0.000001));
test(approxEqual(closestSeg2.y, 5.0, 0.000001));
test(approxEqual(closestSeg2.z, -5.0, 0.000001));
// Test computePlaneSegmentIntersection();
test(approxEqual(computePlaneSegmentIntersection(Vector3(-6, 3, 0), Vector3(6, 3, 0), 0.0, Vector3(-1, 0, 0)), 0.5, 0.000001));
test(approxEqual(computePlaneSegmentIntersection(Vector3(-6, 3, 0), Vector3(6, 3, 0), 0.0, Vector3(1, 0, 0)), 0.5, 0.000001));
test(approxEqual(computePlaneSegmentIntersection(Vector3(5, 12, 0), Vector3(5, 4, 0), 6, Vector3(0, 1, 0)), 0.75, 0.000001));
test(approxEqual(computePlaneSegmentIntersection(Vector3(5, 4, 8), Vector3(9, 14, 8), 4, Vector3(0, 1, 0)), 0.0, 0.000001));
decimal tIntersect = computePlaneSegmentIntersection(Vector3(5, 4, 0), Vector3(9, 4, 0), 4, Vector3(0, 1, 0));
test(tIntersect < 0.0 && tIntersect > 1.0);
// Test computeDistancePointToLineDistance()
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, 0, 0), Vector3(14, 0, 0), Vector3(5, 3, 0)), 3.0, 0.000001));
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, -5, 0), Vector3(10, -5, 0), Vector3(4, 3, 0)), 8.0, 0.000001));
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, -5, 0), Vector3(10, -5, 0), Vector3(-43, 254, 0)), 259.0, 0.000001));
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, -5, 8), Vector3(10, -5, -5), Vector3(6, -5, 8)), 0.0, 0.000001));
test(approxEqual(computeDistancePointToLineDistance(Vector3(6, -5, 8), Vector3(10, -5, -5), Vector3(10, -5, -5)), 0.0, 0.000001));
}
};
}
#endif

View File

@ -1,415 +1,417 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "CollisionDetectionScene.h"
// Namespaces
using namespace openglframework;
using namespace collisiondetectionscene;
// Constructor
CollisionDetectionScene::CollisionDetectionScene(const std::string& name)
: SceneDemo(name, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
mContactManager(mPhongShader, mMeshFolderPath),
mAreNormalsDisplayed(false), mVBOVertices(GL_ARRAY_BUFFER) {
mSelectedShapeIndex = 0;
mIsContactPointsDisplayed = true;
mIsWireframeEnabled = true;
// Compute the radius and the center of the scene
openglframework::Vector3 center(0, 0, 0);
// Set the center of the scene
setScenePosition(center, SCENE_RADIUS);
// Create the dynamics world for the physics simulation
mCollisionWorld = new rp3d::CollisionWorld();
// ---------- Sphere 1 ---------- //
openglframework::Vector3 position1(0, 0, 0);
// Create a sphere and a corresponding collision body in the dynamics world
mSphere1 = new Sphere(6, position1, mCollisionWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere1);
// Set the color
mSphere1->setColor(mGreyColorDemo);
mSphere1->setSleepingColor(mRedColorDemo);
// ---------- Sphere 2 ---------- //
openglframework::Vector3 position2(4, 0, 0);
// Create a sphere and a corresponding collision body in the dynamics world
mSphere2 = new Sphere(4, position2, mCollisionWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere2);
// Set the color
mSphere2->setColor(mGreyColorDemo);
mSphere2->setSleepingColor(mRedColorDemo);
// ---------- Cone ---------- //
//openglframework::Vector3 position4(0, 0, 0);
// Create a cone and a corresponding collision body in the dynamics world
//mCone = new Cone(CONE_RADIUS, CONE_HEIGHT, position4, mCollisionWorld,
// mMeshFolderPath);
// Set the color
//mCone->setColor(mGreyColorDemo);
//mCone->setSleepingColor(mRedColorDemo);
// ---------- Cylinder ---------- //
//openglframework::Vector3 position5(0, 0, 0);
// Create a cylinder and a corresponding collision body in the dynamics world
//mCylinder = new Cylinder(CYLINDER_RADIUS, CYLINDER_HEIGHT, position5,
// mCollisionWorld, mMeshFolderPath);
// Set the color
//mCylinder->setColor(mGreyColorDemo);
//mCylinder->setSleepingColor(mRedColorDemo);
// ---------- Capsule ---------- //
//openglframework::Vector3 position6(0, 0, 0);
// Create a cylinder and a corresponding collision body in the dynamics world
//mCapsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, position6 ,
// mCollisionWorld, mMeshFolderPath);
// Set the color
//mCapsule->setColor(mGreyColorDemo);
//mCapsule->setSleepingColor(mRedColorDemo);
// ---------- Convex Mesh ---------- //
//openglframework::Vector3 position7(0, 0, 0);
// Create a convex mesh and a corresponding collision body in the dynamics world
//mConvexMesh = new ConvexMesh(position7, mCollisionWorld, mMeshFolderPath + "convexmesh.obj");
// Set the color
//mConvexMesh->setColor(mGreyColorDemo);
//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 + "city.obj");
// Set the color
//mConcaveMesh->setColor(mGreyColorDemo);
//mConcaveMesh->setSleepingColor(mRedColorDemo);
// ---------- Heightfield ---------- //
//openglframework::Vector3 position9(0, 0, 0);
// Create a convex mesh and a corresponding collision body in the dynamics world
//mHeightField = new HeightField(position9, mCollisionWorld);
// Set the color
//mHeightField->setColor(mGreyColorDemo);
//mHeightField->setSleepingColor(mRedColorDemo);
// Create the VBO and VAO to render the lines
createVBOAndVAO(mPhongShader);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo);
}
// Reset the scene
void CollisionDetectionScene::reset() {
}
// Destructor
CollisionDetectionScene::~CollisionDetectionScene() {
// Destroy the shader
mPhongShader.destroy();
// Destroy the box rigid body from the dynamics world
//mCollisionWorld->destroyCollisionBody(mBox->getCollisionBody());
//delete mBox;
// Destroy the spheres
mCollisionWorld->destroyCollisionBody(mSphere1->getCollisionBody());
delete mSphere1;
mCollisionWorld->destroyCollisionBody(mSphere2->getCollisionBody());
delete mSphere2;
/*
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCone->getCollisionBody());
delete mCone;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCylinder->getCollisionBody());
// Destroy the sphere
delete mCylinder;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCapsule->getCollisionBody());
// Destroy the sphere
delete mCapsule;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mConvexMesh->getCollisionBody());
// Destroy the convex mesh
delete mConvexMesh;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody());
// Destroy the dumbbell
delete mDumbbell;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody());
// Destroy the convex mesh
delete mConcaveMesh;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mHeightField->getCollisionBody());
// Destroy the convex mesh
delete mHeightField;
*/
mContactManager.resetPoints();
// Destroy the static data for the visual contact points
VisualContactPoint::destroyStaticData();
// Destroy the collision world
delete mCollisionWorld;
// Destroy the VBOs and VAO
mVBOVertices.destroy();
mVAO.destroy();
}
// Update the physics world (take a simulation step)
void CollisionDetectionScene::updatePhysics() {
}
// Take a step for the simulation
void CollisionDetectionScene::update() {
mContactManager.resetPoints();
mCollisionWorld->testCollision(&mContactManager);
SceneDemo::update();
}
// Render the scene
void CollisionDetectionScene::renderSinglePass(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) {
/*
// Bind the VAO
mVAO.bind();
// Bind the shader
shader.bind();
mVBOVertices.bind();
// Set the model to camera matrix
const Matrix4 localToCameraMatrix = Matrix4::identity();
shader.setMatrix4x4Uniform("localToWorldMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color
openglframework::Vector4 color(1, 0, 0, 1);
shader.setVector4Uniform("vertexColor", color, false);
// Get the location of shader attribute variables
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
glEnableVertexAttribArray(vertexPositionLoc);
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
// Draw the lines
glDrawArrays(GL_LINES, 0, NB_RAYS);
glDisableVertexAttribArray(vertexPositionLoc);
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
shader.unbind();
*/
// Render the shapes
if (mSphere1->getCollisionBody()->isActive()) mSphere1->render(shader, worldToCameraMatrix, mIsWireframeEnabled);
if (mSphere2->getCollisionBody()->isActive()) mSphere2->render(shader, worldToCameraMatrix, mIsWireframeEnabled);
/*
if (mBox->getCollisionBody()->isActive()) mBox->render(shader, worldToCameraMatrix);
if (mCone->getCollisionBody()->isActive()) mCone->render(shader, worldToCameraMatrix);
if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(shader, worldToCameraMatrix);
if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix);
if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix);
if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix);
if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix);
if (mHeightField->getCollisionBody()->isActive()) mHeightField->render(shader, worldToCameraMatrix);
*/
shader.unbind();
}
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void CollisionDetectionScene::createVBOAndVAO(openglframework::Shader& shader) {
// Bind the shader
shader.bind();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mLinePoints.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, &mLinePoints[0], GL_STATIC_DRAW);
mVBOVertices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
void CollisionDetectionScene::selectNextShape() {
int previousIndex = mSelectedShapeIndex;
mSelectedShapeIndex++;
if (mSelectedShapeIndex >= mAllShapes.size()) {
mSelectedShapeIndex = 0;
}
mAllShapes[previousIndex]->setColor(mGreyColorDemo);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo);
}
// Called when a keyboard event occurs
bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, int mods) {
// If the space key has been pressed
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
selectNextShape();
return true;
}
float stepDist = 0.5f;
float stepAngle = 20 * (3.14f / 180.0f);
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(-stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_UP && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, -stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_Z && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_H && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, -stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_A && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_D && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, -stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_W && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_S && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(-stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_F && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, 0, stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_G && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, 0, -stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
return false;
}
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
// Libraries
#include "CollisionDetectionScene.h"
// Namespaces
using namespace openglframework;
using namespace collisiondetectionscene;
// Constructor
CollisionDetectionScene::CollisionDetectionScene(const std::string& name)
: SceneDemo(name, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
mContactManager(mPhongShader, mMeshFolderPath),
mAreNormalsDisplayed(false), mVBOVertices(GL_ARRAY_BUFFER) {
mSelectedShapeIndex = 0;
mIsContactPointsDisplayed = true;
mIsWireframeEnabled = true;
// Compute the radius and the center of the scene
openglframework::Vector3 center(0, 0, 0);
// Set the center of the scene
setScenePosition(center, SCENE_RADIUS);
// Create the dynamics world for the physics simulation
mCollisionWorld = new rp3d::CollisionWorld();
// ---------- Sphere 1 ---------- //
openglframework::Vector3 position1(0, 0, 0);
// Create a sphere and a corresponding collision body in the dynamics world
mSphere1 = new Sphere(6, position1, mCollisionWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere1);
// Set the color
mSphere1->setColor(mGreyColorDemo);
mSphere1->setSleepingColor(mRedColorDemo);
// ---------- Sphere 2 ---------- //
openglframework::Vector3 position2(4, 0, 0);
// Create a sphere and a corresponding collision body in the dynamics world
mSphere2 = new Sphere(4, position2, mCollisionWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere2);
// Set the color
mSphere2->setColor(mGreyColorDemo);
mSphere2->setSleepingColor(mRedColorDemo);
// ---------- Capsule 1 ---------- //
openglframework::Vector3 position3(4, 0, 0);
// Create a cylinder and a corresponding collision body in the dynamics world
mCapsule1 = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, position3, mCollisionWorld, mMeshFolderPath);
mAllShapes.push_back(mCapsule1);
// Set the color
mCapsule1->setColor(mGreyColorDemo);
mCapsule1->setSleepingColor(mRedColorDemo);
// ---------- Cone ---------- //
//openglframework::Vector3 position4(0, 0, 0);
// Create a cone and a corresponding collision body in the dynamics world
//mCone = new Cone(CONE_RADIUS, CONE_HEIGHT, position4, mCollisionWorld,
// mMeshFolderPath);
// Set the color
//mCone->setColor(mGreyColorDemo);
//mCone->setSleepingColor(mRedColorDemo);
// ---------- Cylinder ---------- //
//openglframework::Vector3 position5(0, 0, 0);
// Create a cylinder and a corresponding collision body in the dynamics world
//mCylinder = new Cylinder(CYLINDER_RADIUS, CYLINDER_HEIGHT, position5,
// mCollisionWorld, mMeshFolderPath);
// Set the color
//mCylinder->setColor(mGreyColorDemo);
//mCylinder->setSleepingColor(mRedColorDemo);
// ---------- Convex Mesh ---------- //
//openglframework::Vector3 position7(0, 0, 0);
// Create a convex mesh and a corresponding collision body in the dynamics world
//mConvexMesh = new ConvexMesh(position7, mCollisionWorld, mMeshFolderPath + "convexmesh.obj");
// Set the color
//mConvexMesh->setColor(mGreyColorDemo);
//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 + "city.obj");
// Set the color
//mConcaveMesh->setColor(mGreyColorDemo);
//mConcaveMesh->setSleepingColor(mRedColorDemo);
// ---------- Heightfield ---------- //
//openglframework::Vector3 position9(0, 0, 0);
// Create a convex mesh and a corresponding collision body in the dynamics world
//mHeightField = new HeightField(position9, mCollisionWorld);
// Set the color
//mHeightField->setColor(mGreyColorDemo);
//mHeightField->setSleepingColor(mRedColorDemo);
// Create the VBO and VAO to render the lines
//createVBOAndVAO(mPhongShader);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo);
}
// Reset the scene
void CollisionDetectionScene::reset() {
}
// Destructor
CollisionDetectionScene::~CollisionDetectionScene() {
// Destroy the shader
mPhongShader.destroy();
// Destroy the box rigid body from the dynamics world
//mCollisionWorld->destroyCollisionBody(mBox->getCollisionBody());
//delete mBox;
// Destroy the spheres
mCollisionWorld->destroyCollisionBody(mSphere1->getCollisionBody());
delete mSphere1;
mCollisionWorld->destroyCollisionBody(mSphere2->getCollisionBody());
delete mSphere2;
/*
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCone->getCollisionBody());
delete mCone;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCylinder->getCollisionBody());
// Destroy the sphere
delete mCylinder;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCapsule->getCollisionBody());
// Destroy the sphere
delete mCapsule;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mConvexMesh->getCollisionBody());
// Destroy the convex mesh
delete mConvexMesh;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody());
// Destroy the dumbbell
delete mDumbbell;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody());
// Destroy the convex mesh
delete mConcaveMesh;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mHeightField->getCollisionBody());
// Destroy the convex mesh
delete mHeightField;
*/
mContactManager.resetPoints();
// Destroy the static data for the visual contact points
VisualContactPoint::destroyStaticData();
// Destroy the collision world
delete mCollisionWorld;
// Destroy the VBOs and VAO
mVBOVertices.destroy();
mVAO.destroy();
}
// Update the physics world (take a simulation step)
void CollisionDetectionScene::updatePhysics() {
}
// Take a step for the simulation
void CollisionDetectionScene::update() {
mContactManager.resetPoints();
mCollisionWorld->testCollision(&mContactManager);
SceneDemo::update();
}
// Render the scene
void CollisionDetectionScene::renderSinglePass(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) {
/*
// Bind the VAO
mVAO.bind();
// Bind the shader
shader.bind();
mVBOVertices.bind();
// Set the model to camera matrix
const Matrix4 localToCameraMatrix = Matrix4::identity();
shader.setMatrix4x4Uniform("localToWorldMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color
openglframework::Vector4 color(1, 0, 0, 1);
shader.setVector4Uniform("vertexColor", color, false);
// Get the location of shader attribute variables
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
glEnableVertexAttribArray(vertexPositionLoc);
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
// Draw the lines
glDrawArrays(GL_LINES, 0, NB_RAYS);
glDisableVertexAttribArray(vertexPositionLoc);
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
shader.unbind();
*/
// Render the shapes
if (mSphere1->getCollisionBody()->isActive()) mSphere1->render(shader, worldToCameraMatrix, mIsWireframeEnabled);
if (mSphere2->getCollisionBody()->isActive()) mSphere2->render(shader, worldToCameraMatrix, mIsWireframeEnabled);
if (mCapsule1->getCollisionBody()->isActive()) mCapsule1->render(shader, worldToCameraMatrix, mIsWireframeEnabled);
/*
if (mBox->getCollisionBody()->isActive()) mBox->render(shader, worldToCameraMatrix);
if (mCone->getCollisionBody()->isActive()) mCone->render(shader, worldToCameraMatrix);
if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(shader, worldToCameraMatrix);
if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix);
if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix);
if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix);
if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix);
if (mHeightField->getCollisionBody()->isActive()) mHeightField->render(shader, worldToCameraMatrix);
*/
shader.unbind();
}
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void CollisionDetectionScene::createVBOAndVAO(openglframework::Shader& shader) {
// Bind the shader
shader.bind();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mLinePoints.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, &mLinePoints[0], GL_STATIC_DRAW);
mVBOVertices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
void CollisionDetectionScene::selectNextShape() {
int previousIndex = mSelectedShapeIndex;
mSelectedShapeIndex++;
if (mSelectedShapeIndex >= mAllShapes.size()) {
mSelectedShapeIndex = 0;
}
mAllShapes[previousIndex]->setColor(mGreyColorDemo);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo);
}
// Called when a keyboard event occurs
bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, int mods) {
// If the space key has been pressed
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
selectNextShape();
return true;
}
float stepDist = 0.5f;
float stepAngle = 20 * (3.14f / 180.0f);
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(-stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_UP && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, -stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_Z && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_H && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, -stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_A && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_D && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, -stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_W && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_S && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(-stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_F && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, 0, stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
else if (key == GLFW_KEY_G && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion(0, 0, -stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform);
}
return false;
}

View File

@ -1,231 +1,235 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef COLLISION_DETECTION_SCENE_H
#define COLLISION_DETECTION_SCENE_H
// Libraries
#include <cmath>
#include "openglframework.h"
#include "reactphysics3d.h"
#include "SceneDemo.h"
#include "Sphere.h"
#include "Box.h"
#include "Capsule.h"
#include "Line.h"
#include "ConvexMesh.h"
#include "ConcaveMesh.h"
#include "HeightField.h"
#include "Dumbbell.h"
#include "VisualContactPoint.h"
namespace collisiondetectionscene {
// Constants
const float SCENE_RADIUS = 30.0f;
const openglframework::Vector3 BOX_SIZE(4, 2, 1);
const float SPHERE_RADIUS = 3.0f;
const float CONE_RADIUS = 3.0f;
const float CONE_HEIGHT = 5.0f;
const float CYLINDER_RADIUS = 3.0f;
const float CYLINDER_HEIGHT = 5.0f;
const float CAPSULE_RADIUS = 3.0f;
const float CAPSULE_HEIGHT = 5.0f;
const float DUMBBELL_HEIGHT = 5.0f;
const int NB_RAYS = 100;
const float RAY_LENGTH = 30.0f;
const int NB_BODIES = 9;
// Raycast manager
class ContactManager : public rp3d::CollisionCallback {
private:
/// All the visual contact points
std::vector<ContactPoint> mContactPoints;
/// All the normals at contact points
std::vector<Line*> mNormals;
/// Contact point mesh folder path
std::string mMeshFolderPath;
public:
ContactManager(openglframework::Shader& shader,
const std::string& meshFolderPath)
: mMeshFolderPath(meshFolderPath) {
}
/// This method will be called for each reported contact point
virtual void notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) override {
rp3d::Vector3 point1 = collisionCallbackInfo.contactPoint.localPoint1;
point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1;
openglframework::Vector3 position1(point1.x, point1.y, point1.z);
mContactPoints.push_back(ContactPoint(position1));
rp3d::Vector3 point2 = collisionCallbackInfo.contactPoint.localPoint2;
point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2;
openglframework::Vector3 position2(point2.x, point2.y, point2.z);
mContactPoints.push_back(ContactPoint(position2));
// Create a line to display the normal at hit point
rp3d::Vector3 n = collisionCallbackInfo.contactPoint.normal;
openglframework::Vector3 normal(n.x, n.y, n.z);
Line* normalLine = new Line(position1, position1 + normal);
mNormals.push_back(normalLine);
}
void resetPoints() {
mContactPoints.clear();
// Destroy all the normals
for (std::vector<Line*>::iterator it = mNormals.begin();
it != mNormals.end(); ++it) {
delete (*it);
}
mNormals.clear();
}
std::vector<ContactPoint> getContactPoints() const {
return mContactPoints;
}
};
// Class CollisionDetectionScene
class CollisionDetectionScene : public SceneDemo {
private :
// -------------------- Attributes -------------------- //
/// Contact point mesh folder path
std::string mMeshFolderPath;
/// Contact manager
ContactManager mContactManager;
bool mAreNormalsDisplayed;
/// All objects on the scene
//Box* mBox;
Sphere* mSphere1;
Sphere* mSphere2;
//Cone* mCone;
//Cylinder* mCylinder;
//Capsule* mCapsule;
//ConvexMesh* mConvexMesh;
//Dumbbell* mDumbbell;
//ConcaveMesh* mConcaveMesh;
//HeightField* mHeightField;
std::vector<PhysicsObject*> mAllShapes;
int mSelectedShapeIndex;
/// Collision world used for the physics simulation
rp3d::CollisionWorld* mCollisionWorld;
/// All the points to render the lines
std::vector<openglframework::Vector3> mLinePoints;
/// Vertex Buffer Object for the vertices data
openglframework::VertexBufferObject mVBOVertices;
/// Vertex Array Object for the vertex data
openglframework::VertexArrayObject mVAO;
/// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO(openglframework::Shader& shader);
/// Select the next shape
void selectNextShape();
public:
// -------------------- Methods -------------------- //
/// Constructor
CollisionDetectionScene(const std::string& name);
/// Destructor
virtual ~CollisionDetectionScene() override;
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics() override;
/// Take a step for the simulation
virtual void update() override;
/// Render the scene in a single pass
virtual void renderSinglePass(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) override;
/// Reset the scene
virtual void reset() override;
/// Display or not the surface normals at hit points
void showHideNormals();
/// Called when a keyboard event occurs
virtual bool keyboardEvent(int key, int scancode, int action, int mods) override;
/// Enabled/Disable the shadow mapping
virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override;
/// Display/Hide the contact points
virtual void setIsContactPointsDisplayed(bool display) override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() const override;
};
// Display or not the surface normals at hit points
inline void CollisionDetectionScene::showHideNormals() {
mAreNormalsDisplayed = !mAreNormalsDisplayed;
}
// Enabled/Disable the shadow mapping
inline void CollisionDetectionScene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) {
SceneDemo::setIsShadowMappingEnabled(false);
}
// Display/Hide the contact points
inline void CollisionDetectionScene::setIsContactPointsDisplayed(bool display) {
SceneDemo::setIsContactPointsDisplayed(true);
}
// Return all the contact points of the scene
inline std::vector<ContactPoint> CollisionDetectionScene::getContactPoints() const {
return mContactManager.getContactPoints();
}
}
#endif
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis *
*********************************************************************************
* *
* This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the *
* use of this software. *
* *
* Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: *
* *
* 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be *
* appreciated but is not required. *
* *
* 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. *
* *
* 3. This notice may not be removed or altered from any source distribution. *
* *
********************************************************************************/
#ifndef COLLISION_DETECTION_SCENE_H
#define COLLISION_DETECTION_SCENE_H
// Libraries
#include <cmath>
#include "openglframework.h"
#include "reactphysics3d.h"
#include "SceneDemo.h"
#include "Sphere.h"
#include "Box.h"
#include "Cone.h"
#include "Cylinder.h"
#include "Capsule.h"
#include "Line.h"
#include "ConvexMesh.h"
#include "ConcaveMesh.h"
#include "HeightField.h"
#include "Dumbbell.h"
#include "VisualContactPoint.h"
namespace collisiondetectionscene {
// Constants
const float SCENE_RADIUS = 30.0f;
const openglframework::Vector3 BOX_SIZE(4, 2, 1);
const float SPHERE_RADIUS = 3.0f;
const float CONE_RADIUS = 3.0f;
const float CONE_HEIGHT = 5.0f;
const float CYLINDER_RADIUS = 3.0f;
const float CYLINDER_HEIGHT = 5.0f;
const float CAPSULE_RADIUS = 3.0f;
const float CAPSULE_HEIGHT = 5.0f;
const float DUMBBELL_HEIGHT = 5.0f;
const int NB_RAYS = 100;
const float RAY_LENGTH = 30.0f;
const int NB_BODIES = 9;
// Raycast manager
class ContactManager : public rp3d::CollisionCallback {
private:
/// All the visual contact points
std::vector<ContactPoint> mContactPoints;
/// All the normals at contact points
std::vector<Line*> mNormals;
/// Contact point mesh folder path
std::string mMeshFolderPath;
public:
ContactManager(openglframework::Shader& shader,
const std::string& meshFolderPath)
: mMeshFolderPath(meshFolderPath) {
}
/// This method will be called for each reported contact point
virtual void notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) override {
rp3d::Vector3 point1 = collisionCallbackInfo.contactPoint.localPoint1;
point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1;
openglframework::Vector3 position1(point1.x, point1.y, point1.z);
mContactPoints.push_back(ContactPoint(position1));
rp3d::Vector3 point2 = collisionCallbackInfo.contactPoint.localPoint2;
point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2;
openglframework::Vector3 position2(point2.x, point2.y, point2.z);
mContactPoints.push_back(ContactPoint(position2));
// Create a line to display the normal at hit point
rp3d::Vector3 n = collisionCallbackInfo.contactPoint.normal;
openglframework::Vector3 normal(n.x, n.y, n.z);
Line* normalLine = new Line(position1, position1 + normal);
mNormals.push_back(normalLine);
}
void resetPoints() {
mContactPoints.clear();
// Destroy all the normals
for (std::vector<Line*>::iterator it = mNormals.begin();
it != mNormals.end(); ++it) {
delete (*it);
}
mNormals.clear();
}
std::vector<ContactPoint> getContactPoints() const {
return mContactPoints;
}
};
// Class CollisionDetectionScene
class CollisionDetectionScene : public SceneDemo {
private :
// -------------------- Attributes -------------------- //
/// Contact point mesh folder path
std::string mMeshFolderPath;
/// Contact manager
ContactManager mContactManager;
bool mAreNormalsDisplayed;
/// All objects on the scene
//Box* mBox;
Sphere* mSphere1;
Sphere* mSphere2;
Capsule* mCapsule1;
Capsule* mCapsule2;
//Cone* mCone;
//Cylinder* mCylinder;
//Capsule* mCapsule;
//ConvexMesh* mConvexMesh;
//Dumbbell* mDumbbell;
//ConcaveMesh* mConcaveMesh;
//HeightField* mHeightField;
std::vector<PhysicsObject*> mAllShapes;
int mSelectedShapeIndex;
/// Collision world used for the physics simulation
rp3d::CollisionWorld* mCollisionWorld;
/// All the points to render the lines
std::vector<openglframework::Vector3> mLinePoints;
/// Vertex Buffer Object for the vertices data
openglframework::VertexBufferObject mVBOVertices;
/// Vertex Array Object for the vertex data
openglframework::VertexArrayObject mVAO;
/// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO(openglframework::Shader& shader);
/// Select the next shape
void selectNextShape();
public:
// -------------------- Methods -------------------- //
/// Constructor
CollisionDetectionScene(const std::string& name);
/// Destructor
virtual ~CollisionDetectionScene() override;
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics() override;
/// Take a step for the simulation
virtual void update() override;
/// Render the scene in a single pass
virtual void renderSinglePass(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) override;
/// Reset the scene
virtual void reset() override;
/// Display or not the surface normals at hit points
void showHideNormals();
/// Called when a keyboard event occurs
virtual bool keyboardEvent(int key, int scancode, int action, int mods) override;
/// Enabled/Disable the shadow mapping
virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override;
/// Display/Hide the contact points
virtual void setIsContactPointsDisplayed(bool display) override;
/// Return all the contact points of the scene
virtual std::vector<ContactPoint> getContactPoints() const override;
};
// Display or not the surface normals at hit points
inline void CollisionDetectionScene::showHideNormals() {
mAreNormalsDisplayed = !mAreNormalsDisplayed;
}
// Enabled/Disable the shadow mapping
inline void CollisionDetectionScene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) {
SceneDemo::setIsShadowMappingEnabled(false);
}
// Display/Hide the contact points
inline void CollisionDetectionScene::setIsContactPointsDisplayed(bool display) {
SceneDemo::setIsContactPointsDisplayed(true);
}
// Return all the contact points of the scene
inline std::vector<ContactPoint> CollisionDetectionScene::getContactPoints() const {
return mContactManager.getContactPoints();
}
}
#endif