Blender V2.61 - r43446

btTransformUtil.h

Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
00003 
00004 This software is provided 'as-is', without any express or implied warranty.
00005 In no event will the authors be held liable for any damages arising from the use of this software.
00006 Permission is granted to anyone to use this software for any purpose, 
00007 including commercial applications, and to alter it and redistribute it freely, 
00008 subject to the following restrictions:
00009 
00010 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00011 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00012 3. This notice may not be removed or altered from any source distribution.
00013 */
00014 
00015 
00016 #ifndef SIMD_TRANSFORM_UTIL_H
00017 #define SIMD_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 //  #define QUATERNION_DERIVATIVE
00047     #ifdef QUATERNION_DERIVATIVE
00048         btQuaternion predictedOrn = curTrans.getRotation();
00049         predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
00050         predictedOrn.normalize();
00051     #else
00052         //Exponential map
00053         //google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
00054 
00055         btVector3 axis;
00056         btScalar    fAngle = angvel.length(); 
00057         //limit the angular motion
00058         if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
00059         {
00060             fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
00061         }
00062 
00063         if ( fAngle < btScalar(0.001) )
00064         {
00065             // use Taylor's expansions of sync function
00066             axis   = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
00067         }
00068         else
00069         {
00070             // sync(fAngle) = sin(c*fAngle)/t
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         //check for axis length
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         //check for axis length
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 //SIMD_TRANSFORM_UTIL_H
00228