00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef BT_TRANSFORM_UTIL_H
00017 #define BT_TRANSFORM_UTIL_H
00018
00019 #include "btTransform.h"
00020 #define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
00021
00022
00023
00024
00025 SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
00026 {
00027 return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
00028 supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
00029 supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z());
00030 }
00031
00032
00033
00034
00035
00036
00038 class btTransformUtil
00039 {
00040
00041 public:
00042
00043 static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
00044 {
00045 predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
00046
00047 #ifdef QUATERNION_DERIVATIVE
00048 btQuaternion predictedOrn = curTrans.getRotation();
00049 predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
00050 predictedOrn.normalize();
00051 #else
00052
00053
00054
00055 btVector3 axis;
00056 btScalar fAngle = angvel.length();
00057
00058 if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
00059 {
00060 fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
00061 }
00062
00063 if ( fAngle < btScalar(0.001) )
00064 {
00065
00066 axis = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
00067 }
00068 else
00069 {
00070
00071 axis = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
00072 }
00073 btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
00074 btQuaternion orn0 = curTrans.getRotation();
00075
00076 btQuaternion predictedOrn = dorn * orn0;
00077 predictedOrn.normalize();
00078 #endif
00079 predictedTransform.setRotation(predictedOrn);
00080 }
00081
00082 static void calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
00083 {
00084 linVel = (pos1 - pos0) / timeStep;
00085 btVector3 axis;
00086 btScalar angle;
00087 if (orn0 != orn1)
00088 {
00089 calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
00090 angVel = axis * angle / timeStep;
00091 } else
00092 {
00093 angVel.setValue(0,0,0);
00094 }
00095 }
00096
00097 static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
00098 {
00099 btQuaternion orn1 = orn0.nearest(orn1a);
00100 btQuaternion dorn = orn1 * orn0.inverse();
00101 angle = dorn.getAngle();
00102 axis = btVector3(dorn.x(),dorn.y(),dorn.z());
00103 axis[3] = btScalar(0.);
00104
00105 btScalar len = axis.length2();
00106 if (len < SIMD_EPSILON*SIMD_EPSILON)
00107 axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
00108 else
00109 axis /= btSqrt(len);
00110 }
00111
00112 static void calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
00113 {
00114 linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
00115 btVector3 axis;
00116 btScalar angle;
00117 calculateDiffAxisAngle(transform0,transform1,axis,angle);
00118 angVel = axis * angle / timeStep;
00119 }
00120
00121 static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
00122 {
00123 btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
00124 btQuaternion dorn;
00125 dmat.getRotation(dorn);
00126
00128 dorn.normalize();
00129
00130 angle = dorn.getAngle();
00131 axis = btVector3(dorn.x(),dorn.y(),dorn.z());
00132 axis[3] = btScalar(0.);
00133
00134 btScalar len = axis.length2();
00135 if (len < SIMD_EPSILON*SIMD_EPSILON)
00136 axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
00137 else
00138 axis /= btSqrt(len);
00139 }
00140
00141 };
00142
00143
00146 class btConvexSeparatingDistanceUtil
00147 {
00148 btQuaternion m_ornA;
00149 btQuaternion m_ornB;
00150 btVector3 m_posA;
00151 btVector3 m_posB;
00152
00153 btVector3 m_separatingNormal;
00154
00155 btScalar m_boundingRadiusA;
00156 btScalar m_boundingRadiusB;
00157 btScalar m_separatingDistance;
00158
00159 public:
00160
00161 btConvexSeparatingDistanceUtil(btScalar boundingRadiusA,btScalar boundingRadiusB)
00162 :m_boundingRadiusA(boundingRadiusA),
00163 m_boundingRadiusB(boundingRadiusB),
00164 m_separatingDistance(0.f)
00165 {
00166 }
00167
00168 btScalar getConservativeSeparatingDistance()
00169 {
00170 return m_separatingDistance;
00171 }
00172
00173 void updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
00174 {
00175 const btVector3& toPosA = transA.getOrigin();
00176 const btVector3& toPosB = transB.getOrigin();
00177 btQuaternion toOrnA = transA.getRotation();
00178 btQuaternion toOrnB = transB.getRotation();
00179
00180 if (m_separatingDistance>0.f)
00181 {
00182
00183
00184 btVector3 linVelA,angVelA,linVelB,angVelB;
00185 btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
00186 btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
00187 btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
00188 btVector3 relLinVel = (linVelB-linVelA);
00189 btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
00190 if (relLinVelocLength<0.f)
00191 {
00192 relLinVelocLength = 0.f;
00193 }
00194
00195 btScalar projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
00196 m_separatingDistance -= projectedMotion;
00197 }
00198
00199 m_posA = toPosA;
00200 m_posB = toPosB;
00201 m_ornA = toOrnA;
00202 m_ornB = toOrnB;
00203 }
00204
00205 void initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
00206 {
00207 m_separatingDistance = separatingDistance;
00208
00209 if (m_separatingDistance>0.f)
00210 {
00211 m_separatingNormal = separatingVector;
00212
00213 const btVector3& toPosA = transA.getOrigin();
00214 const btVector3& toPosB = transB.getOrigin();
00215 btQuaternion toOrnA = transA.getRotation();
00216 btQuaternion toOrnB = transB.getRotation();
00217 m_posA = toPosA;
00218 m_posB = toPosB;
00219 m_ornA = toOrnA;
00220 m_ornB = toOrnB;
00221 }
00222 }
00223
00224 };
00225
00226
00227 #endif //BT_TRANSFORM_UTIL_H
00228