00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
00105
00106
00107
00108 btScalar steering = wheel.m_steering;
00109
00110 btQuaternion steeringOrn(up,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
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
00192
00193
00194 btScalar hitDistance = param*raylen;
00195 wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius;
00196
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
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
00248
00249
00250
00251
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
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
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);
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
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
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
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
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
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
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
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;
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
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
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
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
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