2 Physics Effects Copyright(C) 2010 Sony Computer Entertainment Inc.
\r
5 Physics Effects is open software; you can redistribute it and/or
\r
6 modify it under the terms of the BSD License.
\r
8 Physics Effects is distributed in the hope that it will be useful,
\r
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
\r
11 See the BSD License for more details.
\r
13 A copy of the BSD License is distributed with
\r
14 Physics Effects under the filename: physics_effects_license.txt
\r
17 #include "../../../include/physics_effects/base_level/base/pfx_vec_utils.h"
\r
18 #include "../../../include/physics_effects/base_level/collision/pfx_capsule.h"
\r
19 #include "pfx_contact_capsule_capsule.h"
\r
22 namespace PhysicsEffects {
\r
26 segmentsClosestPoints(
\r
27 PfxVector3& ptsVector,
\r
28 PfxVector3& offsetA,
\r
29 PfxVector3& offsetB,
\r
30 PfxFloat& tA, PfxFloat& tB,
\r
31 const PfxVector3 &translation,
\r
32 const PfxVector3 &dirA, PfxFloat hlenA,
\r
33 const PfxVector3 &dirB, PfxFloat hlenB )
\r
35 // compute the parameters of the closest points on each line segment
\r
37 PfxFloat dirA_dot_dirB = dot(dirA,dirB);
\r
38 PfxFloat dirA_dot_trans = dot(dirA,translation);
\r
39 PfxFloat dirB_dot_trans = dot(dirB,translation);
\r
41 PfxFloat denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
\r
43 if ( denom == 0.0f ) {
\r
46 tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
\r
49 else if ( tA > hlenA )
\r
53 tB = tA * dirA_dot_dirB - dirB_dot_trans;
\r
55 if ( tB < -hlenB ) {
\r
57 tA = tB * dirA_dot_dirB + dirA_dot_trans;
\r
61 else if ( tA > hlenA )
\r
63 } else if ( tB > hlenB ) {
\r
65 tA = tB * dirA_dot_dirB + dirA_dot_trans;
\r
69 else if ( tA > hlenA )
\r
73 // compute the closest points relative to segment centers.
\r
75 offsetA = dirA * tA;
\r
76 offsetB = dirB * tB;
\r
78 ptsVector = translation - offsetA + offsetB;
\r
83 segmentsNormal( PfxVector3& normal, const PfxVector3 &ptsVector )
\r
85 // compute the unit direction vector between the closest points.
\r
86 // with convex objects, you want the unit direction providing the largest gap between the
\r
87 // objects when they're projected onto it. So, if you have a few candidates covering different
\r
88 // configurations of the objects, you can compute them all, test the gaps and pick best axis
\r
89 // based on this. Some directions might be degenerate, and the normalized() function tests for
\r
90 // degeneracy and returns an arbitrary unit vector in that case.
\r
94 // closest points vector
\r
96 normal = pfxSafeNormalize(ptsVector);
\r
99 PfxFloat pfxContactCapsuleCapsule(
\r
100 PfxVector3 &normal,PfxPoint3 &pointA,PfxPoint3 &pointB,
\r
101 void *shapeA,const PfxTransform3 &transformA,
\r
102 void *shapeB,const PfxTransform3 &transformB,
\r
103 PfxFloat distanceThreshold)
\r
105 PfxCapsule &capsuleA = *((PfxCapsule*)shapeA);
\r
106 PfxCapsule &capsuleB = *((PfxCapsule*)shapeB);
\r
108 PfxVector3 directionA = transformA.getUpper3x3().getCol0();
\r
109 PfxVector3 translationA = transformA.getTranslation();
\r
110 PfxVector3 directionB = transformB.getUpper3x3().getCol0();
\r
111 PfxVector3 translationB = transformB.getTranslation();
\r
113 // translation between centers
\r
115 PfxVector3 translation = translationB - translationA;
\r
117 // compute the closest points of the capsule line segments
\r
119 PfxVector3 ptsVector; // the vector between the closest points
\r
120 PfxVector3 offsetA, offsetB; // offsets from segment centers to their closest points
\r
121 PfxFloat tA, tB; // parameters on line segment
\r
123 segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
\r
124 directionA, capsuleA.m_halfLen, directionB, capsuleB.m_halfLen );
\r
126 PfxFloat distance = length(ptsVector) - capsuleA.m_radius - capsuleB.m_radius;
\r
128 if ( distance > distanceThreshold )
\r
131 // compute the contact normal
\r
133 segmentsNormal( normal, ptsVector );
\r
135 // compute points on capsules
\r
137 pointA = PfxPoint3( transpose(transformA.getUpper3x3()) * ( offsetA + normal * capsuleA.m_radius ) );
\r
138 pointB = PfxPoint3( transpose(transformB.getUpper3x3()) * ( offsetB - normal * capsuleB.m_radius ) );
\r
143 } //namespace PhysicsEffects
\r