btRaycastVehicle.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/
00003  *
00004  * Permission to use, copy, modify, distribute and sell this software
00005  * and its documentation for any purpose is hereby granted without fee,
00006  * provided that the above copyright notice appear in all copies.
00007  * Erwin Coumans makes no representations about the suitability 
00008  * of this software for any purpose.  
00009  * It is provided "as is" without express or implied warranty.
00010 */
00011 
00012 #include "LinearMath/btVector3.h"
00013 #include "btRaycastVehicle.h"
00014 
00015 #include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h"
00016 #include "BulletDynamics/ConstraintSolver/btJacobianEntry.h"
00017 #include "LinearMath/btQuaternion.h"
00018 #include "BulletDynamics/Dynamics/btDynamicsWorld.h"
00019 #include "btVehicleRaycaster.h"
00020 #include "btWheelInfo.h"
00021 #include "LinearMath/btMinMax.h"
00022 #include "LinearMath/btIDebugDraw.h"
00023 #include "BulletDynamics/ConstraintSolver/btContactConstraint.h"
00024 
00025 
00026 
00027 btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis,  btVehicleRaycaster* raycaster )
00028 :m_vehicleRaycaster(raycaster),
00029 m_pitchControl(btScalar(0.))
00030 {
00031         m_chassisBody = chassis;
00032         m_indexRightAxis = 0;
00033         m_indexUpAxis = 2;
00034         m_indexForwardAxis = 1;
00035         defaultInit(tuning);
00036 }
00037 
00038 
00039 void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning)
00040 {
00041         (void)tuning;
00042         m_currentVehicleSpeedKmHour = btScalar(0.);
00043         m_steeringValue = btScalar(0.);
00044         
00045 }
00046 
00047         
00048 
00049 btRaycastVehicle::~btRaycastVehicle()
00050 {
00051 }
00052 
00053 
00054 //
00055 // basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed
00056 //
00057 btWheelInfo&    btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel)
00058 {
00059 
00060         btWheelInfoConstructionInfo ci;
00061 
00062         ci.m_chassisConnectionCS = connectionPointCS;
00063         ci.m_wheelDirectionCS = wheelDirectionCS0;
00064         ci.m_wheelAxleCS = wheelAxleCS;
00065         ci.m_suspensionRestLength = suspensionRestLength;
00066         ci.m_wheelRadius = wheelRadius;
00067         ci.m_suspensionStiffness = tuning.m_suspensionStiffness;
00068         ci.m_wheelsDampingCompression = tuning.m_suspensionCompression;
00069         ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping;
00070         ci.m_frictionSlip = tuning.m_frictionSlip;
00071         ci.m_bIsFrontWheel = isFrontWheel;
00072         ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm;
00073         ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce;
00074 
00075         m_wheelInfo.push_back( btWheelInfo(ci));
00076         
00077         btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1];
00078         
00079         updateWheelTransformsWS( wheel , false );
00080         updateWheelTransform(getNumWheels()-1,false);
00081         return wheel;
00082 }
00083 
00084 
00085 
00086 
00087 const btTransform&      btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const
00088 {
00089         btAssert(wheelIndex < getNumWheels());
00090         const btWheelInfo& wheel = m_wheelInfo[wheelIndex];
00091         return wheel.m_worldTransform;
00092 
00093 }
00094 
00095 void    btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform)
00096 {
00097         
00098         btWheelInfo& wheel = m_wheelInfo[ wheelIndex ];
00099         updateWheelTransformsWS(wheel,interpolatedTransform);
00100         btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS;
00101         const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS;
00102         btVector3 fwd = up.cross(right);
00103         fwd = fwd.normalize();
00104 //      up = right.cross(fwd);
00105 //      up.normalize();
00106 
00107         //rotate around steering over de wheelAxleWS
00108         btScalar steering = wheel.m_steering;
00109         
00110         btQuaternion steeringOrn(up,steering);//wheel.m_steering);
00111         btMatrix3x3 steeringMat(steeringOrn);
00112 
00113         btQuaternion rotatingOrn(right,-wheel.m_rotation);
00114         btMatrix3x3 rotatingMat(rotatingOrn);
00115 
00116         btMatrix3x3 basis2(
00117                 right[0],fwd[0],up[0],
00118                 right[1],fwd[1],up[1],
00119                 right[2],fwd[2],up[2]
00120         );
00121         
00122         wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2);
00123         wheel.m_worldTransform.setOrigin(
00124                 wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength
00125         );
00126 }
00127 
00128 void btRaycastVehicle::resetSuspension()
00129 {
00130 
00131         int i;
00132         for (i=0;i<m_wheelInfo.size();  i++)
00133         {
00134                         btWheelInfo& wheel = m_wheelInfo[i];
00135                         wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
00136                         wheel.m_suspensionRelativeVelocity = btScalar(0.0);
00137                         
00138                         wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
00139                         //wheel_info.setContactFriction(btScalar(0.0));
00140                         wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
00141         }
00142 }
00143 
00144 void    btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform)
00145 {
00146         wheel.m_raycastInfo.m_isInContact = false;
00147 
00148         btTransform chassisTrans = getChassisWorldTransform();
00149         if (interpolatedTransform && (getRigidBody()->getMotionState()))
00150         {
00151                 getRigidBody()->getMotionState()->getWorldTransform(chassisTrans);
00152         }
00153 
00154         wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS );
00155         wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() *  wheel.m_wheelDirectionCS ;
00156         wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS;
00157 }
00158 
00159 btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel)
00160 {
00161         updateWheelTransformsWS( wheel,false);
00162 
00163         
00164         btScalar depth = -1;
00165         
00166         btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius;
00167 
00168         btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen);
00169         const btVector3& source = wheel.m_raycastInfo.m_hardPointWS;
00170         wheel.m_raycastInfo.m_contactPointWS = source + rayvector;
00171         const btVector3& target = wheel.m_raycastInfo.m_contactPointWS;
00172 
00173         btScalar param = btScalar(0.);
00174         
00175         btVehicleRaycaster::btVehicleRaycasterResult    rayResults;
00176 
00177         btAssert(m_vehicleRaycaster);
00178 
00179         void* object = m_vehicleRaycaster->castRay(source,target,rayResults);
00180 
00181         wheel.m_raycastInfo.m_groundObject = 0;
00182 
00183         if (object)
00184         {
00185                 param = rayResults.m_distFraction;
00186                 depth = raylen * rayResults.m_distFraction;
00187                 wheel.m_raycastInfo.m_contactNormalWS  = rayResults.m_hitNormalInWorld;
00188                 wheel.m_raycastInfo.m_isInContact = true;
00189                 
00190                 wheel.m_raycastInfo.m_groundObject = &getFixedBody();
00191                 //wheel.m_raycastInfo.m_groundObject = object;
00192 
00193 
00194                 btScalar hitDistance = param*raylen;
00195                 wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
00196                 //clamp on max suspension travel
00197 
00198                 btScalar  minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01);
00199                 btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01);
00200                 if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength)
00201                 {
00202                         wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength;
00203                 }
00204                 if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength)
00205                 {
00206                         wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength;
00207                 }
00208 
00209                 wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld;
00210 
00211                 btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS );
00212 
00213                 btVector3 chassis_velocity_at_contactPoint;
00214                 btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition();
00215 
00216                 chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos);
00217 
00218                 btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint );
00219 
00220                 if ( denominator >= btScalar(-0.1))
00221                 {
00222                         wheel.m_suspensionRelativeVelocity = btScalar(0.0);
00223                         wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1);
00224                 }
00225                 else
00226                 {
00227                         btScalar inv = btScalar(-1.) / denominator;
00228                         wheel.m_suspensionRelativeVelocity = projVel * inv;
00229                         wheel.m_clippedInvContactDotSuspension = inv;
00230                 }
00231                         
00232         } else
00233         {
00234                 //put wheel info as in rest position
00235                 wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength();
00236                 wheel.m_suspensionRelativeVelocity = btScalar(0.0);
00237                 wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS;
00238                 wheel.m_clippedInvContactDotSuspension = btScalar(1.0);
00239         }
00240 
00241         return depth;
00242 }
00243 
00244 
00245 const btTransform& btRaycastVehicle::getChassisWorldTransform() const
00246 {
00247         /*if (getRigidBody()->getMotionState())
00248         {
00249                 btTransform chassisWorldTrans;
00250                 getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans);
00251                 return chassisWorldTrans;
00252         }
00253         */
00254 
00255         
00256         return getRigidBody()->getCenterOfMassTransform();
00257 }
00258 
00259 
00260 void btRaycastVehicle::updateVehicle( btScalar step )
00261 {
00262         {
00263                 for (int i=0;i<getNumWheels();i++)
00264                 {
00265                         updateWheelTransform(i,false);
00266                 }
00267         }
00268 
00269 
00270         m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length();
00271         
00272         const btTransform& chassisTrans = getChassisWorldTransform();
00273 
00274         btVector3 forwardW (
00275                 chassisTrans.getBasis()[0][m_indexForwardAxis],
00276                 chassisTrans.getBasis()[1][m_indexForwardAxis],
00277                 chassisTrans.getBasis()[2][m_indexForwardAxis]);
00278 
00279         if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.))
00280         {
00281                 m_currentVehicleSpeedKmHour *= btScalar(-1.);
00282         }
00283 
00284         //
00285         // simulate suspension
00286         //
00287         
00288         int i=0;
00289         for (i=0;i<m_wheelInfo.size();i++)
00290         {
00291                 btScalar depth; 
00292                 depth = rayCast( m_wheelInfo[i]);
00293         }
00294 
00295         updateSuspension(step);
00296 
00297         
00298         for (i=0;i<m_wheelInfo.size();i++)
00299         {
00300                 //apply suspension force
00301                 btWheelInfo& wheel = m_wheelInfo[i];
00302                 
00303                 btScalar suspensionForce = wheel.m_wheelsSuspensionForce;
00304                 
00305                 if (suspensionForce > wheel.m_maxSuspensionForce)
00306                 {
00307                         suspensionForce = wheel.m_maxSuspensionForce;
00308                 }
00309                 btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step;
00310                 btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition();
00311                 
00312                 getRigidBody()->applyImpulse(impulse, relpos);
00313         
00314         }
00315         
00316 
00317         
00318         updateFriction( step);
00319 
00320         
00321         for (i=0;i<m_wheelInfo.size();i++)
00322         {
00323                 btWheelInfo& wheel = m_wheelInfo[i];
00324                 btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition();
00325                 btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos );
00326 
00327                 if (wheel.m_raycastInfo.m_isInContact)
00328                 {
00329                         const btTransform&      chassisWorldTransform = getChassisWorldTransform();
00330 
00331                         btVector3 fwd (
00332                                 chassisWorldTransform.getBasis()[0][m_indexForwardAxis],
00333                                 chassisWorldTransform.getBasis()[1][m_indexForwardAxis],
00334                                 chassisWorldTransform.getBasis()[2][m_indexForwardAxis]);
00335 
00336                         btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS);
00337                         fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj;
00338 
00339                         btScalar proj2 = fwd.dot(vel);
00340                         
00341                         wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius);
00342                         wheel.m_rotation += wheel.m_deltaRotation;
00343 
00344                 } else
00345                 {
00346                         wheel.m_rotation += wheel.m_deltaRotation;
00347                 }
00348                 
00349                 wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact
00350 
00351         }
00352 
00353 
00354 
00355 }
00356 
00357 
00358 void    btRaycastVehicle::setSteeringValue(btScalar steering,int wheel)
00359 {
00360         btAssert(wheel>=0 && wheel < getNumWheels());
00361 
00362         btWheelInfo& wheelInfo = getWheelInfo(wheel);
00363         wheelInfo.m_steering = steering;
00364 }
00365 
00366 
00367 
00368 btScalar        btRaycastVehicle::getSteeringValue(int wheel) const
00369 {
00370         return getWheelInfo(wheel).m_steering;
00371 }
00372 
00373 
00374 void    btRaycastVehicle::applyEngineForce(btScalar force, int wheel)
00375 {
00376         btAssert(wheel>=0 && wheel < getNumWheels());
00377         btWheelInfo& wheelInfo = getWheelInfo(wheel);
00378         wheelInfo.m_engineForce = force;
00379 }
00380 
00381 
00382 const btWheelInfo&      btRaycastVehicle::getWheelInfo(int index) const
00383 {
00384         btAssert((index >= 0) && (index <       getNumWheels()));
00385         
00386         return m_wheelInfo[index];
00387 }
00388 
00389 btWheelInfo&    btRaycastVehicle::getWheelInfo(int index) 
00390 {
00391         btAssert((index >= 0) && (index <       getNumWheels()));
00392         
00393         return m_wheelInfo[index];
00394 }
00395 
00396 void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex)
00397 {
00398         btAssert((wheelIndex >= 0) && (wheelIndex <     getNumWheels()));
00399         getWheelInfo(wheelIndex).m_brake = brake;
00400 }
00401 
00402 
00403 void    btRaycastVehicle::updateSuspension(btScalar deltaTime)
00404 {
00405         (void)deltaTime;
00406 
00407         btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass();
00408         
00409         for (int w_it=0; w_it<getNumWheels(); w_it++)
00410         {
00411                 btWheelInfo &wheel_info = m_wheelInfo[w_it];
00412                 
00413                 if ( wheel_info.m_raycastInfo.m_isInContact )
00414                 {
00415                         btScalar force;
00416                         //      Spring
00417                         {
00418                                 btScalar        susp_length                     = wheel_info.getSuspensionRestLength();
00419                                 btScalar        current_length = wheel_info.m_raycastInfo.m_suspensionLength;
00420 
00421                                 btScalar length_diff = (susp_length - current_length);
00422 
00423                                 force = wheel_info.m_suspensionStiffness
00424                                         * length_diff * wheel_info.m_clippedInvContactDotSuspension;
00425                         }
00426                 
00427                         // Damper
00428                         {
00429                                 btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity;
00430                                 {
00431                                         btScalar        susp_damping;
00432                                         if ( projected_rel_vel < btScalar(0.0) )
00433                                         {
00434                                                 susp_damping = wheel_info.m_wheelsDampingCompression;
00435                                         }
00436                                         else
00437                                         {
00438                                                 susp_damping = wheel_info.m_wheelsDampingRelaxation;
00439                                         }
00440                                         force -= susp_damping * projected_rel_vel;
00441                                 }
00442                         }
00443 
00444                         // RESULT
00445                         wheel_info.m_wheelsSuspensionForce = force * chassisMass;
00446                         if (wheel_info.m_wheelsSuspensionForce < btScalar(0.))
00447                         {
00448                                 wheel_info.m_wheelsSuspensionForce = btScalar(0.);
00449                         }
00450                 }
00451                 else
00452                 {
00453                         wheel_info.m_wheelsSuspensionForce = btScalar(0.0);
00454                 }
00455         }
00456 
00457 }
00458 
00459 
00460 struct btWheelContactPoint
00461 {
00462         btRigidBody* m_body0;
00463         btRigidBody* m_body1;
00464         btVector3       m_frictionPositionWorld;
00465         btVector3       m_frictionDirectionWorld;
00466         btScalar        m_jacDiagABInv;
00467         btScalar        m_maxImpulse;
00468 
00469 
00470         btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse)
00471                 :m_body0(body0),
00472                 m_body1(body1),
00473                 m_frictionPositionWorld(frictionPosWorld),
00474                 m_frictionDirectionWorld(frictionDirectionWorld),
00475                 m_maxImpulse(maxImpulse)
00476         {
00477                 btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
00478                 btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld);
00479                 btScalar        relaxation = 1.f;
00480                 m_jacDiagABInv = relaxation/(denom0+denom1);
00481         }
00482 
00483 
00484 
00485 };
00486 
00487 btScalar calcRollingFriction(btWheelContactPoint& contactPoint);
00488 btScalar calcRollingFriction(btWheelContactPoint& contactPoint)
00489 {
00490 
00491         btScalar j1=0.f;
00492 
00493         const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld;
00494 
00495         btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); 
00496         btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition();
00497         
00498         btScalar maxImpulse  = contactPoint.m_maxImpulse;
00499         
00500         btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1);
00501         btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2);
00502         btVector3 vel = vel1 - vel2;
00503 
00504         btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel);
00505 
00506         // calculate j that moves us to zero relative velocity
00507         j1 = -vrel * contactPoint.m_jacDiagABInv;
00508         btSetMin(j1, maxImpulse);
00509         btSetMax(j1, -maxImpulse);
00510 
00511         return j1;
00512 }
00513 
00514 
00515 
00516 
00517 btScalar sideFrictionStiffness2 = btScalar(1.0);
00518 void    btRaycastVehicle::updateFriction(btScalar       timeStep)
00519 {
00520 
00521                 //calculate the impulse, so that the wheels don't move sidewards
00522                 int numWheel = getNumWheels();
00523                 if (!numWheel)
00524                         return;
00525 
00526                 m_forwardWS.resize(numWheel);
00527                 m_axle.resize(numWheel);
00528                 m_forwardImpulse.resize(numWheel);
00529                 m_sideImpulse.resize(numWheel);
00530                 
00531                 int numWheelsOnGround = 0;
00532         
00533 
00534                 //collapse all those loops into one!
00535                 for (int i=0;i<getNumWheels();i++)
00536                 {
00537                         btWheelInfo& wheelInfo = m_wheelInfo[i];
00538                         class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
00539                         if (groundObject)
00540                                 numWheelsOnGround++;
00541                         m_sideImpulse[i] = btScalar(0.);
00542                         m_forwardImpulse[i] = btScalar(0.);
00543 
00544                 }
00545         
00546                 {
00547         
00548                         for (int i=0;i<getNumWheels();i++)
00549                         {
00550 
00551                                 btWheelInfo& wheelInfo = m_wheelInfo[i];
00552                                         
00553                                 class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
00554 
00555                                 if (groundObject)
00556                                 {
00557 
00558                                         const btTransform& wheelTrans = getWheelTransformWS( i );
00559 
00560                                         btMatrix3x3 wheelBasis0 = wheelTrans.getBasis();
00561                                         m_axle[i] = btVector3(  
00562                                                 wheelBasis0[0][m_indexRightAxis],
00563                                                 wheelBasis0[1][m_indexRightAxis],
00564                                                 wheelBasis0[2][m_indexRightAxis]);
00565                                         
00566                                         const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS;
00567                                         btScalar proj = m_axle[i].dot(surfNormalWS);
00568                                         m_axle[i] -= surfNormalWS * proj;
00569                                         m_axle[i] = m_axle[i].normalize();
00570                                         
00571                                         m_forwardWS[i] = surfNormalWS.cross(m_axle[i]);
00572                                         m_forwardWS[i].normalize();
00573 
00574                                 
00575                                         resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS,
00576                                                           *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS,
00577                                                           btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep);
00578 
00579                                         m_sideImpulse[i] *= sideFrictionStiffness2;
00580                                                 
00581                                 }
00582                                 
00583 
00584                         }
00585                 }
00586 
00587         btScalar sideFactor = btScalar(1.);
00588         btScalar fwdFactor = 0.5;
00589 
00590         bool sliding = false;
00591         {
00592                 for (int wheel =0;wheel <getNumWheels();wheel++)
00593                 {
00594                         btWheelInfo& wheelInfo = m_wheelInfo[wheel];
00595                         class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject;
00596 
00597                         btScalar        rollingFriction = 0.f;
00598 
00599                         if (groundObject)
00600                         {
00601                                 if (wheelInfo.m_engineForce != 0.f)
00602                                 {
00603                                         rollingFriction = wheelInfo.m_engineForce* timeStep;
00604                                 } else
00605                                 {
00606                                         btScalar defaultRollingFrictionImpulse = 0.f;
00607                                         btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse;
00608                                         btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse);
00609                                         rollingFriction = calcRollingFriction(contactPt);
00610                                 }
00611                         }
00612 
00613                         //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break)
00614                         
00615 
00616 
00617 
00618                         m_forwardImpulse[wheel] = btScalar(0.);
00619                         m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
00620 
00621                         if (groundObject)
00622                         {
00623                                 m_wheelInfo[wheel].m_skidInfo= btScalar(1.);
00624                                 
00625                                 btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip;
00626                                 btScalar maximpSide = maximp;
00627 
00628                                 btScalar maximpSquared = maximp * maximpSide;
00629                         
00630 
00631                                 m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep;
00632 
00633                                 btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor;
00634                                 btScalar y = (m_sideImpulse[wheel] ) * sideFactor;
00635                                 
00636                                 btScalar impulseSquared = (x*x + y*y);
00637 
00638                                 if (impulseSquared > maximpSquared)
00639                                 {
00640                                         sliding = true;
00641                                         
00642                                         btScalar factor = maximp / btSqrt(impulseSquared);
00643                                         
00644                                         m_wheelInfo[wheel].m_skidInfo *= factor;
00645                                 }
00646                         } 
00647 
00648                 }
00649         }
00650 
00651         
00652 
00653 
00654                 if (sliding)
00655                 {
00656                         for (int wheel = 0;wheel < getNumWheels(); wheel++)
00657                         {
00658                                 if (m_sideImpulse[wheel] != btScalar(0.))
00659                                 {
00660                                         if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.))
00661                                         {
00662                                                 m_forwardImpulse[wheel] *=      m_wheelInfo[wheel].m_skidInfo;
00663                                                 m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo;
00664                                         }
00665                                 }
00666                         }
00667                 }
00668 
00669                 // apply the impulses
00670                 {
00671                         for (int wheel = 0;wheel<getNumWheels() ; wheel++)
00672                         {
00673                                 btWheelInfo& wheelInfo = m_wheelInfo[wheel];
00674 
00675                                 btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - 
00676                                                 m_chassisBody->getCenterOfMassPosition();
00677 
00678                                 if (m_forwardImpulse[wheel] != btScalar(0.))
00679                                 {
00680                                         m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos);
00681                                 }
00682                                 if (m_sideImpulse[wheel] != btScalar(0.))
00683                                 {
00684                                         class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject;
00685 
00686                                         btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - 
00687                                                 groundObject->getCenterOfMassPosition();
00688 
00689                                         
00690                                         btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel];
00691 
00692                                         rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence;
00693                                         m_chassisBody->applyImpulse(sideImp,rel_pos);
00694 
00695                                         //apply friction impulse on the ground
00696                                         groundObject->applyImpulse(-sideImp,rel_pos2);
00697                                 }
00698                         }
00699                 }
00700 
00701         
00702 }
00703 
00704 
00705 
00706 void    btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer)
00707 {
00708 
00709         for (int v=0;v<this->getNumWheels();v++)
00710         {
00711                 btVector3 wheelColor(0,1,1);
00712                 if (getWheelInfo(v).m_raycastInfo.m_isInContact)
00713                 {
00714                         wheelColor.setValue(0,0,1);
00715                 } else
00716                 {
00717                         wheelColor.setValue(1,0,1);
00718                 }
00719 
00720                 btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin();
00721 
00722                 btVector3 axle = btVector3(     
00723                         getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()],
00724                         getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()],
00725                         getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]);
00726 
00727                 //debug wheels (cylinders)
00728                 debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor);
00729                 debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor);
00730 
00731         }
00732 }
00733 
00734 
00735 void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result)
00736 {
00737 //      RayResultCallback& resultCallback;
00738 
00739         btCollisionWorld::ClosestRayResultCallback rayCallback(from,to);
00740 
00741         m_dynamicsWorld->rayTest(from, to, rayCallback);
00742 
00743         if (rayCallback.hasHit())
00744         {
00745                 
00746                 btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject);
00747         if (body && body->hasContactResponse())
00748                 {
00749                         result.m_hitPointInWorld = rayCallback.m_hitPointWorld;
00750                         result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld;
00751                         result.m_hitNormalInWorld.normalize();
00752                         result.m_distFraction = rayCallback.m_closestHitFraction;
00753                         return body;
00754                 }
00755         }
00756         return 0;
00757 }
00758 

Generated on Mon Feb 15 22:17:05 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1