Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Apr 8, 2009, 12:58:47 AM (16 years ago)
Author:
dafrick
Message:

Reverted to revision 2906 (because I'm too stupid to merge correctly, 2nd try will follow shortly. ;))

Location:
code/branches/questsystem5
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/branches/questsystem5

  • code/branches/questsystem5/src/bullet/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp

    r2907 r2908  
    2020#include "LinearMath/btMinMax.h"
    2121#include <new>
    22 #include "btSolverBody.h"
    23 
    24 //-----------------------------------------------------------------------------
    25 
    26 #define HINGE_USE_OBSOLETE_SOLVER false
    27 
    28 //-----------------------------------------------------------------------------
    2922
    3023
    3124btHingeConstraint::btHingeConstraint()
    3225: btTypedConstraint (HINGE_CONSTRAINT_TYPE),
    33 m_enableAngularMotor(false),
    34 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
    35 m_useReferenceFrameA(false)
    36 {
    37         m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
    38 }
    39 
    40 //-----------------------------------------------------------------------------
     26m_enableAngularMotor(false)
     27{
     28}
    4129
    4230btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB,
    43                                                                          btVector3& axisInA,btVector3& axisInB, bool useReferenceFrameA)
     31                                                                         btVector3& axisInA,btVector3& axisInB)
    4432                                                                         :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),
    4533                                                                         m_angularOnly(false),
    46                                                                          m_enableAngularMotor(false),
    47                                                                          m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
    48                                                                          m_useReferenceFrameA(useReferenceFrameA)
     34                                                                         m_enableAngularMotor(false)
    4935{
    5036        m_rbAFrame.getOrigin() = pivotInA;
     
    7561       
    7662        m_rbBFrame.getOrigin() = pivotInB;
    77         m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),axisInB.getX(),
    78                                                                         rbAxisB1.getY(),rbAxisB2.getY(),axisInB.getY(),
    79                                                                         rbAxisB1.getZ(),rbAxisB2.getZ(),axisInB.getZ() );
     63        m_rbBFrame.getBasis().setValue( rbAxisB1.getX(),rbAxisB2.getX(),-axisInB.getX(),
     64                                                                        rbAxisB1.getY(),rbAxisB2.getY(),-axisInB.getY(),
     65                                                                        rbAxisB1.getZ(),rbAxisB2.getZ(),-axisInB.getZ() );
    8066       
    8167        //start with free
     
    8672        m_limitSoftness = 0.9f;
    8773        m_solveLimit = false;
    88         m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
    89 }
    90 
    91 //-----------------------------------------------------------------------------
    92 
    93 btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA, bool useReferenceFrameA)
    94 :btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false),
    95 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
    96 m_useReferenceFrameA(useReferenceFrameA)
     74
     75}
     76
     77
     78
     79btHingeConstraint::btHingeConstraint(btRigidBody& rbA,const btVector3& pivotInA,btVector3& axisInA)
     80:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA), m_angularOnly(false), m_enableAngularMotor(false)
    9781{
    9882
     
    10791                                                                        rbAxisA1.getZ(),rbAxisA2.getZ(),axisInA.getZ() );
    10892
    109         btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * axisInA;
     93        btVector3 axisInB = rbA.getCenterOfMassTransform().getBasis() * -axisInA;
    11094
    11195        btQuaternion rotationArc = shortestArcQuat(axisInA,axisInB);
     
    126110        m_limitSoftness = 0.9f;
    127111        m_solveLimit = false;
    128         m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
    129 }
    130 
    131 //-----------------------------------------------------------------------------
     112}
    132113
    133114btHingeConstraint::btHingeConstraint(btRigidBody& rbA,btRigidBody& rbB,
    134                                                                      const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
     115                                                                     const btTransform& rbAFrame, const btTransform& rbBFrame)
    135116:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA,rbB),m_rbAFrame(rbAFrame),m_rbBFrame(rbBFrame),
    136117m_angularOnly(false),
    137 m_enableAngularMotor(false),
    138 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
    139 m_useReferenceFrameA(useReferenceFrameA)
    140 {
     118m_enableAngularMotor(false)
     119{
     120        // flip axis
     121        m_rbBFrame.getBasis()[0][2] *= btScalar(-1.);
     122        m_rbBFrame.getBasis()[1][2] *= btScalar(-1.);
     123        m_rbBFrame.getBasis()[2][2] *= btScalar(-1.);
     124
    141125        //start with free
    142126        m_lowerLimit = btScalar(1e30);
     
    146130        m_limitSoftness = 0.9f;
    147131        m_solveLimit = false;
    148         m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
    149132}                       
    150133
    151 //-----------------------------------------------------------------------------
    152 
    153 btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame, bool useReferenceFrameA)
     134
     135
     136btHingeConstraint::btHingeConstraint(btRigidBody& rbA, const btTransform& rbAFrame)
    154137:btTypedConstraint(HINGE_CONSTRAINT_TYPE, rbA),m_rbAFrame(rbAFrame),m_rbBFrame(rbAFrame),
    155138m_angularOnly(false),
    156 m_enableAngularMotor(false),
    157 m_useSolveConstraintObsolete(HINGE_USE_OBSOLETE_SOLVER),
    158 m_useReferenceFrameA(useReferenceFrameA)
     139m_enableAngularMotor(false)
    159140{
    160141        ///not providing rigidbody B means implicitly using worldspace for body B
     142
     143        // flip axis
     144        m_rbBFrame.getBasis()[0][2] *= btScalar(-1.);
     145        m_rbBFrame.getBasis()[1][2] *= btScalar(-1.);
     146        m_rbBFrame.getBasis()[2][2] *= btScalar(-1.);
    161147
    162148        m_rbBFrame.getOrigin() = m_rbA.getCenterOfMassTransform()(m_rbAFrame.getOrigin());
     
    169155        m_limitSoftness = 0.9f;
    170156        m_solveLimit = false;
    171         m_referenceSign = m_useReferenceFrameA ? btScalar(-1.f) : btScalar(1.f);
    172 }
    173 
    174 //-----------------------------------------------------------------------------
     157}
    175158
    176159void    btHingeConstraint::buildJacobian()
    177160{
    178         if (m_useSolveConstraintObsolete)
     161        m_appliedImpulse = btScalar(0.);
     162
     163        if (!m_angularOnly)
    179164        {
    180                 m_appliedImpulse = btScalar(0.);
    181 
    182                 if (!m_angularOnly)
    183                 {
    184                         btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
    185                         btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
    186                         btVector3 relPos = pivotBInW - pivotAInW;
    187 
    188                         btVector3 normal[3];
    189                         if (relPos.length2() > SIMD_EPSILON)
    190                         {
    191                                 normal[0] = relPos.normalized();
    192                         }
    193                         else
    194                         {
    195                                 normal[0].setValue(btScalar(1.0),0,0);
    196                         }
    197 
    198                         btPlaneSpace1(normal[0], normal[1], normal[2]);
    199 
    200                         for (int i=0;i<3;i++)
    201                         {
    202                                 new (&m_jac[i]) btJacobianEntry(
     165                btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
     166                btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
     167                btVector3 relPos = pivotBInW - pivotAInW;
     168
     169                btVector3 normal[3];
     170                if (relPos.length2() > SIMD_EPSILON)
     171                {
     172                        normal[0] = relPos.normalized();
     173                }
     174                else
     175                {
     176                        normal[0].setValue(btScalar(1.0),0,0);
     177                }
     178
     179                btPlaneSpace1(normal[0], normal[1], normal[2]);
     180
     181                for (int i=0;i<3;i++)
     182                {
     183                        new (&m_jac[i]) btJacobianEntry(
    203184                                m_rbA.getCenterOfMassTransform().getBasis().transpose(),
    204185                                m_rbB.getCenterOfMassTransform().getBasis().transpose(),
     
    210191                                m_rbB.getInvInertiaDiagLocal(),
    211192                                m_rbB.getInvMass());
     193                }
     194        }
     195
     196        //calculate two perpendicular jointAxis, orthogonal to hingeAxis
     197        //these two jointAxis require equal angular velocities for both bodies
     198
     199        //this is unused for now, it's a todo
     200        btVector3 jointAxis0local;
     201        btVector3 jointAxis1local;
     202       
     203        btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
     204
     205        getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
     206        btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
     207        btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
     208        btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
     209               
     210        new (&m_jacAng[0])      btJacobianEntry(jointAxis0,
     211                m_rbA.getCenterOfMassTransform().getBasis().transpose(),
     212                m_rbB.getCenterOfMassTransform().getBasis().transpose(),
     213                m_rbA.getInvInertiaDiagLocal(),
     214                m_rbB.getInvInertiaDiagLocal());
     215
     216        new (&m_jacAng[1])      btJacobianEntry(jointAxis1,
     217                m_rbA.getCenterOfMassTransform().getBasis().transpose(),
     218                m_rbB.getCenterOfMassTransform().getBasis().transpose(),
     219                m_rbA.getInvInertiaDiagLocal(),
     220                m_rbB.getInvInertiaDiagLocal());
     221
     222        new (&m_jacAng[2])      btJacobianEntry(hingeAxisWorld,
     223                m_rbA.getCenterOfMassTransform().getBasis().transpose(),
     224                m_rbB.getCenterOfMassTransform().getBasis().transpose(),
     225                m_rbA.getInvInertiaDiagLocal(),
     226                m_rbB.getInvInertiaDiagLocal());
     227
     228
     229        // Compute limit information
     230        btScalar hingeAngle = getHingeAngle(); 
     231
     232        //set bias, sign, clear accumulator
     233        m_correction = btScalar(0.);
     234        m_limitSign = btScalar(0.);
     235        m_solveLimit = false;
     236        m_accLimitImpulse = btScalar(0.);
     237
     238//      if (m_lowerLimit < m_upperLimit)
     239        if (m_lowerLimit <= m_upperLimit)
     240        {
     241//              if (hingeAngle <= m_lowerLimit*m_limitSoftness)
     242                if (hingeAngle <= m_lowerLimit)
     243                {
     244                        m_correction = (m_lowerLimit - hingeAngle);
     245                        m_limitSign = 1.0f;
     246                        m_solveLimit = true;
     247                }
     248//              else if (hingeAngle >= m_upperLimit*m_limitSoftness)
     249                else if (hingeAngle >= m_upperLimit)
     250                {
     251                        m_correction = m_upperLimit - hingeAngle;
     252                        m_limitSign = -1.0f;
     253                        m_solveLimit = true;
     254                }
     255        }
     256
     257        //Compute K = J*W*J' for hinge axis
     258        btVector3 axisA =  getRigidBodyA().getCenterOfMassTransform().getBasis() *  m_rbAFrame.getBasis().getColumn(2);
     259        m_kHinge =   1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
     260                                     getRigidBodyB().computeAngularImpulseDenominator(axisA));
     261
     262}
     263
     264void    btHingeConstraint::solveConstraint(btScalar     timeStep)
     265{
     266
     267        btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
     268        btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
     269
     270        btScalar tau = btScalar(0.3);
     271
     272        //linear part
     273        if (!m_angularOnly)
     274        {
     275                btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
     276                btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
     277
     278                btVector3 vel1 = m_rbA.getVelocityInLocalPoint(rel_pos1);
     279                btVector3 vel2 = m_rbB.getVelocityInLocalPoint(rel_pos2);
     280                btVector3 vel = vel1 - vel2;
     281
     282                for (int i=0;i<3;i++)
     283                {               
     284                        const btVector3& normal = m_jac[i].m_linearJointAxis;
     285                        btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
     286
     287                        btScalar rel_vel;
     288                        rel_vel = normal.dot(vel);
     289                        //positional error (zeroth order error)
     290                        btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
     291                        btScalar impulse = depth*tau/timeStep  * jacDiagABInv -  rel_vel * jacDiagABInv;
     292                        m_appliedImpulse += impulse;
     293                        btVector3 impulse_vector = normal * impulse;
     294                        m_rbA.applyImpulse(impulse_vector, pivotAInW - m_rbA.getCenterOfMassPosition());
     295                        m_rbB.applyImpulse(-impulse_vector, pivotBInW - m_rbB.getCenterOfMassPosition());
     296                }
     297        }
     298
     299       
     300        {
     301                ///solve angular part
     302
     303                // get axes in world space
     304                btVector3 axisA =  getRigidBodyA().getCenterOfMassTransform().getBasis() *  m_rbAFrame.getBasis().getColumn(2);
     305                btVector3 axisB =  getRigidBodyB().getCenterOfMassTransform().getBasis() *  m_rbBFrame.getBasis().getColumn(2);
     306
     307                const btVector3& angVelA = getRigidBodyA().getAngularVelocity();
     308                const btVector3& angVelB = getRigidBodyB().getAngularVelocity();
     309
     310                btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA);
     311                btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB);
     312
     313                btVector3 angAorthog = angVelA - angVelAroundHingeAxisA;
     314                btVector3 angBorthog = angVelB - angVelAroundHingeAxisB;
     315                btVector3 velrelOrthog = angAorthog-angBorthog;
     316                {
     317                        //solve orthogonal angular velocity correction
     318                        btScalar relaxation = btScalar(1.);
     319                        btScalar len = velrelOrthog.length();
     320                        if (len > btScalar(0.00001))
     321                        {
     322                                btVector3 normal = velrelOrthog.normalized();
     323                                btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) +
     324                                        getRigidBodyB().computeAngularImpulseDenominator(normal);
     325                                // scale for mass and relaxation
     326                                velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor;
    212327                        }
    213                 }
    214 
    215                 //calculate two perpendicular jointAxis, orthogonal to hingeAxis
    216                 //these two jointAxis require equal angular velocities for both bodies
    217 
    218                 //this is unused for now, it's a todo
    219                 btVector3 jointAxis0local;
    220                 btVector3 jointAxis1local;
    221                
    222                 btPlaneSpace1(m_rbAFrame.getBasis().getColumn(2),jointAxis0local,jointAxis1local);
    223 
    224                 getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
    225                 btVector3 jointAxis0 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis0local;
    226                 btVector3 jointAxis1 = getRigidBodyA().getCenterOfMassTransform().getBasis() * jointAxis1local;
    227                 btVector3 hingeAxisWorld = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(2);
     328
     329                        //solve angular positional correction
     330                        btVector3 angularError = -axisA.cross(axisB) *(btScalar(1.)/timeStep);
     331                        btScalar len2 = angularError.length();
     332                        if (len2>btScalar(0.00001))
     333                        {
     334                                btVector3 normal2 = angularError.normalized();
     335                                btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) +
     336                                                getRigidBodyB().computeAngularImpulseDenominator(normal2);
     337                                angularError *= (btScalar(1.)/denom2) * relaxation;
     338                        }
     339
     340                        m_rbA.applyTorqueImpulse(-velrelOrthog+angularError);
     341                        m_rbB.applyTorqueImpulse(velrelOrthog-angularError);
     342
     343                        // solve limit
     344                        if (m_solveLimit)
     345                        {
     346                                btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor  ) * m_limitSign;
     347
     348                                btScalar impulseMag = amplitude * m_kHinge;
     349
     350                                // Clamp the accumulated impulse
     351                                btScalar temp = m_accLimitImpulse;
     352                                m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) );
     353                                impulseMag = m_accLimitImpulse - temp;
     354
     355
     356                                btVector3 impulse = axisA * impulseMag * m_limitSign;
     357                                m_rbA.applyTorqueImpulse(impulse);
     358                                m_rbB.applyTorqueImpulse(-impulse);
     359                        }
     360                }
     361
     362                //apply motor
     363                if (m_enableAngularMotor)
     364                {
     365                        //todo: add limits too
     366                        btVector3 angularLimit(0,0,0);
     367
     368                        btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB;
     369                        btScalar projRelVel = velrel.dot(axisA);
     370
     371                        btScalar desiredMotorVel = m_motorTargetVelocity;
     372                        btScalar motor_relvel = desiredMotorVel - projRelVel;
     373
     374                        btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;;
     375                        //todo: should clip against accumulated impulse
     376                        btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse;
     377                        clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse;
     378                        btVector3 motorImp = clippedMotorImpulse * axisA;
     379
     380                        m_rbA.applyTorqueImpulse(motorImp+angularLimit);
     381                        m_rbB.applyTorqueImpulse(-motorImp-angularLimit);
    228382                       
    229                 new (&m_jacAng[0])      btJacobianEntry(jointAxis0,
    230                         m_rbA.getCenterOfMassTransform().getBasis().transpose(),
    231                         m_rbB.getCenterOfMassTransform().getBasis().transpose(),
    232                         m_rbA.getInvInertiaDiagLocal(),
    233                         m_rbB.getInvInertiaDiagLocal());
    234 
    235                 new (&m_jacAng[1])      btJacobianEntry(jointAxis1,
    236                         m_rbA.getCenterOfMassTransform().getBasis().transpose(),
    237                         m_rbB.getCenterOfMassTransform().getBasis().transpose(),
    238                         m_rbA.getInvInertiaDiagLocal(),
    239                         m_rbB.getInvInertiaDiagLocal());
    240 
    241                 new (&m_jacAng[2])      btJacobianEntry(hingeAxisWorld,
    242                         m_rbA.getCenterOfMassTransform().getBasis().transpose(),
    243                         m_rbB.getCenterOfMassTransform().getBasis().transpose(),
    244                         m_rbA.getInvInertiaDiagLocal(),
    245                         m_rbB.getInvInertiaDiagLocal());
    246 
    247                         // clear accumulator
    248                         m_accLimitImpulse = btScalar(0.);
    249 
    250                         // test angular limit
    251                         testLimit();
    252 
    253                 //Compute K = J*W*J' for hinge axis
    254                 btVector3 axisA =  getRigidBodyA().getCenterOfMassTransform().getBasis() *  m_rbAFrame.getBasis().getColumn(2);
    255                 m_kHinge =   1.0f / (getRigidBodyA().computeAngularImpulseDenominator(axisA) +
    256                                                          getRigidBodyB().computeAngularImpulseDenominator(axisA));
    257 
     383                }
    258384        }
    259 }
    260 
    261 //-----------------------------------------------------------------------------
    262 
    263 void btHingeConstraint::getInfo1(btConstraintInfo1* info)
    264 {
    265         if (m_useSolveConstraintObsolete)
    266         {
    267                 info->m_numConstraintRows = 0;
    268                 info->nub = 0;
    269         }
    270         else
    271         {
    272                 info->m_numConstraintRows = 5; // Fixed 3 linear + 2 angular
    273                 info->nub = 1;
    274                 //prepare constraint
    275                 testLimit();
    276                 if(getSolveLimit() || getEnableAngularMotor())
    277                 {
    278                         info->m_numConstraintRows++; // limit 3rd anguar as well
    279                         info->nub--;
    280                 }
    281         }
    282 } // btHingeConstraint::getInfo1 ()
    283 
    284 //-----------------------------------------------------------------------------
    285 
    286 void btHingeConstraint::getInfo2 (btConstraintInfo2* info)
    287 {
    288         btAssert(!m_useSolveConstraintObsolete);
    289         int i, s = info->rowskip;
    290         // transforms in world space
    291         btTransform trA = m_rbA.getCenterOfMassTransform()*m_rbAFrame;
    292         btTransform trB = m_rbB.getCenterOfMassTransform()*m_rbBFrame;
    293         // pivot point
    294         btVector3 pivotAInW = trA.getOrigin();
    295         btVector3 pivotBInW = trB.getOrigin();
    296         // linear (all fixed)
    297     info->m_J1linearAxis[0] = 1;
    298     info->m_J1linearAxis[s + 1] = 1;
    299     info->m_J1linearAxis[2 * s + 2] = 1;
    300         btVector3 a1 = pivotAInW - m_rbA.getCenterOfMassTransform().getOrigin();
    301         {
    302                 btVector3* angular0 = (btVector3*)(info->m_J1angularAxis);
    303                 btVector3* angular1 = (btVector3*)(info->m_J1angularAxis + s);
    304                 btVector3* angular2 = (btVector3*)(info->m_J1angularAxis + 2 * s);
    305                 btVector3 a1neg = -a1;
    306                 a1neg.getSkewSymmetricMatrix(angular0,angular1,angular2);
    307         }
    308         btVector3 a2 = pivotBInW - m_rbB.getCenterOfMassTransform().getOrigin();
    309         {
    310                 btVector3* angular0 = (btVector3*)(info->m_J2angularAxis);
    311                 btVector3* angular1 = (btVector3*)(info->m_J2angularAxis + s);
    312                 btVector3* angular2 = (btVector3*)(info->m_J2angularAxis + 2 * s);
    313                 a2.getSkewSymmetricMatrix(angular0,angular1,angular2);
    314         }
    315         // linear RHS
    316     btScalar k = info->fps * info->erp;
    317         for(i = 0; i < 3; i++)
    318     {
    319         info->m_constraintError[i * s] = k * (pivotBInW[i] - pivotAInW[i]);
    320     }
    321         // make rotations around X and Y equal
    322         // the hinge axis should be the only unconstrained
    323         // rotational axis, the angular velocity of the two bodies perpendicular to
    324         // the hinge axis should be equal. thus the constraint equations are
    325         //    p*w1 - p*w2 = 0
    326         //    q*w1 - q*w2 = 0
    327         // where p and q are unit vectors normal to the hinge axis, and w1 and w2
    328         // are the angular velocity vectors of the two bodies.
    329         // get hinge axis (Z)
    330         btVector3 ax1 = trA.getBasis().getColumn(2);
    331         // get 2 orthos to hinge axis (X, Y)
    332         btVector3 p = trA.getBasis().getColumn(0);
    333         btVector3 q = trA.getBasis().getColumn(1);
    334         // set the two hinge angular rows
    335     int s3 = 3 * info->rowskip;
    336     int s4 = 4 * info->rowskip;
    337 
    338         info->m_J1angularAxis[s3 + 0] = p[0];
    339         info->m_J1angularAxis[s3 + 1] = p[1];
    340         info->m_J1angularAxis[s3 + 2] = p[2];
    341         info->m_J1angularAxis[s4 + 0] = q[0];
    342         info->m_J1angularAxis[s4 + 1] = q[1];
    343         info->m_J1angularAxis[s4 + 2] = q[2];
    344 
    345         info->m_J2angularAxis[s3 + 0] = -p[0];
    346         info->m_J2angularAxis[s3 + 1] = -p[1];
    347         info->m_J2angularAxis[s3 + 2] = -p[2];
    348         info->m_J2angularAxis[s4 + 0] = -q[0];
    349         info->m_J2angularAxis[s4 + 1] = -q[1];
    350         info->m_J2angularAxis[s4 + 2] = -q[2];
    351     // compute the right hand side of the constraint equation. set relative
    352     // body velocities along p and q to bring the hinge back into alignment.
    353     // if ax1,ax2 are the unit length hinge axes as computed from body1 and
    354     // body2, we need to rotate both bodies along the axis u = (ax1 x ax2).
    355     // if `theta' is the angle between ax1 and ax2, we need an angular velocity
    356     // along u to cover angle erp*theta in one step :
    357     //   |angular_velocity| = angle/time = erp*theta / stepsize
    358     //                      = (erp*fps) * theta
    359     //    angular_velocity  = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2|
    360     //                      = (erp*fps) * theta * (ax1 x ax2) / sin(theta)
    361     // ...as ax1 and ax2 are unit length. if theta is smallish,
    362     // theta ~= sin(theta), so
    363     //    angular_velocity  = (erp*fps) * (ax1 x ax2)
    364     // ax1 x ax2 is in the plane space of ax1, so we project the angular
    365     // velocity to p and q to find the right hand side.
    366     btVector3 ax2 = trB.getBasis().getColumn(2);
    367         btVector3 u = ax1.cross(ax2);
    368         info->m_constraintError[s3] = k * u.dot(p);
    369         info->m_constraintError[s4] = k * u.dot(q);
    370         // check angular limits
    371         int nrow = 4; // last filled row
    372         int srow;
    373         btScalar limit_err = btScalar(0.0);
    374         int limit = 0;
    375         if(getSolveLimit())
    376         {
    377                 limit_err = m_correction * m_referenceSign;
    378                 limit = (limit_err > btScalar(0.0)) ? 1 : 2;
    379         }
    380         // if the hinge has joint limits or motor, add in the extra row
    381         int powered = 0;
    382         if(getEnableAngularMotor())
    383         {
    384                 powered = 1;
    385         }
    386         if(limit || powered)
    387         {
    388                 nrow++;
    389                 srow = nrow * info->rowskip;
    390                 info->m_J1angularAxis[srow+0] = ax1[0];
    391                 info->m_J1angularAxis[srow+1] = ax1[1];
    392                 info->m_J1angularAxis[srow+2] = ax1[2];
    393 
    394                 info->m_J2angularAxis[srow+0] = -ax1[0];
    395                 info->m_J2angularAxis[srow+1] = -ax1[1];
    396                 info->m_J2angularAxis[srow+2] = -ax1[2];
    397 
    398                 btScalar lostop = getLowerLimit();
    399                 btScalar histop = getUpperLimit();
    400                 if(limit && (lostop == histop))
    401                 {  // the joint motor is ineffective
    402                         powered = 0;
    403                 }
    404                 info->m_constraintError[srow] = btScalar(0.0f);
    405                 if(powered)
    406                 {
    407             info->cfm[srow] = btScalar(0.0);
    408                         btScalar mot_fact = getMotorFactor(m_hingeAngle, lostop, histop, m_motorTargetVelocity, info->fps * info->erp);
    409                         info->m_constraintError[srow] += mot_fact * m_motorTargetVelocity * m_referenceSign;
    410                         info->m_lowerLimit[srow] = - m_maxMotorImpulse;
    411                         info->m_upperLimit[srow] =   m_maxMotorImpulse;
    412                 }
    413                 if(limit)
    414                 {
    415                         k = info->fps * info->erp;
    416                         info->m_constraintError[srow] += k * limit_err;
    417                         info->cfm[srow] = btScalar(0.0);
    418                         if(lostop == histop)
    419                         {
    420                                 // limited low and high simultaneously
    421                                 info->m_lowerLimit[srow] = -SIMD_INFINITY;
    422                                 info->m_upperLimit[srow] = SIMD_INFINITY;
    423                         }
    424                         else if(limit == 1)
    425                         { // low limit
    426                                 info->m_lowerLimit[srow] = 0;
    427                                 info->m_upperLimit[srow] = SIMD_INFINITY;
    428                         }
    429                         else
    430                         { // high limit
    431                                 info->m_lowerLimit[srow] = -SIMD_INFINITY;
    432                                 info->m_upperLimit[srow] = 0;
    433                         }
    434                         // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that)
    435                         btScalar bounce = m_relaxationFactor;
    436                         if(bounce > btScalar(0.0))
    437                         {
    438                                 btScalar vel = m_rbA.getAngularVelocity().dot(ax1);
    439                                 vel -= m_rbB.getAngularVelocity().dot(ax1);
    440                                 // only apply bounce if the velocity is incoming, and if the
    441                                 // resulting c[] exceeds what we already have.
    442                                 if(limit == 1)
    443                                 {       // low limit
    444                                         if(vel < 0)
    445                                         {
    446                                                 btScalar newc = -bounce * vel;
    447                                                 if(newc > info->m_constraintError[srow])
    448                                                 {
    449                                                         info->m_constraintError[srow] = newc;
    450                                                 }
    451                                         }
    452                                 }
    453                                 else
    454                                 {       // high limit - all those computations are reversed
    455                                         if(vel > 0)
    456                                         {
    457                                                 btScalar newc = -bounce * vel;
    458                                                 if(newc < info->m_constraintError[srow])
    459                                                 {
    460                                                         info->m_constraintError[srow] = newc;
    461                                                 }
    462                                         }
    463                                 }
    464                         }
    465                         info->m_constraintError[srow] *= m_biasFactor;
    466                 } // if(limit)
    467         } // if angular limit or powered
    468 }
    469 
    470 //-----------------------------------------------------------------------------
    471 
    472 void    btHingeConstraint::solveConstraintObsolete(btSolverBody& bodyA,btSolverBody& bodyB,btScalar     timeStep)
    473 {
    474 
    475         ///for backwards compatibility during the transition to 'getInfo/getInfo2'
    476         if (m_useSolveConstraintObsolete)
    477         {
    478 
    479                 btVector3 pivotAInW = m_rbA.getCenterOfMassTransform()*m_rbAFrame.getOrigin();
    480                 btVector3 pivotBInW = m_rbB.getCenterOfMassTransform()*m_rbBFrame.getOrigin();
    481 
    482                 btScalar tau = btScalar(0.3);
    483 
    484                 //linear part
    485                 if (!m_angularOnly)
    486                 {
    487                         btVector3 rel_pos1 = pivotAInW - m_rbA.getCenterOfMassPosition();
    488                         btVector3 rel_pos2 = pivotBInW - m_rbB.getCenterOfMassPosition();
    489 
    490                         btVector3 vel1,vel2;
    491                         bodyA.getVelocityInLocalPointObsolete(rel_pos1,vel1);
    492                         bodyB.getVelocityInLocalPointObsolete(rel_pos2,vel2);
    493                         btVector3 vel = vel1 - vel2;
    494 
    495                         for (int i=0;i<3;i++)
    496                         {               
    497                                 const btVector3& normal = m_jac[i].m_linearJointAxis;
    498                                 btScalar jacDiagABInv = btScalar(1.) / m_jac[i].getDiagonal();
    499 
    500                                 btScalar rel_vel;
    501                                 rel_vel = normal.dot(vel);
    502                                 //positional error (zeroth order error)
    503                                 btScalar depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal
    504                                 btScalar impulse = depth*tau/timeStep  * jacDiagABInv -  rel_vel * jacDiagABInv;
    505                                 m_appliedImpulse += impulse;
    506                                 btVector3 impulse_vector = normal * impulse;
    507                                 btVector3 ftorqueAxis1 = rel_pos1.cross(normal);
    508                                 btVector3 ftorqueAxis2 = rel_pos2.cross(normal);
    509                                 bodyA.applyImpulse(normal*m_rbA.getInvMass(), m_rbA.getInvInertiaTensorWorld()*ftorqueAxis1,impulse);
    510                                 bodyB.applyImpulse(normal*m_rbB.getInvMass(), m_rbB.getInvInertiaTensorWorld()*ftorqueAxis2,-impulse);
    511                         }
    512                 }
    513 
    514                
    515                 {
    516                         ///solve angular part
    517 
    518                         // get axes in world space
    519                         btVector3 axisA =  getRigidBodyA().getCenterOfMassTransform().getBasis() *  m_rbAFrame.getBasis().getColumn(2);
    520                         btVector3 axisB =  getRigidBodyB().getCenterOfMassTransform().getBasis() *  m_rbBFrame.getBasis().getColumn(2);
    521 
    522                         btVector3 angVelA;
    523                         bodyA.getAngularVelocity(angVelA);
    524                         btVector3 angVelB;
    525                         bodyB.getAngularVelocity(angVelB);
    526 
    527                         btVector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA);
    528                         btVector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB);
    529 
    530                         btVector3 angAorthog = angVelA - angVelAroundHingeAxisA;
    531                         btVector3 angBorthog = angVelB - angVelAroundHingeAxisB;
    532                         btVector3 velrelOrthog = angAorthog-angBorthog;
    533                         {
    534                                
    535 
    536                                 //solve orthogonal angular velocity correction
    537                                 btScalar relaxation = btScalar(1.);
    538                                 btScalar len = velrelOrthog.length();
    539                                 if (len > btScalar(0.00001))
    540                                 {
    541                                         btVector3 normal = velrelOrthog.normalized();
    542                                         btScalar denom = getRigidBodyA().computeAngularImpulseDenominator(normal) +
    543                                                 getRigidBodyB().computeAngularImpulseDenominator(normal);
    544                                         // scale for mass and relaxation
    545                                         //velrelOrthog *= (btScalar(1.)/denom) * m_relaxationFactor;
    546 
    547                                         bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*velrelOrthog,-(btScalar(1.)/denom));
    548                                         bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*velrelOrthog,(btScalar(1.)/denom));
    549 
    550                                 }
    551 
    552                                 //solve angular positional correction
    553                                 btVector3 angularError =  axisA.cross(axisB) *(btScalar(1.)/timeStep);
    554                                 btScalar len2 = angularError.length();
    555                                 if (len2>btScalar(0.00001))
    556                                 {
    557                                         btVector3 normal2 = angularError.normalized();
    558                                         btScalar denom2 = getRigidBodyA().computeAngularImpulseDenominator(normal2) +
    559                                                         getRigidBodyB().computeAngularImpulseDenominator(normal2);
    560                                         //angularError *= (btScalar(1.)/denom2) * relaxation;
    561                                        
    562                                         bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*angularError,(btScalar(1.)/denom2));
    563                                         bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*angularError,-(btScalar(1.)/denom2));
    564 
    565                                 }
    566                                
    567                                
    568 
    569 
    570 
    571                                 // solve limit
    572                                 if (m_solveLimit)
    573                                 {
    574                                         btScalar amplitude = ( (angVelB - angVelA).dot( axisA )*m_relaxationFactor + m_correction* (btScalar(1.)/timeStep)*m_biasFactor  ) * m_limitSign;
    575 
    576                                         btScalar impulseMag = amplitude * m_kHinge;
    577 
    578                                         // Clamp the accumulated impulse
    579                                         btScalar temp = m_accLimitImpulse;
    580                                         m_accLimitImpulse = btMax(m_accLimitImpulse + impulseMag, btScalar(0) );
    581                                         impulseMag = m_accLimitImpulse - temp;
    582 
    583 
    584                                        
    585                                         bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,impulseMag * m_limitSign);
    586                                         bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-(impulseMag * m_limitSign));
    587 
    588                                 }
    589                         }
    590 
    591                         //apply motor
    592                         if (m_enableAngularMotor)
    593                         {
    594                                 //todo: add limits too
    595                                 btVector3 angularLimit(0,0,0);
    596 
    597                                 btVector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB;
    598                                 btScalar projRelVel = velrel.dot(axisA);
    599 
    600                                 btScalar desiredMotorVel = m_motorTargetVelocity;
    601                                 btScalar motor_relvel = desiredMotorVel - projRelVel;
    602 
    603                                 btScalar unclippedMotorImpulse = m_kHinge * motor_relvel;;
    604                                 //todo: should clip against accumulated impulse
    605                                 btScalar clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse;
    606                                 clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse;
    607                                 btVector3 motorImp = clippedMotorImpulse * axisA;
    608                        
    609                                 bodyA.applyImpulse(btVector3(0,0,0), m_rbA.getInvInertiaTensorWorld()*axisA,clippedMotorImpulse);
    610                                 bodyB.applyImpulse(btVector3(0,0,0), m_rbB.getInvInertiaTensorWorld()*axisA,-clippedMotorImpulse);
    611                                
    612                         }
    613                 }
    614         }
    615 
    616 }
    617 
    618 //-----------------------------------------------------------------------------
     385
     386}
    619387
    620388void    btHingeConstraint::updateRHS(btScalar   timeStep)
     
    623391
    624392}
    625 
    626 //-----------------------------------------------------------------------------
    627393
    628394btScalar btHingeConstraint::getHingeAngle()
     
    631397        const btVector3 refAxis1  = getRigidBodyA().getCenterOfMassTransform().getBasis() * m_rbAFrame.getBasis().getColumn(1);
    632398        const btVector3 swingAxis = getRigidBodyB().getCenterOfMassTransform().getBasis() * m_rbBFrame.getBasis().getColumn(1);
    633         btScalar angle = btAtan2Fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
    634         return m_referenceSign * angle;
    635 }
    636 
    637 //-----------------------------------------------------------------------------
    638 
    639 void btHingeConstraint::testLimit()
    640 {
    641         // Compute limit information
    642         m_hingeAngle = getHingeAngle(); 
    643         m_correction = btScalar(0.);
    644         m_limitSign = btScalar(0.);
    645         m_solveLimit = false;
    646         if (m_lowerLimit <= m_upperLimit)
    647         {
    648                 if (m_hingeAngle <= m_lowerLimit)
    649                 {
    650                         m_correction = (m_lowerLimit - m_hingeAngle);
    651                         m_limitSign = 1.0f;
    652                         m_solveLimit = true;
    653                 }
    654                 else if (m_hingeAngle >= m_upperLimit)
    655                 {
    656                         m_correction = m_upperLimit - m_hingeAngle;
    657                         m_limitSign = -1.0f;
    658                         m_solveLimit = true;
    659                 }
    660         }
    661         return;
    662 } // btHingeConstraint::testLimit()
    663 
    664 //-----------------------------------------------------------------------------
    665 //-----------------------------------------------------------------------------
    666 //-----------------------------------------------------------------------------
     399
     400        return btAtan2Fast( swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)  );
     401}
     402
Note: See TracChangeset for help on using the changeset viewer.