aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp245
1 files changed, 245 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp b/PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp
new file mode 100644
index 00000000..bde848bd
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/intersection/GuIntersectionRayCapsule.cpp
@@ -0,0 +1,245 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "GuIntersectionRayCapsule.h"
+#include "GuIntersectionRaySphere.h"
+
+using namespace physx;
+
+// PT: ray-capsule intersection code, originally from the old Magic Software library.
+PxU32 Gu::intersectRayCapsuleInternal(const PxVec3& origin, const PxVec3& dir, const PxVec3& p0, const PxVec3& p1, float radius, PxReal s[2])
+{
+ // set up quadratic Q(t) = a*t^2 + 2*b*t + c
+ PxVec3 kW = p1 - p0;
+ const float fWLength = kW.magnitude();
+ if(fWLength!=0.0f)
+ kW /= fWLength;
+
+ // PT: if the capsule is in fact a sphere, switch back to dedicated sphere code.
+ // This is not just an optimization, the rest of the code fails otherwise.
+ if(fWLength<=1e-6f)
+ {
+ const float d0 = (origin - p0).magnitudeSquared();
+ const float d1 = (origin - p1).magnitudeSquared();
+ const float approxLength = (PxMax(d0, d1) + radius)*2.0f;
+ return PxU32(Gu::intersectRaySphere(origin, dir, approxLength, p0, radius, s[0]));
+ }
+
+ // generate orthonormal basis
+ PxVec3 kU(0.0f);
+
+ if (fWLength > 0.0f)
+ {
+ PxReal fInvLength;
+ if ( PxAbs(kW.x) >= PxAbs(kW.y) )
+ {
+ // W.x or W.z is the largest magnitude component, swap them
+ fInvLength = PxRecipSqrt(kW.x*kW.x + kW.z*kW.z);
+ kU.x = -kW.z*fInvLength;
+ kU.y = 0.0f;
+ kU.z = kW.x*fInvLength;
+ }
+ else
+ {
+ // W.y or W.z is the largest magnitude component, swap them
+ fInvLength = PxRecipSqrt(kW.y*kW.y + kW.z*kW.z);
+ kU.x = 0.0f;
+ kU.y = kW.z*fInvLength;
+ kU.z = -kW.y*fInvLength;
+ }
+ }
+
+ PxVec3 kV = kW.cross(kU);
+ kV.normalize(); // PT: fixed november, 24, 2004. This is a bug in Magic.
+
+ // compute intersection
+
+ PxVec3 kD(kU.dot(dir), kV.dot(dir), kW.dot(dir));
+ const float fDLength = kD.magnitude();
+ const float fInvDLength = fDLength!=0.0f ? 1.0f/fDLength : 0.0f;
+ kD *= fInvDLength;
+
+ const PxVec3 kDiff = origin - p0;
+ const PxVec3 kP(kU.dot(kDiff), kV.dot(kDiff), kW.dot(kDiff));
+ const PxReal fRadiusSqr = radius*radius;
+
+ // Is the velocity parallel to the capsule direction? (or zero)
+ if ( PxAbs(kD.z) >= 1.0f - PX_EPS_REAL || fDLength < PX_EPS_REAL )
+ {
+ const float fAxisDir = dir.dot(kW);
+
+ const PxReal fDiscr = fRadiusSqr - kP.x*kP.x - kP.y*kP.y;
+ if ( fAxisDir < 0 && fDiscr >= 0.0f )
+ {
+ // Velocity anti-parallel to the capsule direction
+ const PxReal fRoot = PxSqrt(fDiscr);
+ s[0] = (kP.z + fRoot)*fInvDLength;
+ s[1] = -(fWLength - kP.z + fRoot)*fInvDLength;
+ return 2;
+ }
+ else if ( fAxisDir > 0 && fDiscr >= 0.0f )
+ {
+ // Velocity parallel to the capsule direction
+ const PxReal fRoot = PxSqrt(fDiscr);
+ s[0] = -(kP.z + fRoot)*fInvDLength;
+ s[1] = (fWLength - kP.z + fRoot)*fInvDLength;
+ return 2;
+ }
+ else
+ {
+ // sphere heading wrong direction, or no velocity at all
+ return 0;
+ }
+ }
+
+ // test intersection with infinite cylinder
+ PxReal fA = kD.x*kD.x + kD.y*kD.y;
+ PxReal fB = kP.x*kD.x + kP.y*kD.y;
+ PxReal fC = kP.x*kP.x + kP.y*kP.y - fRadiusSqr;
+ PxReal fDiscr = fB*fB - fA*fC;
+ if ( fDiscr < 0.0f )
+ {
+ // line does not intersect infinite cylinder
+ return 0;
+ }
+
+ PxU32 iQuantity = 0;
+
+ if ( fDiscr > 0.0f )
+ {
+ // line intersects infinite cylinder in two places
+ const PxReal fRoot = PxSqrt(fDiscr);
+ const PxReal fInv = 1.0f/fA;
+ PxReal fT = (-fB - fRoot)*fInv;
+ PxReal fTmp = kP.z + fT*kD.z;
+ const float epsilon = 1e-3f; // PT: see TA35174
+ if ( fTmp >= -epsilon && fTmp <= fWLength+epsilon )
+ s[iQuantity++] = fT*fInvDLength;
+
+ fT = (-fB + fRoot)*fInv;
+ fTmp = kP.z + fT*kD.z;
+ if ( fTmp >= -epsilon && fTmp <= fWLength+epsilon )
+ s[iQuantity++] = fT*fInvDLength;
+
+ if ( iQuantity == 2 )
+ {
+ // line intersects capsule wall in two places
+ return 2;
+ }
+ }
+ else
+ {
+ // line is tangent to infinite cylinder
+ const PxReal fT = -fB/fA;
+ const PxReal fTmp = kP.z + fT*kD.z;
+ if ( 0.0f <= fTmp && fTmp <= fWLength )
+ {
+ s[0] = fT*fInvDLength;
+ return 1;
+ }
+ }
+
+ // test intersection with bottom hemisphere
+ // fA = 1
+ fB += kP.z*kD.z;
+ fC += kP.z*kP.z;
+ fDiscr = fB*fB - fC;
+ if ( fDiscr > 0.0f )
+ {
+ const PxReal fRoot = PxSqrt(fDiscr);
+ PxReal fT = -fB - fRoot;
+ PxReal fTmp = kP.z + fT*kD.z;
+ if ( fTmp <= 0.0f )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+
+ fT = -fB + fRoot;
+ fTmp = kP.z + fT*kD.z;
+ if ( fTmp <= 0.0f )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+ }
+ else if ( fDiscr == 0.0f )
+ {
+ const PxReal fT = -fB;
+ const PxReal fTmp = kP.z + fT*kD.z;
+ if ( fTmp <= 0.0f )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+ }
+
+ // test intersection with top hemisphere
+ // fA = 1
+ fB -= kD.z*fWLength;
+ fC += fWLength*(fWLength - 2.0f*kP.z);
+
+ fDiscr = fB*fB - fC;
+ if ( fDiscr > 0.0f )
+ {
+ const PxReal fRoot = PxSqrt(fDiscr);
+ PxReal fT = -fB - fRoot;
+ PxReal fTmp = kP.z + fT*kD.z;
+ if ( fTmp >= fWLength )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+
+ fT = -fB + fRoot;
+ fTmp = kP.z + fT*kD.z;
+ if ( fTmp >= fWLength )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+ }
+ else if ( fDiscr == 0.0f )
+ {
+ const PxReal fT = -fB;
+ const PxReal fTmp = kP.z + fT*kD.z;
+ if ( fTmp >= fWLength )
+ {
+ s[iQuantity++] = fT*fInvDLength;
+ if ( iQuantity == 2 )
+ return 2;
+ }
+ }
+ return iQuantity;
+}