From e9257ec56fd53ee3d4aec26f48d2f410d6ad37b2 Mon Sep 17 00:00:00 2001 From: Daniel Chappuis Date: Tue, 21 Oct 2014 22:26:40 +0200 Subject: [PATCH] Change raycasting so that a ray is given by two points instead of a point and a direction --- src/body/Body.h | 2 + src/body/CollisionBody.cpp | 20 +- src/body/CollisionBody.h | 6 +- src/collision/ProxyShape.h | 15 +- src/collision/RaycastInfo.h | 5 +- .../narrowphase/GJK/GJKAlgorithm.cpp | 22 +- src/collision/narrowphase/GJK/GJKAlgorithm.h | 3 +- src/collision/shapes/BoxShape.cpp | 77 +- src/collision/shapes/BoxShape.h | 6 +- src/collision/shapes/CapsuleShape.cpp | 188 ++-- src/collision/shapes/CapsuleShape.h | 16 +- src/collision/shapes/CollisionShape.h | 6 +- src/collision/shapes/ConeShape.cpp | 126 +-- src/collision/shapes/ConeShape.h | 6 +- src/collision/shapes/ConvexMeshShape.cpp | 12 +- src/collision/shapes/ConvexMeshShape.h | 6 +- src/collision/shapes/CylinderShape.cpp | 145 +-- src/collision/shapes/CylinderShape.h | 6 +- src/collision/shapes/SphereShape.cpp | 77 +- src/collision/shapes/SphereShape.h | 6 +- src/configuration.h | 3 - src/engine/CollisionWorld.cpp | 8 +- src/engine/CollisionWorld.h | 6 +- src/mathematics/Ray.h | 26 +- src/mathematics/mathematics.h | 1 + src/reactphysics3d.h | 2 + test/tests/collision/TestRaycast.h | 879 ++++++------------ 27 files changed, 463 insertions(+), 1212 deletions(-) diff --git a/src/body/Body.h b/src/body/Body.h index 9cddfc27..2a0077a1 100644 --- a/src/body/Body.h +++ b/src/body/Body.h @@ -34,6 +34,7 @@ /// Namespace reactphysics3d namespace reactphysics3d { +// TODO : Make this class abstract // Class Body /** * This class is an abstract class to represent a body of the physics engine. @@ -53,6 +54,7 @@ class Body { /// True if the body is allowed to go to sleep for better efficiency bool mIsAllowedToSleep; + // TODO : Use this variable to make bodies active or not /// True if the body is active bool mIsActive; diff --git a/src/body/CollisionBody.cpp b/src/body/CollisionBody.cpp index be539988..2cb32c8e 100644 --- a/src/body/CollisionBody.cpp +++ b/src/body/CollisionBody.cpp @@ -212,31 +212,19 @@ bool CollisionBody::testPointInside(const Vector3& worldPoint) const { return false; } -// Raycast method -bool CollisionBody::raycast(const Ray& ray) { - - // For each collision shape of the body - for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) { - - // Test if the ray hits the collision shape - if (shape->raycast(ray)) return true; - } - - return false; -} - // Raycast method with feedback information /// The method returns the closest hit among all the collision shapes of the body -bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo, decimal distance) { +bool CollisionBody::raycast(const Ray& ray, RaycastInfo& raycastInfo) { bool isHit = false; + Ray rayTemp(ray); // For each collision shape of the body for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) { // Test if the ray hits the collision shape - if (shape->raycast(ray, raycastInfo, distance)) { - distance = raycastInfo.distance; + if (shape->raycast(rayTemp, raycastInfo)) { + rayTemp.maxFraction = raycastInfo.hitFraction; isHit = true; } } diff --git a/src/body/CollisionBody.h b/src/body/CollisionBody.h index 16d50c45..a70ad41a 100644 --- a/src/body/CollisionBody.h +++ b/src/body/CollisionBody.h @@ -165,12 +165,8 @@ class CollisionBody : public Body { /// Return true if a point is inside the collision body bool testPointInside(const Vector3& worldPoint) const; - /// Raycast method - bool raycast(const Ray& ray); - /// Raycast method with feedback information - bool raycast(const Ray& ray, RaycastInfo& raycastInfo, - decimal distance = RAYCAST_INFINITY_DISTANCE); + bool raycast(const Ray& ray, RaycastInfo& raycastInfo); // -------------------- Friendship -------------------- // diff --git a/src/collision/ProxyShape.h b/src/collision/ProxyShape.h index 65eddaf9..8493b0d1 100644 --- a/src/collision/ProxyShape.h +++ b/src/collision/ProxyShape.h @@ -99,12 +99,8 @@ class ProxyShape { /// Return true if a point is inside the collision shape bool testPointInside(const Vector3& worldPoint); - /// Raycast method - bool raycast(const Ray& ray); - /// Raycast method with feedback information - bool raycast(const Ray& ray, RaycastInfo& raycastInfo, - decimal distance = RAYCAST_INFINITY_DISTANCE); + bool raycast(const Ray& ray, RaycastInfo& raycastInfo); // -------------------- Friendship -------------------- // @@ -169,14 +165,9 @@ inline decimal ProxyShape::getMargin() const { return mCollisionShape->getMargin(); } -// Raycast method -inline bool ProxyShape::raycast(const Ray& ray) { - return mCollisionShape->raycast(ray, this); -} - // Raycast method with feedback information -inline bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, decimal distance) { - return mCollisionShape->raycast(ray, raycastInfo, this, distance); +inline bool ProxyShape::raycast(const Ray& ray, RaycastInfo& raycastInfo) { + return mCollisionShape->raycast(ray, raycastInfo, this); } } diff --git a/src/collision/RaycastInfo.h b/src/collision/RaycastInfo.h index 9b90e4d3..fc08aaf4 100644 --- a/src/collision/RaycastInfo.h +++ b/src/collision/RaycastInfo.h @@ -63,8 +63,9 @@ struct RaycastInfo { /// Surface normal at hit point in world-space coordinates Vector3 worldNormal; - /// Distance from the ray origin to the hit point - decimal distance; + /// Fraction distance of the hit point between point1 and point2 of the ray + /// The hit point "p" is such that p = point1 + hitFraction * (point2 - point1) + decimal hitFraction; /// Pointer to the hit collision body CollisionBody* body; diff --git a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp index 77dd52e7..393830bf 100644 --- a/src/collision/narrowphase/GJK/GJKAlgorithm.cpp +++ b/src/collision/narrowphase/GJK/GJKAlgorithm.cpp @@ -397,8 +397,7 @@ bool GJKAlgorithm::testPointInside(const Vector3& localPoint, ProxyShape* collis // Ray casting algorithm agains a convex collision shape using the GJK Algorithm /// This method implements the GJK ray casting algorithm described by Gino Van Den Bergen in /// "Ray Casting against General Convex Objects with Application to Continuous Collision Detection". -bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastInfo& raycastInfo, - decimal maxDistance) { +bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastInfo& raycastInfo) { Vector3 suppA; // Current lower bound point on the ray (starting at ray's origin) Vector3 suppB; // Support point on the collision shape @@ -408,8 +407,13 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastIn // Convert the ray origin and direction into the local-space of the collision shape const Transform localToWorldTransform = collisionShape->getLocalToWorldTransform(); const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 rayDirection = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); + Vector3 point1 = worldToLocalTransform * ray.point1; + Vector3 point2 = worldToLocalTransform * ray.point2; + Vector3 rayDirection = point2 - point1; + + // If the points of the segment are two close, return no hit + if (rayDirection.lengthSquare() < machineEpsilonSquare) return false; + Vector3 w; // Create a simplex set @@ -417,7 +421,7 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastIn Vector3 n(decimal(0.0), decimal(0.0), decimal(0.0)); decimal lambda = decimal(0.0); - suppA = origin; // Current lower bound point on the ray (starting at ray's origin) + suppA = point1; // Current lower bound point on the ray (starting at ray's origin) suppB = collisionShape->getLocalSupportPointWithoutMargin(rayDirection); Vector3 v = suppA - suppB; decimal vDotW, vDotR; @@ -444,7 +448,7 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastIn // We have found a better lower bound for the hit point along the ray lambda = lambda - vDotW / vDotR; - suppA = origin + lambda * rayDirection; + suppA = point1 + lambda * rayDirection; w = suppA - suppB; n = v; } @@ -465,7 +469,7 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastIn } // If the current lower bound distance is larger than the maximum raycasting distance - if (lambda > maxDistance) return false; + if (lambda > ray.maxFraction) return false; nbIterations++; } @@ -478,8 +482,8 @@ bool GJKAlgorithm::raycast(const Ray& ray, ProxyShape* collisionShape, RaycastIn Vector3 pointB; simplex.computeClosestPointsOfAandB(pointA, pointB); - // A raycast hit has been found, we fill in the raycast info object - raycastInfo.distance = lambda; + // A raycast hit has been found, we fill in the raycast info + raycastInfo.hitFraction = lambda; raycastInfo.worldPoint = localToWorldTransform * pointB; raycastInfo.body = collisionShape->getBody(); raycastInfo.proxyShape = collisionShape; diff --git a/src/collision/narrowphase/GJK/GJKAlgorithm.h b/src/collision/narrowphase/GJK/GJKAlgorithm.h index 0c671d78..f511dd69 100644 --- a/src/collision/narrowphase/GJK/GJKAlgorithm.h +++ b/src/collision/narrowphase/GJK/GJKAlgorithm.h @@ -99,8 +99,7 @@ class GJKAlgorithm : public NarrowPhaseAlgorithm { bool testPointInside(const Vector3& localPoint, ProxyShape* collisionShape); /// Ray casting algorithm agains a convex collision shape using the GJK Algorithm - bool raycast(const Ray& ray, ProxyShape* collisionShape, RaycastInfo& raycastInfo, - decimal maxDistance); + bool raycast(const Ray& ray, ProxyShape* collisionShape, RaycastInfo& raycastInfo); }; } diff --git a/src/collision/shapes/BoxShape.cpp b/src/collision/shapes/BoxShape.cpp index d89af6b3..d99e3835 100644 --- a/src/collision/shapes/BoxShape.cpp +++ b/src/collision/shapes/BoxShape.cpp @@ -45,6 +45,7 @@ BoxShape::BoxShape(const BoxShape& shape) : CollisionShape(shape), mExtent(shape } + // Destructor BoxShape::~BoxShape() { @@ -62,61 +63,15 @@ void BoxShape::computeLocalInertiaTensor(Matrix3x3& tensor, decimal mass) const 0.0, 0.0, factor * (xSquare + ySquare)); } -// Raycast method -bool BoxShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 rayDirection = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - decimal tMin = decimal(0.0); - decimal tMax = DECIMAL_LARGEST; - - // For each of the three slabs - for (int i=0; i<3; i++) { - - // If ray is parallel to the slab - if (std::abs(rayDirection[i]) < MACHINE_EPSILON) { - - // If the ray's origin is not inside the slab, there is no hit - if (origin[i] > mExtent[i] || origin[i] < -mExtent[i]) return false; - } - else { - - // Compute the intersection of the ray with the near and far plane of the slab - decimal oneOverD = decimal(1.0) / rayDirection[i]; - decimal t1 = (-mExtent[i] - origin[i]) * oneOverD; - decimal t2 = (mExtent[i] - origin [i]) * oneOverD; - - // Swap t1 and t2 if need so that t1 is intersection with near plane and - // t2 with far plane - if (t1 > t2) std::swap(t1, t2); - - // If t1 is negative, the origin is inside the box and therefore, there is no hit - if (t1 < decimal(0.0)) return false; - - // Compute the intersection of the of slab intersection interval with previous slabs - tMin = std::max(tMin, t1); - tMax = std::min(tMax, t2); - - // If the slabs intersection is empty, there is no hit - if (tMin > tMax) return false; - } - } - - // A hit has been found - return true; -} - // Raycast method with feedback information -bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance) const { +bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 rayDirection = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - decimal tMin = decimal(0.0); + const Vector3 point1 = worldToLocalTransform * ray.point1; + const Vector3 point2 = worldToLocalTransform * ray.point2; + Vector3 rayDirection = point2 - point1; + decimal tMin = DECIMAL_SMALLEST; decimal tMax = DECIMAL_LARGEST; Vector3 normalDirection(decimal(0), decimal(0), decimal(0)); Vector3 currentNormal; @@ -128,14 +83,14 @@ bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pro if (std::abs(rayDirection[i]) < MACHINE_EPSILON) { // If the ray's origin is not inside the slab, there is no hit - if (origin[i] > mExtent[i] || origin[i] < -mExtent[i]) return false; + if (point1[i] > mExtent[i] || point1[i] < -mExtent[i]) return false; } else { // Compute the intersection of the ray with the near and far plane of the slab decimal oneOverD = decimal(1.0) / rayDirection[i]; - decimal t1 = (-mExtent[i] - origin[i]) * oneOverD; - decimal t2 = (mExtent[i] - origin [i]) * oneOverD; + decimal t1 = (-mExtent[i] - point1[i]) * oneOverD; + decimal t2 = (mExtent[i] - point1 [i]) * oneOverD; currentNormal = -mExtent; // Swap t1 and t2 if need so that t1 is intersection with near plane and @@ -145,9 +100,6 @@ bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pro currentNormal = -currentNormal; } - // If t1 is negative, the origin is inside the box and therefore, there is no hit - if (t1 < decimal(0.0)) return false; - // Compute the intersection of the of slab intersection interval with previous slabs if (t1 > tMin) { tMin = t1; @@ -155,20 +107,23 @@ bool BoxShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pro } tMax = std::min(tMax, t2); - // If tMin is larger than the maximum raycasting distance, we return no hit - if (tMin > distance) return false; + // If tMin is larger than the maximum raycasting fraction, we return no hit + if (tMin > ray.maxFraction) return false; // If the slabs intersection is empty, there is no hit if (tMin > tMax) return false; } } + // If tMin is negative, we return no hit + if (tMin < decimal(0.0)) return false; + // The ray intersects the three slabs, we compute the hit point - Vector3 localHitPoint = origin + tMin * rayDirection; + Vector3 localHitPoint = point1 + tMin * rayDirection; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = tMin; + raycastInfo.hitFraction = tMin; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; diff --git a/src/collision/shapes/BoxShape.h b/src/collision/shapes/BoxShape.h index ba9b9d4d..53d6e4bd 100644 --- a/src/collision/shapes/BoxShape.h +++ b/src/collision/shapes/BoxShape.h @@ -78,12 +78,8 @@ class BoxShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; public : diff --git a/src/collision/shapes/CapsuleShape.cpp b/src/collision/shapes/CapsuleShape.cpp index d4fa711a..976b8f3c 100644 --- a/src/collision/shapes/CapsuleShape.cpp +++ b/src/collision/shapes/CapsuleShape.cpp @@ -143,103 +143,37 @@ bool CapsuleShape::testPointInside(const Vector3& localPoint, ProxyShape* proxyS (xSquare + zSquare + diffYCenterSphere2 * diffYCenterSphere2) < squareRadius; } -// Raycast method -bool CapsuleShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - - // Transform the ray direction and origin in local-space coordinates - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 n = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - - const decimal epsilon = decimal(0.00001); - Vector3 p(decimal(0), -mHalfHeight, decimal(0)); - Vector3 q(decimal(0), mHalfHeight, decimal(0)); - Vector3 d = q - p; - Vector3 m = origin - p; - decimal t; - - decimal mDotD = m.dot(d); - decimal nDotD = n.dot(d); - decimal dDotD = d.dot(d); - decimal mDotN = m.dot(n); - - decimal a = dDotD - nDotD * nDotD; - decimal k = m.dot(m) - mRadius * mRadius; - decimal c = dDotD * k - mDotD * mDotD; - - // If the ray is parallel to the cylinder axis - if (std::abs(a) < epsilon) { - - // If the origin is outside the surface of the cylinder, we return no hit - if (c > decimal(0.0)) return false; - - // Here we know that the segment intersect an endcap of the cylinder - - // If the ray intersects with the "p" endcap of the capsule - if (mDotD < decimal(0.0)) { - - // Check intersection with the sphere "p" endcap of the capsule - return raycastWithSphereEndCap(origin, n, p); - } - else if (mDotD > dDotD) { // If the ray intersects with the "q" endcap of the cylinder - - // Check intersection with the sphere "q" endcap of the capsule - return raycastWithSphereEndCap(origin, n, q); - } - else { // If the origin is inside the cylinder, we return no hit - return false; - } - } - decimal b = dDotD * mDotN - nDotD * mDotD; - decimal discriminant = b * b - a * c; - - // If the discriminant is negative, no real roots and therfore, no hit - if (discriminant < decimal(0.0)) return false; - - // Compute the smallest root (first intersection along the ray) - decimal t0 = t = (-b - std::sqrt(discriminant)) / a; - - // If the intersection is outside the cylinder on "p" endcap side - decimal value = mDotD + t * nDotD; - if (value < decimal(0.0)) { - - // Check intersection with the sphere "p" endcap of the capsule - return raycastWithSphereEndCap(origin, n, p); - } - else if (value > dDotD) { // If the intersection is outside the cylinder on the "q" side - - // Check intersection with the sphere "q" endcap of the capsule - return raycastWithSphereEndCap(origin, n, q); - } - - // If the intersection is behind the origin of the ray, we return no hit - return (t0 >= decimal(0.0)); -} - // Raycast method with feedback information -bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance) const { +bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { // Transform the ray direction and origin in local-space coordinates const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 n = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); + const Vector3 point1 = worldToLocalTransform * ray.point1; + const Vector3 point2 = worldToLocalTransform * ray.point2; + const Vector3 n = point2 - point1; - const decimal epsilon = decimal(0.00001); + const decimal epsilon = decimal(0.01); Vector3 p(decimal(0), -mHalfHeight, decimal(0)); Vector3 q(decimal(0), mHalfHeight, decimal(0)); Vector3 d = q - p; - Vector3 m = origin - p; + Vector3 m = point1 - p; decimal t; decimal mDotD = m.dot(d); decimal nDotD = n.dot(d); decimal dDotD = d.dot(d); + + // Test if the segment is outside the cylinder + decimal vec1DotD = (point1 - Vector3(decimal(0.0), -mHalfHeight - mRadius, decimal(0.0))).dot(d); + if (vec1DotD < decimal(0.0) && vec1DotD + nDotD < decimal(0.0)) return false; + decimal ddotDExtraCaps = decimal(2.0) * mRadius * d.y; + if (vec1DotD > dDotD + ddotDExtraCaps && vec1DotD + nDotD > dDotD + ddotDExtraCaps) return false; + + decimal nDotN = n.dot(n); decimal mDotN = m.dot(n); - decimal a = dDotD - nDotD * nDotD; + decimal a = dDotD * nDotN - nDotD * nDotD; decimal k = m.dot(m) - mRadius * mRadius; decimal c = dDotD * k - mDotD * mDotD; @@ -256,11 +190,11 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* // Check intersection between the ray and the "p" sphere endcap of the capsule Vector3 hitLocalPoint; - decimal hitDistance; - if (raycastWithSphereEndCap(origin, n, p, distance, hitLocalPoint, hitDistance)) { + decimal hitFraction; + if (raycastWithSphereEndCap(point1, point2, p, ray.maxFraction, hitLocalPoint, hitFraction)) { raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = hitDistance; + raycastInfo.hitFraction = hitFraction; raycastInfo.worldPoint = localToWorldTransform * hitLocalPoint; Vector3 normalDirection = (hitLocalPoint - p).getUnit(); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -274,11 +208,11 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* // Check intersection between the ray and the "q" sphere endcap of the capsule Vector3 hitLocalPoint; - decimal hitDistance; - if (raycastWithSphereEndCap(origin, n, q, distance, hitLocalPoint, hitDistance)) { + decimal hitFraction; + if (raycastWithSphereEndCap(point1, point2, q, ray.maxFraction, hitLocalPoint, hitFraction)) { raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = hitDistance; + raycastInfo.hitFraction = hitFraction; raycastInfo.worldPoint = localToWorldTransform * hitLocalPoint; Vector3 normalDirection = (hitLocalPoint - q).getUnit(); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -307,11 +241,11 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* // Check intersection between the ray and the "p" sphere endcap of the capsule Vector3 hitLocalPoint; - decimal hitDistance; - if (raycastWithSphereEndCap(origin, n, p, distance, hitLocalPoint, hitDistance)) { + decimal hitFraction; + if (raycastWithSphereEndCap(point1, point2, p, ray.maxFraction, hitLocalPoint, hitFraction)) { raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = hitDistance; + raycastInfo.hitFraction = hitFraction; raycastInfo.worldPoint = localToWorldTransform * hitLocalPoint; Vector3 normalDirection = (hitLocalPoint - p).getUnit(); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -325,11 +259,11 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* // Check intersection between the ray and the "q" sphere endcap of the capsule Vector3 hitLocalPoint; - decimal hitDistance; - if (raycastWithSphereEndCap(origin, n, q, distance, hitLocalPoint, hitDistance)) { + decimal hitFraction; + if (raycastWithSphereEndCap(point1, point2, q, ray.maxFraction, hitLocalPoint, hitFraction)) { raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = hitDistance; + raycastInfo.hitFraction = hitFraction; raycastInfo.worldPoint = localToWorldTransform * hitLocalPoint; Vector3 normalDirection = (hitLocalPoint - q).getUnit(); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -344,13 +278,13 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = point1 + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 v = localHitPoint - p; Vector3 w = (v.dot(d) / d.lengthSquare()) * d; @@ -361,64 +295,46 @@ bool CapsuleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* } // Raycasting method between a ray one of the two spheres end cap of the capsule -bool CapsuleShape::raycastWithSphereEndCap(const Vector3& rayOrigin, const Vector3& rayDirection, - const Vector3& sphereCenter, decimal maxDistance, - Vector3& hitLocalPoint, decimal& hitDistance) const { +bool CapsuleShape::raycastWithSphereEndCap(const Vector3& point1, const Vector3& point2, + const Vector3& sphereCenter, decimal maxFraction, + Vector3& hitLocalPoint, decimal& hitFraction) const { - Vector3 m = rayOrigin - sphereCenter; + const Vector3 m = point1 - sphereCenter; decimal c = m.dot(m) - mRadius * mRadius; // If the origin of the ray is inside the sphere, we return no intersection if (c < decimal(0.0)) return false; + const Vector3 rayDirection = point2 - point1; decimal b = m.dot(rayDirection); // If the origin of the ray is outside the sphere and the ray - // is pointing away from the sphere and there is no intersection - if (c >= decimal(0.0) && b > decimal(0.0)) return false; + // is pointing away from the sphere, there is no intersection + if (b > decimal(0.0)) return false; + + decimal raySquareLength = rayDirection.lengthSquare(); // Compute the discriminant of the quadratic equation - decimal discriminant = b * b - c; + decimal discriminant = b * b - raySquareLength * c; - // If the discriminant is negative, there is no intersection - if (discriminant < decimal(0.0)) return false; + // If the discriminant is negative or the ray length is very small, there is no intersection + if (discriminant < decimal(0.0) || raySquareLength < MACHINE_EPSILON) return false; // Compute the solution "t" closest to the origin decimal t = -b - std::sqrt(discriminant); assert(t >= decimal(0.0)); - // If the intersection distance is larger than the allowed distance, return no intersection - if (t > maxDistance) return false; + // If the hit point is withing the segment ray fraction + if (t < maxFraction * raySquareLength) { - // Compute the hit point and distance - hitLocalPoint = rayOrigin + t * rayDirection; - hitDistance = t; + // Compute the intersection information + t /= raySquareLength; + hitFraction = t; + hitLocalPoint = point1 + t * rayDirection; - return true; -} - -// Raycasting method between a ray one of the two spheres end cap of the capsule -/// This method returns true if there is an intersection and false otherwise but does not -/// compute the intersection point. -bool CapsuleShape::raycastWithSphereEndCap(const Vector3& rayOrigin, const Vector3& rayDirection, - const Vector3& sphereCenter) const { - - Vector3 m = rayOrigin - sphereCenter; - decimal c = m.dot(m) - mRadius * mRadius; - - // If the origin of the ray is inside the sphere, we return no intersection - if (c < decimal(0.0)) return false; - - decimal b = m.dot(rayDirection); - - // If the origin of the ray is outside the sphere and the ray - // is pointing away from the sphere and there is no intersection - if (c >= decimal(0.0) && b > decimal(0.0)) return false; - - // Compute the discriminant of the quadratic equation - decimal discriminant = b * b - c; - - // If the discriminant is negative, there is no intersection - return (discriminant >= decimal(0.0)); + return true; + } + + return false; } diff --git a/src/collision/shapes/CapsuleShape.h b/src/collision/shapes/CapsuleShape.h index 15d3f101..f0591aaf 100644 --- a/src/collision/shapes/CapsuleShape.h +++ b/src/collision/shapes/CapsuleShape.h @@ -75,21 +75,13 @@ class CapsuleShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; /// Raycasting method between a ray one of the two spheres end cap of the capsule - bool raycastWithSphereEndCap(const Vector3& rayOrigin, const Vector3& rayDirection, - const Vector3& sphereCenter, decimal maxDistance, - Vector3& hitLocalPoint, decimal& hitDistance) const; - - // Raycasting method between a ray one of the two spheres end cap of the capsule - bool raycastWithSphereEndCap(const Vector3& rayOrigin, const Vector3& rayDirection, - const Vector3& sphereCenter) const; + bool raycastWithSphereEndCap(const Vector3& point1, const Vector3& point2, + const Vector3& sphereCenter, decimal maxFraction, + Vector3& hitLocalPoint, decimal& hitFraction) const; public : diff --git a/src/collision/shapes/CollisionShape.h b/src/collision/shapes/CollisionShape.h index 4e12bc3e..f8699f75 100644 --- a/src/collision/shapes/CollisionShape.h +++ b/src/collision/shapes/CollisionShape.h @@ -85,12 +85,8 @@ class CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& worldPoint, ProxyShape* proxyShape) const=0; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const=0; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const=0; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const=0; public : diff --git a/src/collision/shapes/ConeShape.cpp b/src/collision/shapes/ConeShape.cpp index d1cdb87b..89d67471 100644 --- a/src/collision/shapes/ConeShape.cpp +++ b/src/collision/shapes/ConeShape.cpp @@ -95,120 +95,18 @@ Vector3 ConeShape::getLocalSupportPointWithoutMargin(const Vector3& direction, return supportPoint; } -// Raycast method -// This implementation is based on the technique described by David Eberly in the article -// "Intersection of a Line and a Cone" that can be found at -// http://www.geometrictools.com/Documentation/IntersectionLineCone.pdf -bool ConeShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - - // Transform the ray direction and origin in local-space coordinates - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 r = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - - const decimal epsilon = decimal(0.00001); - Vector3 V(0, mHalfHeight, 0); - Vector3 centerBase(0, -mHalfHeight, 0); - Vector3 axis(0, decimal(-1.0), 0); - decimal heightSquare = decimal(4.0) * mHalfHeight * mHalfHeight; - decimal cosThetaSquare = heightSquare / (heightSquare + mRadius * mRadius); - decimal factor = decimal(1.0) - cosThetaSquare; - Vector3 delta = origin - V; - decimal c0 = -cosThetaSquare * delta.x * delta.x + factor * delta.y * delta.y - - cosThetaSquare * delta.z * delta.z; - decimal c1 = -cosThetaSquare * delta.x * r.x + factor * delta.y * r.y - cosThetaSquare * delta.z * r.z; - decimal c2 = -cosThetaSquare * r.x * r.x + factor * r.y * r.y - cosThetaSquare * r.z * r.z; - decimal tHit[] = {decimal(-1.0), decimal(-1.0), decimal(-1.0)}; - Vector3 localHitPoint[3]; - - // If c2 is different from zero - if (std::abs(c2) > MACHINE_EPSILON) { - decimal gamma = c1 * c1 - c0 * c2; - - // If there is no real roots in the quadratic equation - if (gamma < decimal(0.0)) { - return false; - } - else if (gamma > decimal(0.0)) { // The equation has two real roots - - // Compute two intersections - decimal sqrRoot = std::sqrt(gamma); - tHit[0] = (-c1 - sqrRoot) / c2; - tHit[1] = (-c1 + sqrRoot) / c2; - } - else { // If the equation has a single real root - - // Compute the intersection - tHit[0] = -c1 / c2; - } - } - else { // If c2 == 0 - - // If c2 = 0 and c1 != 0 - if (std::abs(c1) > MACHINE_EPSILON) { - tHit[0] = -c0 / (decimal(2.0) * c1); - } - else { // If c2 = c1 = 0 - - // If c0 is different from zero, no solution and if c0 = 0, we have a - // degenerate case, the whole ray is contained in the cone side - // but we return no hit in this case - return false; - } - } - - // If the origin of the ray is inside the cone, we return no hit - if (testPointInside(origin, NULL)) return false; - - localHitPoint[0] = origin + tHit[0] * r; - localHitPoint[1] = origin + tHit[1] * r; - - // Only keep hit points in one side of the double cone (the cone we are interested in) - if (axis.dot(localHitPoint[0] - V) < decimal(0.0)) { - tHit[0] = decimal(-1.0); - } - if (axis.dot(localHitPoint[1] - V) < decimal(0.0)) { - tHit[1] = decimal(-1.0); - } - - // Only keep hit points that are within the correct height of the cone - if (localHitPoint[0].y < decimal(-mHalfHeight)) { - tHit[0] = decimal(-1.0); - } - if (localHitPoint[1].y < decimal(-mHalfHeight)) { - tHit[1] = decimal(-1.0); - } - - if (tHit[0] >= decimal(0.0) || tHit[1] >= decimal(0.0)) return true; - - // If the ray is in direction of the base plane of the cone - if (r.y > epsilon) { - - // Compute the intersection with the base plane of the cone - tHit[2] = (-mHalfHeight + origin.y) / (-r.y); - - // Only keep this intersection if it is inside the cone radius - localHitPoint[2] = origin + tHit[2] * r; - - return ((localHitPoint[2] - centerBase).lengthSquare() <= mRadius * mRadius); - } - - return false; -} - // Raycast method with feedback information // This implementation is based on the technique described by David Eberly in the article // "Intersection of a Line and a Cone" that can be found at // http://www.geometrictools.com/Documentation/IntersectionLineCone.pdf -bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal maxDistance) const { +bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { // Transform the ray direction and origin in local-space coordinates const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 r = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); + const Vector3 point1 = worldToLocalTransform * ray.point1; + const Vector3 point2 = worldToLocalTransform * ray.point2; + const Vector3 r = point2 - point1; const decimal epsilon = decimal(0.00001); Vector3 V(0, mHalfHeight, 0); @@ -217,7 +115,7 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr decimal heightSquare = decimal(4.0) * mHalfHeight * mHalfHeight; decimal cosThetaSquare = heightSquare / (heightSquare + mRadius * mRadius); decimal factor = decimal(1.0) - cosThetaSquare; - Vector3 delta = origin - V; + Vector3 delta = point1 - V; decimal c0 = -cosThetaSquare * delta.x * delta.x + factor * delta.y * delta.y - cosThetaSquare * delta.z * delta.z; decimal c1 = -cosThetaSquare * delta.x * r.x + factor * delta.y * r.y - cosThetaSquare * delta.z * r.z; @@ -263,10 +161,10 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr } // If the origin of the ray is inside the cone, we return no hit - if (testPointInside(origin, NULL)) return false; + if (testPointInside(point1, NULL)) return false; - localHitPoint[0] = origin + tHit[0] * r; - localHitPoint[1] = origin + tHit[1] * r; + localHitPoint[0] = point1 + tHit[0] * r; + localHitPoint[1] = point1 + tHit[1] * r; // Only keep hit points in one side of the double cone (the cone we are interested in) if (axis.dot(localHitPoint[0] - V) < decimal(0.0)) { @@ -288,10 +186,10 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr if (r.y > epsilon) { // Compute the intersection with the base plane of the cone - tHit[2] = (-origin.y - mHalfHeight) / (r.y); + tHit[2] = (-point1.y - mHalfHeight) / (r.y); // Only keep this intersection if it is inside the cone radius - localHitPoint[2] = origin + tHit[2] * r; + localHitPoint[2] = point1 + tHit[2] * r; if ((localHitPoint[2] - centerBase).lengthSquare() > mRadius * mRadius) { tHit[2] = decimal(-1.0); @@ -313,7 +211,7 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr } if (hitIndex < 0) return false; - if (t > maxDistance) return false; + if (t > ray.maxFraction) return false; // Compute the normal direction for hit against side of the cone if (hitIndex != 2) { @@ -329,7 +227,7 @@ bool ConeShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* pr raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint[hitIndex]; raycastInfo.worldNormal = localToWorldTransform.getOrientation() * localNormal[hitIndex]; diff --git a/src/collision/shapes/ConeShape.h b/src/collision/shapes/ConeShape.h index 12fa498e..74cdc8e1 100644 --- a/src/collision/shapes/ConeShape.h +++ b/src/collision/shapes/ConeShape.h @@ -83,12 +83,8 @@ class ConeShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal maxDistance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; public : diff --git a/src/collision/shapes/ConvexMeshShape.cpp b/src/collision/shapes/ConvexMeshShape.cpp index c4f8f4db..b3567b4f 100644 --- a/src/collision/shapes/ConvexMeshShape.cpp +++ b/src/collision/shapes/ConvexMeshShape.cpp @@ -230,16 +230,8 @@ bool ConvexMeshShape::isEqualTo(const CollisionShape& otherCollisionShape) const return true; } -// Raycast method -bool ConvexMeshShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - RaycastInfo raycastInfo; - return proxyShape->mBody->mWorld.mCollisionDetection.mNarrowPhaseGJKAlgorithm.raycast( - ray, proxyShape, raycastInfo, RAYCAST_INFINITY_DISTANCE); -} - // Raycast method with feedback information -bool ConvexMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance) const { +bool ConvexMeshShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { return proxyShape->mBody->mWorld.mCollisionDetection.mNarrowPhaseGJKAlgorithm.raycast( - ray, proxyShape, raycastInfo, distance); + ray, proxyShape, raycastInfo); } diff --git a/src/collision/shapes/ConvexMeshShape.h b/src/collision/shapes/ConvexMeshShape.h index a2c09880..c0bcd27f 100644 --- a/src/collision/shapes/ConvexMeshShape.h +++ b/src/collision/shapes/ConvexMeshShape.h @@ -104,12 +104,8 @@ class ConvexMeshShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; public : diff --git a/src/collision/shapes/CylinderShape.cpp b/src/collision/shapes/CylinderShape.cpp index abaa04b2..60247516 100644 --- a/src/collision/shapes/CylinderShape.cpp +++ b/src/collision/shapes/CylinderShape.cpp @@ -88,122 +88,37 @@ Vector3 CylinderShape::getLocalSupportPointWithoutMargin(const Vector3& directio return supportPoint; } -// Raycast method -/// Algorithm based on the one described at page 194 in Real-ime Collision Detection by -/// Morgan Kaufmann. -bool CylinderShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - - // Transform the ray direction and origin in local-space coordinates - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 n = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - - const decimal epsilon = decimal(0.00001); - Vector3 p(decimal(0), -mHalfHeight, decimal(0)); - Vector3 q(decimal(0), mHalfHeight, decimal(0)); - Vector3 d = q - p; - Vector3 m = origin - p; - decimal t; - - decimal mDotD = m.dot(d); - decimal nDotD = n.dot(d); - decimal dDotD = d.dot(d); - decimal mDotN = m.dot(n); - - decimal a = dDotD - nDotD * nDotD; - decimal k = m.dot(m) - mRadius * mRadius; - decimal c = dDotD * k - mDotD * mDotD; - - // If the ray is parallel to the cylinder axis - if (std::abs(a) < epsilon) { - - // If the origin is outside the surface of the cylinder, we return no hit - if (c > decimal(0.0)) return false; - - // Here we know that the segment intersect an endcap of the cylinder - - // If the ray intersects with the "p" endcap of the cylinder - if (mDotD < decimal(0.0)) { - - t = -mDotN; - - return (t >= decimal(0.0)); - } - else if (mDotD > dDotD) { // If the ray intersects with the "q" endcap of the cylinder - - t = (nDotD - mDotN); - - return (t >= decimal(0.0)); - } - else { // If the origin is inside the cylinder, we return no hit - return false; - } - } - decimal b = dDotD * mDotN - nDotD * mDotD; - decimal discriminant = b * b - a * c; - - // If the discriminant is negative, no real roots and therfore, no hit - if (discriminant < decimal(0.0)) return false; - - // Compute the smallest root (first intersection along the ray) - decimal t0 = t = (-b - std::sqrt(discriminant)) / a; - - // If the intersection is outside the cylinder on "p" endcap side - decimal value = mDotD + t * nDotD; - if (value < decimal(0.0)) { - - // If the ray is pointing away from the "p" endcap, we return no hit - if (nDotD <= decimal(0.0)) return false; - - // Compute the intersection against the "p" endcap (intersection agains whole plane) - t = -mDotD / nDotD; - - // Keep the intersection if the it is inside the cylinder radius - return (t >= decimal(0.0) && k + t * (decimal(2.0) * mDotN + t) <= decimal(0.0)); - } - else if (value > dDotD) { // If the intersection is outside the cylinder on the "q" side - - // If the ray is pointing away from the "q" endcap, we return no hit - if (nDotD >= decimal(0.0)) return false; - - // Compute the intersection against the "q" endcap (intersection against whole plane) - t = (dDotD - mDotD) / nDotD; - - // Keep the intersection if it is inside the cylinder radius - return (t >= decimal(0.0) && k + dDotD - decimal(2.0) * mDotD + t * (decimal(2.0) * - (mDotN - nDotD) + t) <= decimal(0.0)); - } - - // If the intersection is behind the origin of the ray, we return no hit - return (t0 >= decimal(0.0)); -} - // Raycast method with feedback information /// Algorithm based on the one described at page 194 in Real-ime Collision Detection by /// Morgan Kaufmann. -bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance) const { +bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { // Transform the ray direction and origin in local-space coordinates const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - Vector3 n = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); + const Vector3 pointA = worldToLocalTransform * ray.point1; + const Vector3 pointB = worldToLocalTransform * ray.point2; + const Vector3 n = pointB - pointA; - const decimal epsilon = decimal(0.00001); + const decimal epsilon = decimal(0.01); Vector3 p(decimal(0), -mHalfHeight, decimal(0)); Vector3 q(decimal(0), mHalfHeight, decimal(0)); Vector3 d = q - p; - Vector3 m = origin - p; + Vector3 m = pointA - p; decimal t; decimal mDotD = m.dot(d); decimal nDotD = n.dot(d); decimal dDotD = d.dot(d); + + // Test if the segment is outside the cylinder + if (mDotD < decimal(0.0) && mDotD + nDotD < decimal(0.0)) return false; + if (mDotD > dDotD && mDotD + nDotD > dDotD) return false; + + decimal nDotN = n.dot(n); decimal mDotN = m.dot(n); - decimal a = dDotD - nDotD * nDotD; + decimal a = dDotD * nDotN - nDotD * nDotD; decimal k = m.dot(m) - mRadius * mRadius; decimal c = dDotD * k - mDotD * mDotD; @@ -218,17 +133,17 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape // If the ray intersects with the "p" endcap of the cylinder if (mDotD < decimal(0.0)) { - t = -mDotN; + t = -mDotN / nDotN; // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = pointA + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 normalDirection(0, decimal(-1), 0); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -237,17 +152,17 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape } else if (mDotD > dDotD) { // If the ray intersects with the "q" endcap of the cylinder - t = (nDotD - mDotN); + t = (nDotD - mDotN) / nDotN; // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = pointA + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 normalDirection(0, decimal(1.0), 0); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -282,13 +197,13 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = pointA + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 normalDirection(0, decimal(-1.0), 0); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -309,13 +224,13 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = pointA + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 normalDirection(0, decimal(1.0), 0); raycastInfo.worldNormal = localToWorldTransform.getOrientation() * normalDirection; @@ -327,13 +242,13 @@ bool CylinderShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape // If the intersection is behind the origin of the ray or beyond the maximum // raycasting distance, we return no hit - if (t < decimal(0.0) || t > distance) return false; + if (t < decimal(0.0) || t > ray.maxFraction) return false; // Compute the hit information - Vector3 localHitPoint = origin + t * n; + Vector3 localHitPoint = pointA + t * n; raycastInfo.body = proxyShape->getBody(); raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; + raycastInfo.hitFraction = t; raycastInfo.worldPoint = localToWorldTransform * localHitPoint; Vector3 v = localHitPoint - p; Vector3 w = (v.dot(d) / d.lengthSquare()) * d; diff --git a/src/collision/shapes/CylinderShape.h b/src/collision/shapes/CylinderShape.h index d1c7a8f5..878278ea 100644 --- a/src/collision/shapes/CylinderShape.h +++ b/src/collision/shapes/CylinderShape.h @@ -80,12 +80,8 @@ class CylinderShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; public : diff --git a/src/collision/shapes/SphereShape.cpp b/src/collision/shapes/SphereShape.cpp index b5c9b694..4c38fae5 100644 --- a/src/collision/shapes/SphereShape.cpp +++ b/src/collision/shapes/SphereShape.cpp @@ -47,72 +47,51 @@ SphereShape::~SphereShape() { } -// Raycast method -bool SphereShape::raycast(const Ray& ray, ProxyShape* proxyShape) const { - - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - decimal c = origin.dot(origin) - mRadius * mRadius; - - // If the origin of the ray is inside the sphere, we return no intersection - if (c < decimal(0.0)) return false; - - Vector3 rayDirection = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - decimal b = origin.dot(rayDirection); - - // If the origin of the ray is outside the sphere and the ray - // is pointing away from the sphere and there is no intersection - if (c >= decimal(0.0) && b > decimal(0.0)) return false; - - // Compute the discriminant of the quadratic equation - decimal discriminant = b*b - c; - - // If the discriminant is negative, there is no intersection - return (discriminant >= decimal(0.0)); -} - // Raycast method with feedback information -bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance) const { +bool SphereShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const { - const Transform localToWorldTransform = proxyShape->getLocalToWorldTransform(); - const Transform worldToLocalTransform = localToWorldTransform.getInverse(); - Vector3 origin = worldToLocalTransform * ray.origin; - decimal c = origin.dot(origin) - mRadius * mRadius; + // We perform the intersection test in world-space + + const Vector3 sphereCenter = proxyShape->getLocalToWorldTransform().getPosition(); + const Vector3 m = ray.point1 - sphereCenter; + decimal c = m.dot(m) - mRadius * mRadius; // If the origin of the ray is inside the sphere, we return no intersection if (c < decimal(0.0)) return false; - Vector3 rayDirection = worldToLocalTransform.getOrientation() * ray.direction.getUnit(); - decimal b = origin.dot(rayDirection); + const Vector3 rayDirection = ray.point2 - ray.point1; + decimal b = m.dot(rayDirection); // If the origin of the ray is outside the sphere and the ray - // is pointing away from the sphere and there is no intersection - if (c >= decimal(0.0) && b > decimal(0.0)) return false; + // is pointing away from the sphere, there is no intersection + if (b > decimal(0.0)) return false; + + decimal raySquareLength = rayDirection.lengthSquare(); // Compute the discriminant of the quadratic equation - decimal discriminant = b*b - c; + decimal discriminant = b * b - raySquareLength * c; - // If the discriminant is negative, there is no intersection - if (discriminant < decimal(0.0)) return false; + // If the discriminant is negative or the ray length is very small, there is no intersection + if (discriminant < decimal(0.0) || raySquareLength < MACHINE_EPSILON) return false; // Compute the solution "t" closest to the origin decimal t = -b - std::sqrt(discriminant); assert(t >= decimal(0.0)); - // If the intersection distance is larger than the allowed distance, return no intersection - if (t > distance) return false; + // If the hit point is withing the segment ray fraction + if (t < ray.maxFraction * raySquareLength) { - // Compute the intersection information - Vector3 localPoint = origin + t * rayDirection; - raycastInfo.body = proxyShape->getBody(); - raycastInfo.proxyShape = proxyShape; - raycastInfo.distance = t; - raycastInfo.worldPoint = localToWorldTransform * localPoint; - raycastInfo.worldNormal = (raycastInfo.worldPoint - - localToWorldTransform.getPosition()).getUnit(); + // Compute the intersection information + t /= raySquareLength; + raycastInfo.body = proxyShape->getBody(); + raycastInfo.proxyShape = proxyShape; + raycastInfo.hitFraction = t; + raycastInfo.worldPoint = ray.point1 + t * rayDirection; + raycastInfo.worldNormal = (raycastInfo.worldPoint - sphereCenter).getUnit(); - return true; + return true; + } + + return false; } diff --git a/src/collision/shapes/SphereShape.h b/src/collision/shapes/SphereShape.h index bf3a7a11..c9ee75e9 100644 --- a/src/collision/shapes/SphereShape.h +++ b/src/collision/shapes/SphereShape.h @@ -70,12 +70,8 @@ class SphereShape : public CollisionShape { /// Return true if a point is inside the collision shape virtual bool testPointInside(const Vector3& localPoint, ProxyShape* proxyShape) const; - /// Raycast method - virtual bool raycast(const Ray& ray, ProxyShape* proxyShape) const; - /// Raycast method with feedback information - virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape, - decimal distance = RAYCAST_INFINITY_DISTANCE) const; + virtual bool raycast(const Ray& ray, RaycastInfo& raycastInfo, ProxyShape* proxyShape) const; public : diff --git a/src/configuration.h b/src/configuration.h index 7fd95554..5a024e9c 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -131,9 +131,6 @@ const decimal DYNAMIC_TREE_AABB_GAP = decimal(0.1); /// followin constant with the linear velocity and the elapsed time between two frames. const decimal DYNAMIC_TREE_AABB_LIN_GAP_MULTIPLIER = decimal(1.7); -/// Raycasting infinity distance constant -const decimal RAYCAST_INFINITY_DISTANCE = std::numeric_limits::infinity(); - } #endif diff --git a/src/engine/CollisionWorld.cpp b/src/engine/CollisionWorld.cpp index bf0ea54e..1d687745 100644 --- a/src/engine/CollisionWorld.cpp +++ b/src/engine/CollisionWorld.cpp @@ -166,14 +166,8 @@ void CollisionWorld::removeCollisionShape(CollisionShape* collisionShape) { } } -/// Raycast method -bool CollisionWorld::raycast(const Ray& ray, decimal distance) { - // TODO : Implement this method - return false; -} - /// Raycast method with feedback information -bool CollisionWorld::raycast(const Ray& ray, RaycastInfo& raycastInfo, decimal distance) { +bool CollisionWorld::raycast(const Ray& ray, RaycastInfo& raycastInfo) { // TODO : Implement this method return false; } diff --git a/src/engine/CollisionWorld.h b/src/engine/CollisionWorld.h index 52ae8b01..59cf6bae 100644 --- a/src/engine/CollisionWorld.h +++ b/src/engine/CollisionWorld.h @@ -120,12 +120,8 @@ class CollisionWorld { /// Destroy a collision body void destroyCollisionBody(CollisionBody* collisionBody); - /// Raycast method - bool raycast(const Ray& ray, decimal distance = RAYCAST_INFINITY_DISTANCE); - /// Raycast method with feedback information - bool raycast(const Ray& ray, RaycastInfo& raycastInfo, - decimal distance = RAYCAST_INFINITY_DISTANCE); + bool raycast(const Ray& ray, RaycastInfo& raycastInfo); // -------------------- Friendship -------------------- // diff --git a/src/mathematics/Ray.h b/src/mathematics/Ray.h index a5a61298..95c51c9e 100644 --- a/src/mathematics/Ray.h +++ b/src/mathematics/Ray.h @@ -34,7 +34,9 @@ namespace reactphysics3d { // Class Ray /** - * This structure represents a 3D ray with a origin point and a direction. + * This structure represents a 3D ray represented by two points. + * The ray goes from point1 to point1 + maxFraction * (point2 - point1). + * The points are specified in world-space coordinates. */ struct Ray { @@ -42,22 +44,25 @@ struct Ray { // -------------------- Attributes -------------------- // - /// Origin point of the ray - Vector3 origin; + /// First point of the ray (origin) + Vector3 point1; - /// Direction vector of the ray - Vector3 direction; + /// Second point of the ray + Vector3 point2; + + /// Maximum fraction value + decimal maxFraction; // -------------------- Methods -------------------- // /// Constructor with arguments - Ray(const Vector3& originPoint, const Vector3& directionVector) - : origin(originPoint), direction(directionVector) { + Ray(const Vector3& p1, const Vector3& p2, decimal maxFrac = decimal(1.0)) + : point1(p1), point2(p2), maxFraction(maxFrac) { } /// Copy-constructor - Ray(const Ray& ray) : origin(ray.origin), direction(ray.direction) { + Ray(const Ray& ray) : point1(ray.point1), point2(ray.point2), maxFraction(ray.maxFraction) { } @@ -69,8 +74,9 @@ struct Ray { /// Overloaded assignment operator Ray& operator=(const Ray& ray) { if (&ray != this) { - origin = ray.origin; - direction = ray.direction; + point1 = ray.point1; + point2 = ray.point2; + maxFraction = ray.maxFraction; } return *this; } diff --git a/src/mathematics/mathematics.h b/src/mathematics/mathematics.h index 66676dd6..8f277c07 100644 --- a/src/mathematics/mathematics.h +++ b/src/mathematics/mathematics.h @@ -33,6 +33,7 @@ #include "Vector3.h" #include "Vector2.h" #include "Transform.h" +#include "Ray.h" #include "configuration.h" #include "mathematics_functions.h" #include diff --git a/src/reactphysics3d.h b/src/reactphysics3d.h index 4724eab0..a49d5d14 100644 --- a/src/reactphysics3d.h +++ b/src/reactphysics3d.h @@ -51,6 +51,8 @@ #include "collision/shapes/CapsuleShape.h" #include "collision/shapes/ConvexMeshShape.h" #include "collision/shapes/AABB.h" +#include "collision/ProxyShape.h" +#include "collision/RaycastInfo.h" #include "constraint/BallAndSocketJoint.h" #include "constraint/SliderJoint.h" #include "constraint/HingeJoint.h" diff --git a/test/tests/collision/TestRaycast.h b/test/tests/collision/TestRaycast.h index 80e45a26..e5495ac3 100644 --- a/test/tests/collision/TestRaycast.h +++ b/test/tests/collision/TestRaycast.h @@ -88,7 +88,7 @@ class TestRaycast : public Test { /// Constructor TestRaycast(const std::string& name) : Test(name) { - epsilon = 0.0001; + epsilon = decimal(0.0001); // Create the world mWorld = new CollisionWorld(); @@ -194,10 +194,9 @@ class TestRaycast : public Test { void testBox() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(1 , 2, 10); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(0, 0, -5); - Ray ray(origin, direction); + Vector3 point1 = mLocalShapeToWorld * Vector3(1 , 2, 10); + Vector3 point2 = mLocalShapeToWorld * Vector3(1, 2, -20); + Ray ray(point1, point2); Vector3 hitPoint = mLocalShapeToWorld * Vector3(1, 2, 4); // CollisionWorld::raycast() @@ -205,7 +204,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mBoxBody); test(raycastInfo.proxyShape == mBoxShape); - test(approxEqual(raycastInfo.distance, 6, epsilon)); + test(approxEqual(raycastInfo.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z, epsilon)); @@ -215,7 +214,7 @@ class TestRaycast : public Test { test(mBoxBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mBoxBody); test(raycastInfo2.proxyShape == mBoxShape); - test(approxEqual(raycastInfo2.distance, 6, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -225,156 +224,108 @@ class TestRaycast : public Test { test(mBoxShape->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mBoxBody); test(raycastInfo3.proxyShape == mBoxShape); - test(approxEqual(raycastInfo3.distance, 6, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 3), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(3, 1, -5), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-3, 0, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(3, 1, 2), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(17, 29, 28)); + Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 3), mLocalShapeToWorld * Vector3(-11, 2, 24)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(22, 28, 31)); + Ray ray5(mLocalShapeToWorld * Vector3(3, 1, -5), mLocalShapeToWorld * Vector3(-30, 1, -5)); + Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalShapeToWorld * Vector3(4, -20, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalShapeToWorld * Vector3(1, -4, -20)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalShapeToWorld * Vector3(20, 4, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalShapeToWorld * Vector3(0, 50, -7)); + Ray ray10(mLocalShapeToWorld * Vector3(-3, 0, -6), mLocalShapeToWorld * Vector3(-3, 0, 20)); + Ray ray11(mLocalShapeToWorld * Vector3(3, 1, 2), mLocalShapeToWorld * Vector3(-20, 1, 2)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalShapeToWorld * Vector3(1, -20, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalShapeToWorld * Vector3(-1, 2, -20)); + Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalShapeToWorld * Vector3(20, 2, -2)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalShapeToWorld * Vector3(0, 20, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -5), mLocalShapeToWorld * Vector3(-1, 2, 20)); // ----- Test raycast miss ----- // test(!mBoxBody->raycast(ray1, raycastInfo3)); test(!mBoxShape->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mBoxBody->raycast(ray1)); - test(!mBoxShape->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mBoxBody->raycast(ray2, raycastInfo3)); test(!mBoxShape->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mBoxBody->raycast(ray2)); - test(!mBoxShape->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mBoxBody->raycast(ray3, raycastInfo3)); test(!mBoxShape->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mBoxBody->raycast(ray3)); - test(!mBoxShape->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mBoxBody->raycast(ray4, raycastInfo3)); test(!mBoxShape->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mBoxBody->raycast(ray4)); - test(!mBoxShape->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mBoxBody->raycast(ray5, raycastInfo3)); test(!mBoxShape->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mBoxBody->raycast(ray5)); - test(!mBoxShape->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mBoxBody->raycast(ray6, raycastInfo3)); test(!mBoxShape->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mBoxBody->raycast(ray6)); - test(!mBoxShape->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mBoxBody->raycast(ray7, raycastInfo3)); test(!mBoxShape->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mBoxBody->raycast(ray7)); - test(!mBoxShape->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mBoxBody->raycast(ray8, raycastInfo3)); test(!mBoxShape->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mBoxBody->raycast(ray8)); - test(!mBoxShape->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mBoxBody->raycast(ray9, raycastInfo3)); test(!mBoxShape->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mBoxBody->raycast(ray9)); - test(!mBoxShape->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mBoxBody->raycast(ray10, raycastInfo3)); test(!mBoxShape->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mBoxBody->raycast(ray10)); - test(!mBoxShape->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mBoxBody->raycast(ray11, raycastInfo3)); test(mBoxShape->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mBoxBody->raycast(ray11)); - test(mBoxShape->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo3)); test(mBoxBody->raycast(ray12, raycastInfo3)); test(mBoxShape->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mBoxBody->raycast(ray12)); - test(mBoxShape->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mBoxBody->raycast(ray13, raycastInfo3)); test(mBoxShape->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mBoxBody->raycast(ray13)); - test(mBoxShape->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mBoxBody->raycast(ray14, raycastInfo3)); test(mBoxShape->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mBoxBody->raycast(ray14)); - test(mBoxShape->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mBoxBody->raycast(ray15, raycastInfo3)); test(mBoxShape->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mBoxBody->raycast(ray15)); - test(mBoxShape->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mBoxBody->raycast(ray16, raycastInfo3)); test(mBoxShape->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mBoxBody->raycast(ray16)); - test(mBoxShape->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the ProxySphereShape::raycast(), CollisionBody::raycast() and @@ -382,10 +333,9 @@ class TestRaycast : public Test { void testSphere() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(-8 , 0, 0); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(5, 0, 0); - Ray ray(origin, direction); + Vector3 point1 = mLocalShapeToWorld * Vector3(-5 , 0, 0); + Vector3 point2 = mLocalShapeToWorld * Vector3(5, 0, 0); + Ray ray(point1, point2); Vector3 hitPoint = mLocalShapeToWorld * Vector3(-3, 0, 0); // CollisionWorld::raycast() @@ -393,7 +343,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mSphereBody); test(raycastInfo.proxyShape == mSphereShape); - test(approxEqual(raycastInfo.distance, 5, epsilon)); + test(approxEqual(raycastInfo.hitFraction, 0.2, epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z, epsilon)); @@ -403,7 +353,7 @@ class TestRaycast : public Test { test(mSphereBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mSphereBody); test(raycastInfo2.proxyShape == mSphereShape); - test(approxEqual(raycastInfo2.distance, 5, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, 0.2, epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -413,156 +363,108 @@ class TestRaycast : public Test { test(mSphereShape->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mSphereBody); test(raycastInfo3.proxyShape == mSphereShape); - test(approxEqual(raycastInfo3.distance, 5, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, 0.2, epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 2), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -4), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 2), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-5, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -11), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(4, 6, 7)); + Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 2), mLocalShapeToWorld * Vector3(-4, 0, 7)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(4, 6, 7)); + Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalShapeToWorld * Vector3(-30, 1, -5)); + Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalShapeToWorld * Vector3(4, -30, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalShapeToWorld * Vector3(1, -4, -30)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalShapeToWorld * Vector3(30, 4, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -4), mLocalShapeToWorld * Vector3(0, 30, -4)); + Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalShapeToWorld * Vector3(-4, 0, 30)); + Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 2), mLocalShapeToWorld * Vector3(-30, 1, 2)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalShapeToWorld * Vector3(1, -30, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalShapeToWorld * Vector3(-1, 2, -30)); + Ray ray14(mLocalShapeToWorld * Vector3(-5, 2, -2), mLocalShapeToWorld * Vector3(30, 2, -2)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -11), mLocalShapeToWorld * Vector3(-1, 2, 30)); // ----- Test raycast miss ----- // test(!mSphereBody->raycast(ray1, raycastInfo3)); test(!mSphereShape->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mSphereBody->raycast(ray1)); - test(!mSphereShape->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mSphereBody->raycast(ray2, raycastInfo3)); test(!mSphereShape->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mSphereBody->raycast(ray2)); - test(!mSphereShape->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mSphereBody->raycast(ray3, raycastInfo3)); test(!mSphereShape->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mSphereBody->raycast(ray3)); - test(!mSphereShape->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mSphereBody->raycast(ray4, raycastInfo3)); test(!mSphereShape->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mSphereBody->raycast(ray4)); - test(!mSphereShape->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mSphereBody->raycast(ray5, raycastInfo3)); test(!mSphereShape->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mSphereBody->raycast(ray5)); - test(!mSphereShape->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mSphereBody->raycast(ray6, raycastInfo3)); test(!mSphereShape->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mSphereBody->raycast(ray6)); - test(!mSphereShape->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mSphereBody->raycast(ray7, raycastInfo3)); test(!mSphereShape->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mSphereBody->raycast(ray7)); - test(!mSphereShape->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mSphereBody->raycast(ray8, raycastInfo3)); test(!mSphereShape->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mSphereBody->raycast(ray8)); - test(!mSphereShape->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mSphereBody->raycast(ray9, raycastInfo3)); test(!mSphereShape->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mSphereBody->raycast(ray9)); - test(!mSphereShape->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mSphereBody->raycast(ray10, raycastInfo3)); test(!mSphereShape->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mSphereBody->raycast(ray10)); - test(!mSphereShape->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mSphereBody->raycast(ray11, raycastInfo3)); test(mSphereShape->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mSphereBody->raycast(ray11)); - test(mSphereShape->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo3)); test(mSphereBody->raycast(ray12, raycastInfo3)); test(mSphereShape->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mSphereBody->raycast(ray12)); - test(mSphereShape->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mSphereBody->raycast(ray13, raycastInfo3)); test(mSphereShape->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mSphereBody->raycast(ray13)); - test(mSphereShape->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mSphereBody->raycast(ray14, raycastInfo3)); test(mSphereShape->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mSphereBody->raycast(ray14)); - test(mSphereShape->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mSphereBody->raycast(ray15, raycastInfo3)); test(mSphereShape->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mSphereBody->raycast(ray15)); - test(mSphereShape->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mSphereBody->raycast(ray16, raycastInfo3)); test(mSphereShape->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mSphereBody->raycast(ray16)); - test(mSphereShape->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the ProxyCapsuleShape::raycast(), CollisionBody::raycast() and @@ -570,20 +472,19 @@ class TestRaycast : public Test { void testCapsule() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(6 , 1, 0); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(-2, 0, 0); - Ray ray(origin, direction); + Vector3 point1A = mLocalShapeToWorld * Vector3(4 , 1, 0); + Vector3 point1B = mLocalShapeToWorld * Vector3(-6, 1, 0); + Ray ray(point1A, point1B); Vector3 hitPoint = mLocalShapeToWorld * Vector3(2, 1, 0); - Vector3 origin2 = mLocalShapeToWorld * Vector3(0 , 10, 0); - Vector3 direction2 = mLocalToWorldMatrix * Vector3(0, -3, 0); - Ray rayTop(origin2, direction2); + Vector3 point2A = mLocalShapeToWorld * Vector3(0 , 6.5, 0); + Vector3 point2B = mLocalShapeToWorld * Vector3(0, -3.5, 0); + Ray rayTop(point2A, point2B); Vector3 hitPointTop = mLocalShapeToWorld * Vector3(0, decimal(4.5), 0); - Vector3 origin3 = mLocalShapeToWorld * Vector3(0 , -10, 0); - Vector3 direction3 = mLocalToWorldMatrix * Vector3(0, 3, 0); - Ray rayBottom(origin3, direction3); + Vector3 point3A = mLocalShapeToWorld * Vector3(0 , -6.5, 0); + Vector3 point3B = mLocalShapeToWorld * Vector3(0, 3.5, 0); + Ray rayBottom(point3A, point3B); Vector3 hitPointBottom = mLocalShapeToWorld * Vector3(0, decimal(-4.5), 0); // CollisionWorld::raycast() @@ -591,7 +492,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mCapsuleBody); test(raycastInfo.proxyShape == mCapsuleShape); - test(approxEqual(raycastInfo.distance, 4, epsilon)); + test(approxEqual(raycastInfo.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z, epsilon)); @@ -601,7 +502,7 @@ class TestRaycast : public Test { test(mCapsuleBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mCapsuleBody); test(raycastInfo2.proxyShape == mCapsuleShape); - test(approxEqual(raycastInfo2.distance, 4, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -611,7 +512,7 @@ class TestRaycast : public Test { test(mCapsuleShape->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mCapsuleBody); test(raycastInfo3.proxyShape == mCapsuleShape); - test(approxEqual(raycastInfo3.distance, 4, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); @@ -620,7 +521,7 @@ class TestRaycast : public Test { test(mCapsuleShape->raycast(rayTop, raycastInfo4)); test(raycastInfo4.body == mCapsuleBody); test(raycastInfo4.proxyShape == mCapsuleShape); - test(approxEqual(raycastInfo4.distance, decimal(5.5), epsilon)); + test(approxEqual(raycastInfo4.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo4.worldPoint.x, hitPointTop.x, epsilon)); test(approxEqual(raycastInfo4.worldPoint.y, hitPointTop.y, epsilon)); test(approxEqual(raycastInfo4.worldPoint.z, hitPointTop.z, epsilon)); @@ -630,154 +531,108 @@ class TestRaycast : public Test { test(mCapsuleShape->raycast(rayBottom, raycastInfo5)); test(raycastInfo5.body == mCapsuleBody); test(raycastInfo5.proxyShape == mCapsuleShape); - test(approxEqual(raycastInfo5.distance, decimal(5.5), epsilon)); + test(approxEqual(raycastInfo5.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo5.worldPoint.x, hitPointBottom.x, epsilon)); test(approxEqual(raycastInfo5.worldPoint.y, hitPointBottom.y, epsilon)); test(approxEqual(raycastInfo5.worldPoint.z, hitPointBottom.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(1, 3, -1), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(4, 9, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -9, 5), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 9, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -9, -4), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 1.5), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 9, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(9, 17, 14)); + Ray ray3(mLocalShapeToWorld * Vector3(1, 3, -1), mLocalShapeToWorld * Vector3(-3, 3, 6)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(14, 16, 17)); + Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalShapeToWorld * Vector3(1, 1, -5)); + Ray ray6(mLocalShapeToWorld * Vector3(4, 9, 1), mLocalShapeToWorld * Vector3(4, 7, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -9, 5), mLocalShapeToWorld * Vector3(1, -9, 3)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 9, 0), mLocalShapeToWorld * Vector3(-3, 9, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -9, -4), mLocalShapeToWorld * Vector3(0, -4, -4)); + Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalShapeToWorld * Vector3(-4, 0, 2)); + Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 1.5), mLocalShapeToWorld * Vector3(-30, 1, 1.5)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 9, -1), mLocalShapeToWorld * Vector3(1, -30, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalShapeToWorld * Vector3(-1, 2, -30)); + Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalShapeToWorld * Vector3(30, 2, -2)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalShapeToWorld * Vector3(-1, 2, 30)); // ----- Test raycast miss ----- // test(!mCapsuleBody->raycast(ray1, raycastInfo3)); test(!mCapsuleShape->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mCapsuleBody->raycast(ray1)); - test(!mCapsuleShape->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mCapsuleBody->raycast(ray2, raycastInfo3)); test(!mCapsuleShape->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mCapsuleBody->raycast(ray2)); - test(!mCapsuleShape->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mCapsuleBody->raycast(ray3, raycastInfo3)); test(!mCapsuleShape->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mCapsuleBody->raycast(ray3)); - test(!mCapsuleShape->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mCapsuleBody->raycast(ray4, raycastInfo3)); test(!mCapsuleShape->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mCapsuleBody->raycast(ray4)); - test(!mCapsuleShape->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mCapsuleBody->raycast(ray5, raycastInfo3)); test(!mCapsuleShape->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mCapsuleBody->raycast(ray5)); - test(!mCapsuleShape->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mCapsuleBody->raycast(ray6, raycastInfo3)); test(!mCapsuleShape->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mCapsuleBody->raycast(ray6)); - test(!mCapsuleShape->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mCapsuleBody->raycast(ray7, raycastInfo3)); test(!mCapsuleShape->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mCapsuleBody->raycast(ray7)); - test(!mCapsuleShape->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mCapsuleBody->raycast(ray8, raycastInfo3)); test(!mCapsuleShape->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mCapsuleBody->raycast(ray8)); - test(!mCapsuleShape->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mCapsuleBody->raycast(ray9, raycastInfo3)); test(!mCapsuleShape->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mCapsuleBody->raycast(ray9)); - test(!mCapsuleShape->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mCapsuleBody->raycast(ray10, raycastInfo3)); test(!mCapsuleShape->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mCapsuleBody->raycast(ray10)); - test(!mCapsuleShape->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mCapsuleBody->raycast(ray11, raycastInfo3)); test(mCapsuleShape->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mCapsuleBody->raycast(ray11)); - test(mCapsuleShape->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo3)); test(mCapsuleBody->raycast(ray12, raycastInfo3)); test(mCapsuleShape->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mCapsuleBody->raycast(ray12)); - test(mCapsuleShape->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mCapsuleBody->raycast(ray13, raycastInfo3)); test(mCapsuleShape->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mCapsuleBody->raycast(ray13)); - test(mCapsuleShape->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mCapsuleBody->raycast(ray14, raycastInfo3)); test(mCapsuleShape->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mCapsuleBody->raycast(ray14)); - test(mCapsuleShape->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mCapsuleBody->raycast(ray15, raycastInfo3)); test(mCapsuleShape->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mCapsuleBody->raycast(ray15)); - test(mCapsuleShape->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mCapsuleBody->raycast(ray16, raycastInfo3)); test(mCapsuleShape->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the ProxyConeShape::raycast(), CollisionBody::raycast() and @@ -785,15 +640,14 @@ class TestRaycast : public Test { void testCone() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(0 , 0, 3); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(0, 0, -8); - Ray ray(origin, direction); + Vector3 point1A = mLocalShapeToWorld * Vector3(0 , 0, 3); + Vector3 point1B = mLocalShapeToWorld * Vector3(0, 0, -7); + Ray ray(point1A, point1B); Vector3 hitPoint = mLocalShapeToWorld * Vector3(0, 0, 1); - Vector3 origin2 = mLocalShapeToWorld * Vector3(1 , -5, 0); - Vector3 direction2 = mLocalToWorldMatrix * Vector3(0, 3, 0); - Ray rayBottom(origin2, direction2); + Vector3 point2A = mLocalShapeToWorld * Vector3(1 , -5, 0); + Vector3 point2B = mLocalShapeToWorld * Vector3(1, 5, 0); + Ray rayBottom(point2A, point2B); Vector3 hitPoint2 = mLocalShapeToWorld * Vector3(1, -3, 0); // CollisionWorld::raycast() @@ -801,7 +655,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mConeBody); test(raycastInfo.proxyShape == mConeShape); - test(approxEqual(raycastInfo.distance, 2, epsilon)); + test(approxEqual(raycastInfo.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z)); @@ -811,7 +665,7 @@ class TestRaycast : public Test { test(mConeBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mConeBody); test(raycastInfo2.proxyShape == mConeShape); - test(approxEqual(raycastInfo2.distance, 2, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -821,7 +675,7 @@ class TestRaycast : public Test { test(mConeShape->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mConeBody); test(raycastInfo3.proxyShape == mConeShape); - test(approxEqual(raycastInfo3.distance, 2, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); @@ -830,7 +684,7 @@ class TestRaycast : public Test { test(mWorld->raycast(rayBottom, raycastInfo4)); test(raycastInfo4.body == mConeBody); test(raycastInfo4.proxyShape == mConeShape); - test(approxEqual(raycastInfo4.distance, 2, epsilon)); + test(approxEqual(raycastInfo4.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo4.worldPoint.x, hitPoint2.x)); test(approxEqual(raycastInfo4.worldPoint.y, hitPoint2.y)); test(approxEqual(raycastInfo4.worldPoint.z, hitPoint2.z)); @@ -840,7 +694,7 @@ class TestRaycast : public Test { test(mConeBody->raycast(rayBottom, raycastInfo5)); test(raycastInfo5.body == mConeBody); test(raycastInfo5.proxyShape == mConeShape); - test(approxEqual(raycastInfo5.distance, 2, epsilon)); + test(approxEqual(raycastInfo5.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo5.worldPoint.x, hitPoint2.x, epsilon)); test(approxEqual(raycastInfo5.worldPoint.y, hitPoint2.y, epsilon)); test(approxEqual(raycastInfo5.worldPoint.z, hitPoint2.z, epsilon)); @@ -850,156 +704,108 @@ class TestRaycast : public Test { test(mConeShape->raycast(rayBottom, raycastInfo6)); test(raycastInfo6.body == mConeBody); test(raycastInfo6.proxyShape == mConeShape); - test(approxEqual(raycastInfo6.distance, 2, epsilon)); + test(approxEqual(raycastInfo6.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo6.worldPoint.x, hitPoint2.x, epsilon)); test(approxEqual(raycastInfo6.worldPoint.y, hitPoint2.y, epsilon)); test(approxEqual(raycastInfo6.worldPoint.z, hitPoint2.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(-1, -2, 1), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -1), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(3, 4, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 3), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-3, -2, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(3, -1, 0.5), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, -2, 3), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-2, 0, 0.8), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-0.9, 0, -4), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(17, 29, 28)); + Ray ray3(mLocalShapeToWorld * Vector3(-1, -2, 1), mLocalShapeToWorld * Vector3(-13, -2, 22)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(22, 28, 31)); + Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -1), mLocalShapeToWorld * Vector3(-26, 1, -1)); + Ray ray6(mLocalShapeToWorld * Vector3(3, 4, 1), mLocalShapeToWorld * Vector3(3, -16, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 3), mLocalShapeToWorld * Vector3(1, -4, -17)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalShapeToWorld * Vector3(26, 4, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalShapeToWorld * Vector3(0, 46, -7)); + Ray ray10(mLocalShapeToWorld * Vector3(-3, -2, -6), mLocalShapeToWorld * Vector3(-3, -2, 74)); + Ray ray11(mLocalShapeToWorld * Vector3(3, -1, 0.5), mLocalShapeToWorld * Vector3(-27, -1, 0.5)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalShapeToWorld * Vector3(1, -26, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, -2, 3), mLocalShapeToWorld * Vector3(-1, -2, -27)); + Ray ray14(mLocalShapeToWorld * Vector3(-2, 0, 0.8), mLocalShapeToWorld * Vector3(30, 0, 0.8)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-0.9, 0, -4), mLocalShapeToWorld * Vector3(-0.9, 0, 30)); // ----- Test raycast miss ----- // test(!mConeBody->raycast(ray1, raycastInfo3)); test(!mConeShape->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mConeBody->raycast(ray1)); - test(!mConeShape->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mConeBody->raycast(ray2, raycastInfo3)); test(!mConeShape->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mConeBody->raycast(ray2)); - test(!mConeShape->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mConeBody->raycast(ray3, raycastInfo3)); test(!mConeShape->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mConeBody->raycast(ray3)); - test(!mConeShape->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mConeBody->raycast(ray4, raycastInfo3)); test(!mConeShape->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mConeBody->raycast(ray4)); - test(!mConeShape->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mConeBody->raycast(ray5, raycastInfo3)); test(!mConeShape->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mConeBody->raycast(ray5)); - test(!mConeShape->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mConeBody->raycast(ray6, raycastInfo3)); test(!mConeShape->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mConeBody->raycast(ray6)); - test(!mConeShape->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mConeBody->raycast(ray7, raycastInfo3)); test(!mConeShape->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mConeBody->raycast(ray7)); - test(!mConeShape->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mConeBody->raycast(ray8, raycastInfo3)); test(!mConeShape->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mConeBody->raycast(ray8)); - test(!mConeShape->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mConeBody->raycast(ray9, raycastInfo3)); test(!mConeShape->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mConeBody->raycast(ray9)); - test(!mConeShape->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mConeBody->raycast(ray10, raycastInfo3)); test(!mConeShape->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mConeBody->raycast(ray10)); - test(!mConeShape->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mConeBody->raycast(ray11, raycastInfo3)); test(mConeShape->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mConeBody->raycast(ray11)); - test(mConeShape->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo3)); test(mConeBody->raycast(ray12, raycastInfo3)); test(mConeShape->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mConeBody->raycast(ray12)); - test(mConeShape->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mConeBody->raycast(ray13, raycastInfo3)); test(mConeShape->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mConeBody->raycast(ray13)); - test(mConeShape->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mConeBody->raycast(ray14, raycastInfo3)); test(mConeShape->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mConeBody->raycast(ray14)); - test(mConeShape->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mConeBody->raycast(ray15, raycastInfo3)); test(mConeShape->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mConeBody->raycast(ray15)); - test(mConeShape->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mConeBody->raycast(ray16, raycastInfo3)); test(mConeShape->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mConeBody->raycast(ray16)); - test(mConeShape->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the ProxyConvexMeshShape::raycast(), CollisionBody::raycast() and @@ -1007,10 +813,9 @@ class TestRaycast : public Test { void testConvexMesh() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(1 , 2, 10); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(0, 0, -5); - Ray ray(origin, direction); + Vector3 point1 = mLocalShapeToWorld * Vector3(1 , 2, 6); + Vector3 point2 = mLocalShapeToWorld * Vector3(1, 2, -4); + Ray ray(point1, point2); Vector3 hitPoint = mLocalShapeToWorld * Vector3(1, 2, 4); // CollisionWorld::raycast() @@ -1018,7 +823,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mConvexMeshBody); test(raycastInfo.proxyShape == mConvexMeshShape); - test(approxEqual(raycastInfo.distance, 6, epsilon)); + test(approxEqual(raycastInfo.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z, epsilon)); @@ -1028,7 +833,7 @@ class TestRaycast : public Test { test(mConvexMeshBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mConvexMeshBody); test(raycastInfo2.proxyShape == mConvexMeshShape); - test(approxEqual(raycastInfo2.distance, 6, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -1038,7 +843,7 @@ class TestRaycast : public Test { test(mConvexMeshBodyEdgesInfo->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mConvexMeshBodyEdgesInfo); test(raycastInfo3.proxyShape == mConvexMeshShapeEdgesInfo); - test(approxEqual(raycastInfo3.distance, 6, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); @@ -1048,7 +853,7 @@ class TestRaycast : public Test { test(mConvexMeshShape->raycast(ray, raycastInfo4)); test(raycastInfo4.body == mConvexMeshBody); test(raycastInfo4.proxyShape == mConvexMeshShape); - test(approxEqual(raycastInfo4.distance, 6, epsilon)); + test(approxEqual(raycastInfo4.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo4.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo4.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo4.worldPoint.z, hitPoint.z, epsilon)); @@ -1058,27 +863,27 @@ class TestRaycast : public Test { test(mConvexMeshShapeEdgesInfo->raycast(ray, raycastInfo5)); test(raycastInfo5.body == mConvexMeshBodyEdgesInfo); test(raycastInfo5.proxyShape == mConvexMeshShapeEdgesInfo); - test(approxEqual(raycastInfo5.distance, 6, epsilon)); + test(approxEqual(raycastInfo5.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo5.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo5.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo5.worldPoint.z, hitPoint.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 3), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(3, 1, -5), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-3, 0, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(3, 1, 2), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(17, 29, 28)); + Ray ray3(mLocalShapeToWorld * Vector3(1, 2, 3), mLocalShapeToWorld * Vector3(-11, 2, 24)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(22, 28, 31)); + Ray ray5(mLocalShapeToWorld * Vector3(3, 1, -5), mLocalShapeToWorld * Vector3(-30, 1, -5)); + Ray ray6(mLocalShapeToWorld * Vector3(4, 4, 1), mLocalShapeToWorld * Vector3(4, -30, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -4, 5), mLocalShapeToWorld * Vector3(1, -4, -30)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 4, 0), mLocalShapeToWorld * Vector3(30, 4, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -4, -7), mLocalShapeToWorld * Vector3(0, 30, -7)); + Ray ray10(mLocalShapeToWorld * Vector3(-3, 0, -6), mLocalShapeToWorld * Vector3(-3, 0, 30)); + Ray ray11(mLocalShapeToWorld * Vector3(3, 1, 2), mLocalShapeToWorld * Vector3(-30, 0, -6)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 4, -1), mLocalShapeToWorld * Vector3(1, -30, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 5), mLocalShapeToWorld * Vector3(-1, 2, -30)); + Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalShapeToWorld * Vector3(30, 2, -2)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -4, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalShapeToWorld * Vector3(-1, 2, 30)); // ----- Test raycast miss ----- // test(!mConvexMeshBody->raycast(ray1, raycastInfo3)); @@ -1086,119 +891,69 @@ class TestRaycast : public Test { test(!mConvexMeshShape->raycast(ray1, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mConvexMeshBody->raycast(ray1)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray1)); - test(!mConvexMeshShape->raycast(ray1)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mConvexMeshBody->raycast(ray2, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray2, raycastInfo3)); test(!mConvexMeshShape->raycast(ray2, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray2)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray2)); - test(!mConvexMeshShape->raycast(ray2)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mConvexMeshBody->raycast(ray3, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray3, raycastInfo3)); test(!mConvexMeshShape->raycast(ray3, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray3)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray3)); - test(!mConvexMeshShape->raycast(ray3)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mConvexMeshBody->raycast(ray4, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray4, raycastInfo3)); test(!mConvexMeshShape->raycast(ray4, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray4)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray4)); - test(!mConvexMeshShape->raycast(ray4)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mConvexMeshBody->raycast(ray5, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray5, raycastInfo3)); test(!mConvexMeshShape->raycast(ray5, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray5)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray5)); - test(!mConvexMeshShape->raycast(ray5)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mConvexMeshBody->raycast(ray6, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray6, raycastInfo3)); test(!mConvexMeshShape->raycast(ray6, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray6)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray6)); - test(!mConvexMeshShape->raycast(ray6)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mConvexMeshBody->raycast(ray7, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray7, raycastInfo3)); test(!mConvexMeshShape->raycast(ray7, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray7)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray7)); - test(!mConvexMeshShape->raycast(ray7)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mConvexMeshBody->raycast(ray8, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray8, raycastInfo3)); test(!mConvexMeshShape->raycast(ray8, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray8)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray8)); - test(!mConvexMeshShape->raycast(ray8)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mConvexMeshBody->raycast(ray9, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray9, raycastInfo3)); test(!mConvexMeshShape->raycast(ray9, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray9)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray9)); - test(!mConvexMeshShape->raycast(ray9)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mConvexMeshBody->raycast(ray10, raycastInfo3)); test(!mConvexMeshBodyEdgesInfo->raycast(ray10, raycastInfo3)); test(!mConvexMeshShape->raycast(ray10, raycastInfo3)); test(!mConvexMeshShapeEdgesInfo->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mConvexMeshBody->raycast(ray10)); - test(!mConvexMeshBodyEdgesInfo->raycast(ray10)); - test(!mConvexMeshShape->raycast(ray10)); - test(!mConvexMeshShapeEdgesInfo->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mConvexMeshBody->raycast(ray11, raycastInfo3)); @@ -1206,72 +961,42 @@ class TestRaycast : public Test { test(mConvexMeshShape->raycast(ray11, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mConvexMeshBody->raycast(ray11)); - test(mConvexMeshBodyEdgesInfo->raycast(ray11)); - test(mConvexMeshShape->raycast(ray11)); - test(mConvexMeshShapeEdgesInfo->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo3)); test(mConvexMeshBody->raycast(ray12, raycastInfo3)); test(mConvexMeshBodyEdgesInfo->raycast(ray12, raycastInfo3)); test(mConvexMeshShape->raycast(ray12, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mConvexMeshBody->raycast(ray12)); - test(mConvexMeshBodyEdgesInfo->raycast(ray12)); - test(mConvexMeshShape->raycast(ray12)); - test(mConvexMeshShapeEdgesInfo->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mConvexMeshBody->raycast(ray13, raycastInfo3)); test(mConvexMeshBodyEdgesInfo->raycast(ray13, raycastInfo3)); test(mConvexMeshShape->raycast(ray13, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mConvexMeshBody->raycast(ray13)); - test(mConvexMeshBodyEdgesInfo->raycast(ray13)); - test(mConvexMeshShape->raycast(ray13)); - test(mConvexMeshShapeEdgesInfo->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mConvexMeshBody->raycast(ray14, raycastInfo3)); test(mConvexMeshBodyEdgesInfo->raycast(ray14, raycastInfo3)); test(mConvexMeshShape->raycast(ray14, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mConvexMeshBody->raycast(ray14)); - test(mConvexMeshBodyEdgesInfo->raycast(ray14)); - test(mConvexMeshShape->raycast(ray14)); - test(mConvexMeshShapeEdgesInfo->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mConvexMeshBody->raycast(ray15, raycastInfo3)); test(mConvexMeshBodyEdgesInfo->raycast(ray15, raycastInfo3)); test(mConvexMeshShape->raycast(ray15, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mConvexMeshBody->raycast(ray15)); - test(mConvexMeshBodyEdgesInfo->raycast(ray15)); - test(mConvexMeshShape->raycast(ray15)); - test(mConvexMeshShapeEdgesInfo->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mConvexMeshBody->raycast(ray16, raycastInfo3)); test(mConvexMeshBodyEdgesInfo->raycast(ray16, raycastInfo3)); test(mConvexMeshShape->raycast(ray16, raycastInfo3)); test(mConvexMeshShapeEdgesInfo->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mConvexMeshBody->raycast(ray16)); - test(mConvexMeshBodyEdgesInfo->raycast(ray16)); - test(mConvexMeshShape->raycast(ray16)); - test(mConvexMeshShapeEdgesInfo->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the ProxyCylinderShape::raycast(), CollisionBody::raycast() and @@ -1279,20 +1004,19 @@ class TestRaycast : public Test { void testCylinder() { // ----- Test feedback data ----- // - Vector3 origin = mLocalShapeToWorld * Vector3(6 , 1, 0); - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); - Vector3 direction = mLocalToWorldMatrix * Vector3(-2, 0, 0); - Ray ray(origin, direction); + Vector3 point1A = mLocalShapeToWorld * Vector3(4 , 1, 0); + Vector3 point1B = mLocalShapeToWorld * Vector3(-6, 1, 0); + Ray ray(point1A, point1B); Vector3 hitPoint = mLocalShapeToWorld * Vector3(2, 1, 0); - Vector3 origin2 = mLocalShapeToWorld * Vector3(0 , 10, 0); - Vector3 direction2 = mLocalToWorldMatrix * Vector3(0, -3, 0); - Ray rayTop(origin2, direction2); + Vector3 point2A = mLocalShapeToWorld * Vector3(0 , 4.5, 0); + Vector3 point2B = mLocalShapeToWorld * Vector3(0, -5.5, 0); + Ray rayTop(point2A, point2B); Vector3 hitPointTop = mLocalShapeToWorld * Vector3(0, decimal(2.5), 0); - Vector3 origin3 = mLocalShapeToWorld * Vector3(0 , -10, 0); - Vector3 direction3 = mLocalToWorldMatrix * Vector3(0, 3, 0); - Ray rayBottom(origin3, direction3); + Vector3 point3A = mLocalShapeToWorld * Vector3(0 , -4.5, 0); + Vector3 point3B = mLocalShapeToWorld * Vector3(0, 5.5, 0); + Ray rayBottom(point3A, point3B); Vector3 hitPointBottom = mLocalShapeToWorld * Vector3(0, decimal(-2.5), 0); // CollisionWorld::raycast() @@ -1300,7 +1024,7 @@ class TestRaycast : public Test { test(mWorld->raycast(ray, raycastInfo)); test(raycastInfo.body == mCylinderBody); test(raycastInfo.proxyShape == mCylinderShape); - test(approxEqual(raycastInfo.distance, 4, epsilon)); + test(approxEqual(raycastInfo.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo.worldPoint.z, hitPoint.z, epsilon)); @@ -1310,7 +1034,7 @@ class TestRaycast : public Test { test(mCylinderBody->raycast(ray, raycastInfo2)); test(raycastInfo2.body == mCylinderBody); test(raycastInfo2.proxyShape == mCylinderShape); - test(approxEqual(raycastInfo2.distance, 4, epsilon)); + test(approxEqual(raycastInfo2.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo2.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo2.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo2.worldPoint.z, hitPoint.z, epsilon)); @@ -1320,7 +1044,7 @@ class TestRaycast : public Test { test(mCylinderShape->raycast(ray, raycastInfo3)); test(raycastInfo3.body == mCylinderBody); test(raycastInfo3.proxyShape == mCylinderShape); - test(approxEqual(raycastInfo3.distance, 4, epsilon)); + test(approxEqual(raycastInfo3.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo3.worldPoint.x, hitPoint.x, epsilon)); test(approxEqual(raycastInfo3.worldPoint.y, hitPoint.y, epsilon)); test(approxEqual(raycastInfo3.worldPoint.z, hitPoint.z, epsilon)); @@ -1330,7 +1054,7 @@ class TestRaycast : public Test { test(mCylinderShape->raycast(rayTop, raycastInfo5)); test(raycastInfo5.body == mCylinderBody); test(raycastInfo5.proxyShape == mCylinderShape); - test(approxEqual(raycastInfo5.distance, decimal(7.5), epsilon)); + test(approxEqual(raycastInfo5.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo5.worldPoint.x, hitPointTop.x, epsilon)); test(approxEqual(raycastInfo5.worldPoint.y, hitPointTop.y, epsilon)); test(approxEqual(raycastInfo5.worldPoint.z, hitPointTop.z, epsilon)); @@ -1340,156 +1064,108 @@ class TestRaycast : public Test { test(mCylinderShape->raycast(rayBottom, raycastInfo6)); test(raycastInfo6.body == mCylinderBody); test(raycastInfo6.proxyShape == mCylinderShape); - test(approxEqual(raycastInfo6.distance, decimal(7.5), epsilon)); + test(approxEqual(raycastInfo6.hitFraction, decimal(0.2), epsilon)); test(approxEqual(raycastInfo6.worldPoint.x, hitPointBottom.x, epsilon)); test(approxEqual(raycastInfo6.worldPoint.y, hitPointBottom.y, epsilon)); test(approxEqual(raycastInfo6.worldPoint.z, hitPointBottom.z, epsilon)); - Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalToWorldMatrix * Vector3(5, 7, -1)); - Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray3(mLocalShapeToWorld * Vector3(1, 3, -1), mLocalToWorldMatrix * Vector3(-4, 0, 7)); - Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalToWorldMatrix * Vector3(4, 6, 7)); - Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalToWorldMatrix * Vector3(-3, 0, 0)); - Ray ray6(mLocalShapeToWorld * Vector3(4, 9, 1), mLocalToWorldMatrix * Vector3(0, -2, 0)); - Ray ray7(mLocalShapeToWorld * Vector3(1, -9, 5), mLocalToWorldMatrix * Vector3(0, 0, -2)); - Ray ray8(mLocalShapeToWorld * Vector3(-4, 9, 0), mLocalToWorldMatrix * Vector3(1, 0, 0)); - Ray ray9(mLocalShapeToWorld * Vector3(0, -9, -4), mLocalToWorldMatrix * Vector3(0, 5, 0)); - Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalToWorldMatrix * Vector3(0, 0, 8)); - Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 1.5), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 9, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShapeToWorld * Vector3(0, 0, 0), mLocalShapeToWorld * Vector3(5, 7, -1)); + Ray ray2(mLocalShapeToWorld * Vector3(5, 11, 7), mLocalShapeToWorld * Vector3(17, 20, 28)); + Ray ray3(mLocalShapeToWorld * Vector3(1, 3, -1), mLocalShapeToWorld * Vector3(-11,3, 20)); + Ray ray4(mLocalShapeToWorld * Vector3(10, 10, 10), mLocalShapeToWorld * Vector3(22, 28, 31)); + Ray ray5(mLocalShapeToWorld * Vector3(4, 1, -5), mLocalShapeToWorld * Vector3(-30, 1, -5)); + Ray ray6(mLocalShapeToWorld * Vector3(4, 9, 1), mLocalShapeToWorld * Vector3(4, -30, 1)); + Ray ray7(mLocalShapeToWorld * Vector3(1, -9, 5), mLocalShapeToWorld * Vector3(1, -9, -30)); + Ray ray8(mLocalShapeToWorld * Vector3(-4, 9, 0), mLocalShapeToWorld * Vector3(30, 9, 0)); + Ray ray9(mLocalShapeToWorld * Vector3(0, -9, -4), mLocalShapeToWorld * Vector3(0, 30, -4)); + Ray ray10(mLocalShapeToWorld * Vector3(-4, 0, -6), mLocalShapeToWorld * Vector3(-4, 0, 30)); + Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 1.5), mLocalShapeToWorld * Vector3(-30, 1, 1.5)); + Ray ray12(mLocalShapeToWorld * Vector3(1, 9, -1), mLocalShapeToWorld * Vector3(1, -30, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalShapeToWorld * Vector3(-1, 2, -30)); + Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalShapeToWorld * Vector3(30, 2, -2)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalShapeToWorld * Vector3(-1, 2, 30)); // ----- Test raycast miss ----- // test(!mCylinderBody->raycast(ray1, raycastInfo3)); test(!mCylinderShape->raycast(ray1, raycastInfo3)); test(!mWorld->raycast(ray1, raycastInfo3)); - test(!mWorld->raycast(ray1, raycastInfo3, 1)); - test(!mWorld->raycast(ray1, raycastInfo3, 100)); - test(!mCylinderBody->raycast(ray1)); - test(!mCylinderShape->raycast(ray1)); - test(!mWorld->raycast(ray1)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(100.0)), raycastInfo3)); test(!mCylinderBody->raycast(ray2, raycastInfo3)); test(!mCylinderShape->raycast(ray2, raycastInfo3)); test(!mWorld->raycast(ray2, raycastInfo3)); - test(!mCylinderBody->raycast(ray2)); - test(!mCylinderShape->raycast(ray2)); - test(!mWorld->raycast(ray2)); test(!mCylinderBody->raycast(ray3, raycastInfo3)); test(!mCylinderShape->raycast(ray3, raycastInfo3)); test(!mWorld->raycast(ray3, raycastInfo3)); - test(!mCylinderBody->raycast(ray3)); - test(!mCylinderShape->raycast(ray3)); - test(!mWorld->raycast(ray3)); test(!mCylinderBody->raycast(ray4, raycastInfo3)); test(!mCylinderShape->raycast(ray4, raycastInfo3)); test(!mWorld->raycast(ray4, raycastInfo3)); - test(!mCylinderBody->raycast(ray4)); - test(!mCylinderShape->raycast(ray4)); - test(!mWorld->raycast(ray4)); test(!mCylinderBody->raycast(ray5, raycastInfo3)); test(!mCylinderShape->raycast(ray5, raycastInfo3)); test(!mWorld->raycast(ray5, raycastInfo3)); - test(!mCylinderBody->raycast(ray5)); - test(!mCylinderShape->raycast(ray5)); - test(!mWorld->raycast(ray5)); test(!mCylinderBody->raycast(ray6, raycastInfo3)); test(!mCylinderShape->raycast(ray6, raycastInfo3)); test(!mWorld->raycast(ray6, raycastInfo3)); - test(!mCylinderBody->raycast(ray6)); - test(!mCylinderShape->raycast(ray6)); - test(!mWorld->raycast(ray6)); test(!mCylinderBody->raycast(ray7, raycastInfo3)); test(!mCylinderShape->raycast(ray7, raycastInfo3)); test(!mWorld->raycast(ray7, raycastInfo3)); - test(!mCylinderBody->raycast(ray7)); - test(!mCylinderShape->raycast(ray7)); - test(!mWorld->raycast(ray7)); test(!mCylinderBody->raycast(ray8, raycastInfo3)); test(!mCylinderShape->raycast(ray8, raycastInfo3)); test(!mWorld->raycast(ray8, raycastInfo3)); - test(!mCylinderBody->raycast(ray8)); - test(!mCylinderShape->raycast(ray8)); - test(!mWorld->raycast(ray8)); test(!mCylinderBody->raycast(ray9, raycastInfo3)); test(!mCylinderShape->raycast(ray9, raycastInfo3)); test(!mWorld->raycast(ray9, raycastInfo3)); - test(!mCylinderBody->raycast(ray9)); - test(!mCylinderShape->raycast(ray9)); - test(!mWorld->raycast(ray9)); test(!mCylinderBody->raycast(ray10, raycastInfo3)); test(!mCylinderShape->raycast(ray10, raycastInfo3)); test(!mWorld->raycast(ray10, raycastInfo3)); - test(!mCylinderBody->raycast(ray10)); - test(!mCylinderShape->raycast(ray10)); - test(!mWorld->raycast(ray10)); - test(!mWorld->raycast(ray11, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray12, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray13, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray14, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray15, raycastInfo3, 0.5)); - test(!mWorld->raycast(ray16, raycastInfo3, 2)); + test(!mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.01)), raycastInfo3)); + test(!mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.01)), raycastInfo3)); // ----- Test raycast hits ----- // test(mCylinderBody->raycast(ray11, raycastInfo3)); test(mCylinderShape->raycast(ray11, raycastInfo3)); test(mWorld->raycast(ray11, raycastInfo3)); - test(mWorld->raycast(ray11, raycastInfo3, 2)); - test(mCylinderBody->raycast(ray11)); - test(mCylinderShape->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.8)), raycastInfo3)); test(mCylinderBody->raycast(ray12, raycastInfo3)); test(mCylinderShape->raycast(ray12, raycastInfo3)); test(mWorld->raycast(ray12, raycastInfo3)); - test(mWorld->raycast(ray12, raycastInfo3, 2)); - test(mCylinderBody->raycast(ray12)); - test(mCylinderShape->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo3)); test(mCylinderBody->raycast(ray13, raycastInfo3)); test(mCylinderShape->raycast(ray13, raycastInfo3)); test(mWorld->raycast(ray13, raycastInfo3)); - test(mWorld->raycast(ray13, raycastInfo3, 2)); - test(mCylinderBody->raycast(ray13)); - test(mCylinderShape->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo3)); test(mCylinderBody->raycast(ray14, raycastInfo3)); test(mCylinderShape->raycast(ray14, raycastInfo3)); test(mWorld->raycast(ray14, raycastInfo3)); - test(mWorld->raycast(ray14, raycastInfo3, 2)); - test(mCylinderBody->raycast(ray14)); - test(mCylinderShape->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo3)); test(mCylinderBody->raycast(ray15, raycastInfo3)); test(mCylinderShape->raycast(ray15, raycastInfo3)); test(mWorld->raycast(ray15, raycastInfo3)); - test(mWorld->raycast(ray15, raycastInfo3, 2)); - test(mCylinderBody->raycast(ray15)); - test(mCylinderShape->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo3)); test(mCylinderBody->raycast(ray16, raycastInfo3)); test(mCylinderShape->raycast(ray16, raycastInfo3)); test(mWorld->raycast(ray16, raycastInfo3)); - test(mWorld->raycast(ray16, raycastInfo3, 4)); - test(mCylinderBody->raycast(ray16)); - test(mCylinderShape->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo3)); } /// Test the CollisionBody::raycast() and @@ -1497,96 +1173,71 @@ class TestRaycast : public Test { void testCompound() { // ----- Test feedback data ----- // - const Matrix3x3 mLocalToWorldMatrix = mLocalShapeToWorld.getOrientation().getMatrix(); // Raycast hit agains the sphere shape - Ray ray1(mLocalShape2ToWorld * Vector3(4, 1, 2), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray2(mLocalShape2ToWorld * Vector3(1, 4, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray3(mLocalShape2ToWorld * Vector3(-1, 2, 5), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray4(mLocalShape2ToWorld * Vector3(-5, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray5(mLocalShape2ToWorld * Vector3(0, -4, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray6(mLocalShape2ToWorld * Vector3(-1, 2, -11), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray1(mLocalShape2ToWorld * Vector3(4, 1, 2), mLocalShape2ToWorld * Vector3(-30, 1, 2)); + Ray ray2(mLocalShape2ToWorld * Vector3(1, 4, -1), mLocalShape2ToWorld * Vector3(1, -30, -1)); + Ray ray3(mLocalShape2ToWorld * Vector3(-1, 2, 5), mLocalShape2ToWorld * Vector3(-1, 2, -30)); + Ray ray4(mLocalShape2ToWorld * Vector3(-5, 2, -2), mLocalShape2ToWorld * Vector3(30, 2, -2)); + Ray ray5(mLocalShape2ToWorld * Vector3(0, -4, 1), mLocalShape2ToWorld * Vector3(0, 30, 1)); + Ray ray6(mLocalShape2ToWorld * Vector3(-1, 2, -11), mLocalShape2ToWorld * Vector3(-1, 2, 30)); RaycastInfo raycastInfo; test(mCompoundBody->raycast(ray1, raycastInfo)); test(mWorld->raycast(ray1, raycastInfo)); - test(mWorld->raycast(ray1, raycastInfo, 2)); - test(mCompoundBody->raycast(ray1)); - test(mWorld->raycast(ray1)); + test(mWorld->raycast(Ray(ray1.point1, ray1.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray2, raycastInfo)); test(mWorld->raycast(ray2, raycastInfo)); - test(mWorld->raycast(ray2, raycastInfo, 2)); - test(mCompoundBody->raycast(ray2)); - test(mWorld->raycast(ray2)); + test(mWorld->raycast(Ray(ray2.point1, ray2.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray3, raycastInfo)); test(mWorld->raycast(ray3, raycastInfo)); - test(mWorld->raycast(ray3, raycastInfo, 2)); - test(mCompoundBody->raycast(ray3)); - test(mWorld->raycast(ray3)); + test(mWorld->raycast(Ray(ray3.point1, ray3.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray4, raycastInfo)); test(mWorld->raycast(ray4, raycastInfo)); - test(mWorld->raycast(ray4, raycastInfo, 2)); - test(mCompoundBody->raycast(ray4)); - test(mWorld->raycast(ray4)); + test(mWorld->raycast(Ray(ray4.point1, ray4.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray5, raycastInfo)); test(mWorld->raycast(ray5, raycastInfo)); - test(mWorld->raycast(ray5, raycastInfo, 2)); - test(mCompoundBody->raycast(ray5)); - test(mWorld->raycast(ray5)); + test(mWorld->raycast(Ray(ray5.point1, ray5.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray6, raycastInfo)); test(mWorld->raycast(ray6, raycastInfo)); - test(mWorld->raycast(ray6, raycastInfo, 4)); - test(mCompoundBody->raycast(ray6)); - test(mWorld->raycast(ray6)); + test(mWorld->raycast(Ray(ray6.point1, ray6.point2, decimal(0.8)), raycastInfo)); // Raycast hit agains the cylinder shape - Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 2), mLocalToWorldMatrix * Vector3(-4, 0, 0)); - Ray ray12(mLocalShapeToWorld * Vector3(1, 9, -1), mLocalToWorldMatrix * Vector3(0, -3, 0)); - Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalToWorldMatrix * Vector3(0, 0, -8)); - Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -2), mLocalToWorldMatrix * Vector3(4, 0, 0)); - Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalToWorldMatrix * Vector3(0, 3, 0)); - Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalToWorldMatrix * Vector3(0, 0, 8)); + Ray ray11(mLocalShapeToWorld * Vector3(4, 1, 1.5), mLocalShapeToWorld * Vector3(-30, 1.5, 2)); + Ray ray12(mLocalShapeToWorld * Vector3(1.5, 9, -1), mLocalShapeToWorld * Vector3(1.5, -30, -1)); + Ray ray13(mLocalShapeToWorld * Vector3(-1, 2, 3), mLocalShapeToWorld * Vector3(-1, 2, -30)); + Ray ray14(mLocalShapeToWorld * Vector3(-3, 2, -1.5), mLocalShapeToWorld * Vector3(30, 1, -1.5)); + Ray ray15(mLocalShapeToWorld * Vector3(0, -9, 1), mLocalShapeToWorld * Vector3(0, 30, 1)); + Ray ray16(mLocalShapeToWorld * Vector3(-1, 2, -7), mLocalShapeToWorld * Vector3(-1, 2, 30)); test(mCompoundBody->raycast(ray11, raycastInfo)); test(mWorld->raycast(ray11, raycastInfo)); - test(mWorld->raycast(ray11, raycastInfo, 2)); - test(mCompoundBody->raycast(ray11)); - test(mWorld->raycast(ray11)); + test(mWorld->raycast(Ray(ray11.point1, ray11.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray12, raycastInfo)); test(mWorld->raycast(ray12, raycastInfo)); - test(mWorld->raycast(ray12, raycastInfo, 2)); - test(mCompoundBody->raycast(ray12)); - test(mWorld->raycast(ray12)); + test(mWorld->raycast(Ray(ray12.point1, ray12.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray13, raycastInfo)); test(mWorld->raycast(ray13, raycastInfo)); - test(mWorld->raycast(ray13, raycastInfo, 2)); - test(mCompoundBody->raycast(ray13)); - test(mWorld->raycast(ray13)); + test(mWorld->raycast(Ray(ray13.point1, ray13.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray14, raycastInfo)); test(mWorld->raycast(ray14, raycastInfo)); - test(mWorld->raycast(ray14, raycastInfo, 2)); - test(mCompoundBody->raycast(ray14)); - test(mWorld->raycast(ray14)); + test(mWorld->raycast(Ray(ray14.point1, ray14.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray15, raycastInfo)); test(mWorld->raycast(ray15, raycastInfo)); - test(mWorld->raycast(ray15, raycastInfo, 2)); - test(mCompoundBody->raycast(ray15)); - test(mWorld->raycast(ray15)); + test(mWorld->raycast(Ray(ray15.point1, ray15.point2, decimal(0.8)), raycastInfo)); test(mCompoundBody->raycast(ray16, raycastInfo)); test(mWorld->raycast(ray16, raycastInfo)); - test(mWorld->raycast(ray16, raycastInfo, 4)); - test(mCompoundBody->raycast(ray16)); - test(mWorld->raycast(ray16)); + test(mWorld->raycast(Ray(ray16.point1, ray16.point2, decimal(0.8)), raycastInfo)); } };