| [1963] | 1 | /* | 
|---|
|  | 2 | * Copyright (c) 2005 Erwin Coumans http://continuousphysics.com/Bullet/ | 
|---|
|  | 3 | * | 
|---|
|  | 4 | * Permission to use, copy, modify, distribute and sell this software | 
|---|
|  | 5 | * and its documentation for any purpose is hereby granted without fee, | 
|---|
|  | 6 | * provided that the above copyright notice appear in all copies. | 
|---|
|  | 7 | * Erwin Coumans makes no representations about the suitability | 
|---|
|  | 8 | * of this software for any purpose. | 
|---|
|  | 9 | * It is provided "as is" without express or implied warranty. | 
|---|
|  | 10 | */ | 
|---|
|  | 11 |  | 
|---|
|  | 12 | #include "LinearMath/btVector3.h" | 
|---|
|  | 13 | #include "btRaycastVehicle.h" | 
|---|
|  | 14 |  | 
|---|
|  | 15 | #include "BulletDynamics/ConstraintSolver/btSolve2LinearConstraint.h" | 
|---|
|  | 16 | #include "BulletDynamics/ConstraintSolver/btJacobianEntry.h" | 
|---|
|  | 17 | #include "LinearMath/btQuaternion.h" | 
|---|
|  | 18 | #include "BulletDynamics/Dynamics/btDynamicsWorld.h" | 
|---|
|  | 19 | #include "btVehicleRaycaster.h" | 
|---|
|  | 20 | #include "btWheelInfo.h" | 
|---|
|  | 21 | #include "LinearMath/btMinMax.h" | 
|---|
| [2882] | 22 | #include "LinearMath/btIDebugDraw.h" | 
|---|
| [1963] | 23 | #include "BulletDynamics/ConstraintSolver/btContactConstraint.h" | 
|---|
|  | 24 |  | 
|---|
| [8393] | 25 | #define ROLLING_INFLUENCE_FIX | 
|---|
|  | 26 |  | 
|---|
|  | 27 |  | 
|---|
| [8351] | 28 | btRigidBody& btActionInterface::getFixedBody() | 
|---|
|  | 29 | { | 
|---|
|  | 30 | static btRigidBody s_fixed(0, 0,0); | 
|---|
|  | 31 | s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.))); | 
|---|
|  | 32 | return s_fixed; | 
|---|
|  | 33 | } | 
|---|
| [1963] | 34 |  | 
|---|
|  | 35 | btRaycastVehicle::btRaycastVehicle(const btVehicleTuning& tuning,btRigidBody* chassis,  btVehicleRaycaster* raycaster ) | 
|---|
| [2882] | 36 | :m_vehicleRaycaster(raycaster), | 
|---|
| [1963] | 37 | m_pitchControl(btScalar(0.)) | 
|---|
|  | 38 | { | 
|---|
|  | 39 | m_chassisBody = chassis; | 
|---|
|  | 40 | m_indexRightAxis = 0; | 
|---|
|  | 41 | m_indexUpAxis = 2; | 
|---|
|  | 42 | m_indexForwardAxis = 1; | 
|---|
|  | 43 | defaultInit(tuning); | 
|---|
|  | 44 | } | 
|---|
|  | 45 |  | 
|---|
|  | 46 |  | 
|---|
|  | 47 | void btRaycastVehicle::defaultInit(const btVehicleTuning& tuning) | 
|---|
|  | 48 | { | 
|---|
|  | 49 | (void)tuning; | 
|---|
|  | 50 | m_currentVehicleSpeedKmHour = btScalar(0.); | 
|---|
|  | 51 | m_steeringValue = btScalar(0.); | 
|---|
|  | 52 |  | 
|---|
|  | 53 | } | 
|---|
|  | 54 |  | 
|---|
|  | 55 |  | 
|---|
|  | 56 |  | 
|---|
|  | 57 | btRaycastVehicle::~btRaycastVehicle() | 
|---|
|  | 58 | { | 
|---|
|  | 59 | } | 
|---|
|  | 60 |  | 
|---|
|  | 61 |  | 
|---|
|  | 62 | // | 
|---|
|  | 63 | // basically most of the code is general for 2 or 4 wheel vehicles, but some of it needs to be reviewed | 
|---|
|  | 64 | // | 
|---|
|  | 65 | btWheelInfo&    btRaycastVehicle::addWheel( const btVector3& connectionPointCS, const btVector3& wheelDirectionCS0,const btVector3& wheelAxleCS, btScalar suspensionRestLength, btScalar wheelRadius,const btVehicleTuning& tuning, bool isFrontWheel) | 
|---|
|  | 66 | { | 
|---|
|  | 67 |  | 
|---|
|  | 68 | btWheelInfoConstructionInfo ci; | 
|---|
|  | 69 |  | 
|---|
|  | 70 | ci.m_chassisConnectionCS = connectionPointCS; | 
|---|
|  | 71 | ci.m_wheelDirectionCS = wheelDirectionCS0; | 
|---|
|  | 72 | ci.m_wheelAxleCS = wheelAxleCS; | 
|---|
|  | 73 | ci.m_suspensionRestLength = suspensionRestLength; | 
|---|
|  | 74 | ci.m_wheelRadius = wheelRadius; | 
|---|
|  | 75 | ci.m_suspensionStiffness = tuning.m_suspensionStiffness; | 
|---|
|  | 76 | ci.m_wheelsDampingCompression = tuning.m_suspensionCompression; | 
|---|
|  | 77 | ci.m_wheelsDampingRelaxation = tuning.m_suspensionDamping; | 
|---|
|  | 78 | ci.m_frictionSlip = tuning.m_frictionSlip; | 
|---|
|  | 79 | ci.m_bIsFrontWheel = isFrontWheel; | 
|---|
|  | 80 | ci.m_maxSuspensionTravelCm = tuning.m_maxSuspensionTravelCm; | 
|---|
| [8351] | 81 | ci.m_maxSuspensionForce = tuning.m_maxSuspensionForce; | 
|---|
| [1963] | 82 |  | 
|---|
|  | 83 | m_wheelInfo.push_back( btWheelInfo(ci)); | 
|---|
|  | 84 |  | 
|---|
|  | 85 | btWheelInfo& wheel = m_wheelInfo[getNumWheels()-1]; | 
|---|
|  | 86 |  | 
|---|
|  | 87 | updateWheelTransformsWS( wheel , false ); | 
|---|
|  | 88 | updateWheelTransform(getNumWheels()-1,false); | 
|---|
|  | 89 | return wheel; | 
|---|
|  | 90 | } | 
|---|
|  | 91 |  | 
|---|
|  | 92 |  | 
|---|
|  | 93 |  | 
|---|
|  | 94 |  | 
|---|
|  | 95 | const btTransform&      btRaycastVehicle::getWheelTransformWS( int wheelIndex ) const | 
|---|
|  | 96 | { | 
|---|
| [2882] | 97 | btAssert(wheelIndex < getNumWheels()); | 
|---|
| [1963] | 98 | const btWheelInfo& wheel = m_wheelInfo[wheelIndex]; | 
|---|
|  | 99 | return wheel.m_worldTransform; | 
|---|
|  | 100 |  | 
|---|
|  | 101 | } | 
|---|
|  | 102 |  | 
|---|
|  | 103 | void    btRaycastVehicle::updateWheelTransform( int wheelIndex , bool interpolatedTransform) | 
|---|
|  | 104 | { | 
|---|
|  | 105 |  | 
|---|
|  | 106 | btWheelInfo& wheel = m_wheelInfo[ wheelIndex ]; | 
|---|
|  | 107 | updateWheelTransformsWS(wheel,interpolatedTransform); | 
|---|
|  | 108 | btVector3 up = -wheel.m_raycastInfo.m_wheelDirectionWS; | 
|---|
|  | 109 | const btVector3& right = wheel.m_raycastInfo.m_wheelAxleWS; | 
|---|
|  | 110 | btVector3 fwd = up.cross(right); | 
|---|
|  | 111 | fwd = fwd.normalize(); | 
|---|
|  | 112 | //      up = right.cross(fwd); | 
|---|
|  | 113 | //      up.normalize(); | 
|---|
|  | 114 |  | 
|---|
|  | 115 | //rotate around steering over de wheelAxleWS | 
|---|
|  | 116 | btScalar steering = wheel.m_steering; | 
|---|
|  | 117 |  | 
|---|
|  | 118 | btQuaternion steeringOrn(up,steering);//wheel.m_steering); | 
|---|
|  | 119 | btMatrix3x3 steeringMat(steeringOrn); | 
|---|
|  | 120 |  | 
|---|
|  | 121 | btQuaternion rotatingOrn(right,-wheel.m_rotation); | 
|---|
|  | 122 | btMatrix3x3 rotatingMat(rotatingOrn); | 
|---|
|  | 123 |  | 
|---|
|  | 124 | btMatrix3x3 basis2( | 
|---|
|  | 125 | right[0],fwd[0],up[0], | 
|---|
|  | 126 | right[1],fwd[1],up[1], | 
|---|
|  | 127 | right[2],fwd[2],up[2] | 
|---|
|  | 128 | ); | 
|---|
|  | 129 |  | 
|---|
|  | 130 | wheel.m_worldTransform.setBasis(steeringMat * rotatingMat * basis2); | 
|---|
|  | 131 | wheel.m_worldTransform.setOrigin( | 
|---|
|  | 132 | wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength | 
|---|
|  | 133 | ); | 
|---|
|  | 134 | } | 
|---|
|  | 135 |  | 
|---|
|  | 136 | void btRaycastVehicle::resetSuspension() | 
|---|
|  | 137 | { | 
|---|
|  | 138 |  | 
|---|
|  | 139 | int i; | 
|---|
|  | 140 | for (i=0;i<m_wheelInfo.size();  i++) | 
|---|
|  | 141 | { | 
|---|
|  | 142 | btWheelInfo& wheel = m_wheelInfo[i]; | 
|---|
|  | 143 | wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); | 
|---|
|  | 144 | wheel.m_suspensionRelativeVelocity = btScalar(0.0); | 
|---|
|  | 145 |  | 
|---|
|  | 146 | wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; | 
|---|
|  | 147 | //wheel_info.setContactFriction(btScalar(0.0)); | 
|---|
|  | 148 | wheel.m_clippedInvContactDotSuspension = btScalar(1.0); | 
|---|
|  | 149 | } | 
|---|
|  | 150 | } | 
|---|
|  | 151 |  | 
|---|
|  | 152 | void    btRaycastVehicle::updateWheelTransformsWS(btWheelInfo& wheel , bool interpolatedTransform) | 
|---|
|  | 153 | { | 
|---|
|  | 154 | wheel.m_raycastInfo.m_isInContact = false; | 
|---|
|  | 155 |  | 
|---|
|  | 156 | btTransform chassisTrans = getChassisWorldTransform(); | 
|---|
|  | 157 | if (interpolatedTransform && (getRigidBody()->getMotionState())) | 
|---|
|  | 158 | { | 
|---|
|  | 159 | getRigidBody()->getMotionState()->getWorldTransform(chassisTrans); | 
|---|
|  | 160 | } | 
|---|
|  | 161 |  | 
|---|
|  | 162 | wheel.m_raycastInfo.m_hardPointWS = chassisTrans( wheel.m_chassisConnectionPointCS ); | 
|---|
|  | 163 | wheel.m_raycastInfo.m_wheelDirectionWS = chassisTrans.getBasis() *  wheel.m_wheelDirectionCS ; | 
|---|
|  | 164 | wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.getBasis() * wheel.m_wheelAxleCS; | 
|---|
|  | 165 | } | 
|---|
|  | 166 |  | 
|---|
|  | 167 | btScalar btRaycastVehicle::rayCast(btWheelInfo& wheel) | 
|---|
|  | 168 | { | 
|---|
|  | 169 | updateWheelTransformsWS( wheel,false); | 
|---|
|  | 170 |  | 
|---|
|  | 171 |  | 
|---|
|  | 172 | btScalar depth = -1; | 
|---|
|  | 173 |  | 
|---|
|  | 174 | btScalar raylen = wheel.getSuspensionRestLength()+wheel.m_wheelsRadius; | 
|---|
|  | 175 |  | 
|---|
|  | 176 | btVector3 rayvector = wheel.m_raycastInfo.m_wheelDirectionWS * (raylen); | 
|---|
|  | 177 | const btVector3& source = wheel.m_raycastInfo.m_hardPointWS; | 
|---|
|  | 178 | wheel.m_raycastInfo.m_contactPointWS = source + rayvector; | 
|---|
|  | 179 | const btVector3& target = wheel.m_raycastInfo.m_contactPointWS; | 
|---|
|  | 180 |  | 
|---|
|  | 181 | btScalar param = btScalar(0.); | 
|---|
|  | 182 |  | 
|---|
|  | 183 | btVehicleRaycaster::btVehicleRaycasterResult    rayResults; | 
|---|
|  | 184 |  | 
|---|
| [2882] | 185 | btAssert(m_vehicleRaycaster); | 
|---|
| [1963] | 186 |  | 
|---|
|  | 187 | void* object = m_vehicleRaycaster->castRay(source,target,rayResults); | 
|---|
|  | 188 |  | 
|---|
|  | 189 | wheel.m_raycastInfo.m_groundObject = 0; | 
|---|
|  | 190 |  | 
|---|
|  | 191 | if (object) | 
|---|
|  | 192 | { | 
|---|
|  | 193 | param = rayResults.m_distFraction; | 
|---|
|  | 194 | depth = raylen * rayResults.m_distFraction; | 
|---|
|  | 195 | wheel.m_raycastInfo.m_contactNormalWS  = rayResults.m_hitNormalInWorld; | 
|---|
|  | 196 | wheel.m_raycastInfo.m_isInContact = true; | 
|---|
|  | 197 |  | 
|---|
| [8351] | 198 | wheel.m_raycastInfo.m_groundObject = &getFixedBody();///@todo for driving on dynamic/movable objects!; | 
|---|
| [1963] | 199 | //wheel.m_raycastInfo.m_groundObject = object; | 
|---|
|  | 200 |  | 
|---|
|  | 201 |  | 
|---|
|  | 202 | btScalar hitDistance = param*raylen; | 
|---|
|  | 203 | wheel.m_raycastInfo.m_suspensionLength = hitDistance - wheel.m_wheelsRadius; | 
|---|
|  | 204 | //clamp on max suspension travel | 
|---|
|  | 205 |  | 
|---|
|  | 206 | btScalar  minSuspensionLength = wheel.getSuspensionRestLength() - wheel.m_maxSuspensionTravelCm*btScalar(0.01); | 
|---|
|  | 207 | btScalar maxSuspensionLength = wheel.getSuspensionRestLength()+ wheel.m_maxSuspensionTravelCm*btScalar(0.01); | 
|---|
|  | 208 | if (wheel.m_raycastInfo.m_suspensionLength < minSuspensionLength) | 
|---|
|  | 209 | { | 
|---|
|  | 210 | wheel.m_raycastInfo.m_suspensionLength = minSuspensionLength; | 
|---|
|  | 211 | } | 
|---|
|  | 212 | if (wheel.m_raycastInfo.m_suspensionLength > maxSuspensionLength) | 
|---|
|  | 213 | { | 
|---|
|  | 214 | wheel.m_raycastInfo.m_suspensionLength = maxSuspensionLength; | 
|---|
|  | 215 | } | 
|---|
|  | 216 |  | 
|---|
|  | 217 | wheel.m_raycastInfo.m_contactPointWS = rayResults.m_hitPointInWorld; | 
|---|
|  | 218 |  | 
|---|
|  | 219 | btScalar denominator= wheel.m_raycastInfo.m_contactNormalWS.dot( wheel.m_raycastInfo.m_wheelDirectionWS ); | 
|---|
|  | 220 |  | 
|---|
|  | 221 | btVector3 chassis_velocity_at_contactPoint; | 
|---|
|  | 222 | btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS-getRigidBody()->getCenterOfMassPosition(); | 
|---|
|  | 223 |  | 
|---|
|  | 224 | chassis_velocity_at_contactPoint = getRigidBody()->getVelocityInLocalPoint(relpos); | 
|---|
|  | 225 |  | 
|---|
|  | 226 | btScalar projVel = wheel.m_raycastInfo.m_contactNormalWS.dot( chassis_velocity_at_contactPoint ); | 
|---|
|  | 227 |  | 
|---|
|  | 228 | if ( denominator >= btScalar(-0.1)) | 
|---|
|  | 229 | { | 
|---|
|  | 230 | wheel.m_suspensionRelativeVelocity = btScalar(0.0); | 
|---|
|  | 231 | wheel.m_clippedInvContactDotSuspension = btScalar(1.0) / btScalar(0.1); | 
|---|
|  | 232 | } | 
|---|
|  | 233 | else | 
|---|
|  | 234 | { | 
|---|
|  | 235 | btScalar inv = btScalar(-1.) / denominator; | 
|---|
|  | 236 | wheel.m_suspensionRelativeVelocity = projVel * inv; | 
|---|
|  | 237 | wheel.m_clippedInvContactDotSuspension = inv; | 
|---|
|  | 238 | } | 
|---|
|  | 239 |  | 
|---|
|  | 240 | } else | 
|---|
|  | 241 | { | 
|---|
|  | 242 | //put wheel info as in rest position | 
|---|
|  | 243 | wheel.m_raycastInfo.m_suspensionLength = wheel.getSuspensionRestLength(); | 
|---|
|  | 244 | wheel.m_suspensionRelativeVelocity = btScalar(0.0); | 
|---|
|  | 245 | wheel.m_raycastInfo.m_contactNormalWS = - wheel.m_raycastInfo.m_wheelDirectionWS; | 
|---|
|  | 246 | wheel.m_clippedInvContactDotSuspension = btScalar(1.0); | 
|---|
|  | 247 | } | 
|---|
|  | 248 |  | 
|---|
|  | 249 | return depth; | 
|---|
|  | 250 | } | 
|---|
|  | 251 |  | 
|---|
|  | 252 |  | 
|---|
|  | 253 | const btTransform& btRaycastVehicle::getChassisWorldTransform() const | 
|---|
|  | 254 | { | 
|---|
|  | 255 | /*if (getRigidBody()->getMotionState()) | 
|---|
|  | 256 | { | 
|---|
|  | 257 | btTransform chassisWorldTrans; | 
|---|
|  | 258 | getRigidBody()->getMotionState()->getWorldTransform(chassisWorldTrans); | 
|---|
|  | 259 | return chassisWorldTrans; | 
|---|
|  | 260 | } | 
|---|
|  | 261 | */ | 
|---|
|  | 262 |  | 
|---|
|  | 263 |  | 
|---|
|  | 264 | return getRigidBody()->getCenterOfMassTransform(); | 
|---|
|  | 265 | } | 
|---|
|  | 266 |  | 
|---|
|  | 267 |  | 
|---|
|  | 268 | void btRaycastVehicle::updateVehicle( btScalar step ) | 
|---|
|  | 269 | { | 
|---|
|  | 270 | { | 
|---|
|  | 271 | for (int i=0;i<getNumWheels();i++) | 
|---|
|  | 272 | { | 
|---|
|  | 273 | updateWheelTransform(i,false); | 
|---|
|  | 274 | } | 
|---|
|  | 275 | } | 
|---|
|  | 276 |  | 
|---|
|  | 277 |  | 
|---|
|  | 278 | m_currentVehicleSpeedKmHour = btScalar(3.6) * getRigidBody()->getLinearVelocity().length(); | 
|---|
|  | 279 |  | 
|---|
|  | 280 | const btTransform& chassisTrans = getChassisWorldTransform(); | 
|---|
|  | 281 |  | 
|---|
|  | 282 | btVector3 forwardW ( | 
|---|
|  | 283 | chassisTrans.getBasis()[0][m_indexForwardAxis], | 
|---|
|  | 284 | chassisTrans.getBasis()[1][m_indexForwardAxis], | 
|---|
|  | 285 | chassisTrans.getBasis()[2][m_indexForwardAxis]); | 
|---|
|  | 286 |  | 
|---|
|  | 287 | if (forwardW.dot(getRigidBody()->getLinearVelocity()) < btScalar(0.)) | 
|---|
|  | 288 | { | 
|---|
|  | 289 | m_currentVehicleSpeedKmHour *= btScalar(-1.); | 
|---|
|  | 290 | } | 
|---|
|  | 291 |  | 
|---|
|  | 292 | // | 
|---|
|  | 293 | // simulate suspension | 
|---|
|  | 294 | // | 
|---|
|  | 295 |  | 
|---|
|  | 296 | int i=0; | 
|---|
|  | 297 | for (i=0;i<m_wheelInfo.size();i++) | 
|---|
|  | 298 | { | 
|---|
|  | 299 | btScalar depth; | 
|---|
|  | 300 | depth = rayCast( m_wheelInfo[i]); | 
|---|
|  | 301 | } | 
|---|
|  | 302 |  | 
|---|
|  | 303 | updateSuspension(step); | 
|---|
|  | 304 |  | 
|---|
|  | 305 |  | 
|---|
|  | 306 | for (i=0;i<m_wheelInfo.size();i++) | 
|---|
|  | 307 | { | 
|---|
|  | 308 | //apply suspension force | 
|---|
|  | 309 | btWheelInfo& wheel = m_wheelInfo[i]; | 
|---|
|  | 310 |  | 
|---|
|  | 311 | btScalar suspensionForce = wheel.m_wheelsSuspensionForce; | 
|---|
|  | 312 |  | 
|---|
| [8351] | 313 | if (suspensionForce > wheel.m_maxSuspensionForce) | 
|---|
| [1963] | 314 | { | 
|---|
| [8351] | 315 | suspensionForce = wheel.m_maxSuspensionForce; | 
|---|
| [1963] | 316 | } | 
|---|
|  | 317 | btVector3 impulse = wheel.m_raycastInfo.m_contactNormalWS * suspensionForce * step; | 
|---|
|  | 318 | btVector3 relpos = wheel.m_raycastInfo.m_contactPointWS - getRigidBody()->getCenterOfMassPosition(); | 
|---|
|  | 319 |  | 
|---|
|  | 320 | getRigidBody()->applyImpulse(impulse, relpos); | 
|---|
|  | 321 |  | 
|---|
|  | 322 | } | 
|---|
|  | 323 |  | 
|---|
|  | 324 |  | 
|---|
|  | 325 |  | 
|---|
|  | 326 | updateFriction( step); | 
|---|
|  | 327 |  | 
|---|
|  | 328 |  | 
|---|
|  | 329 | for (i=0;i<m_wheelInfo.size();i++) | 
|---|
|  | 330 | { | 
|---|
|  | 331 | btWheelInfo& wheel = m_wheelInfo[i]; | 
|---|
|  | 332 | btVector3 relpos = wheel.m_raycastInfo.m_hardPointWS - getRigidBody()->getCenterOfMassPosition(); | 
|---|
|  | 333 | btVector3 vel = getRigidBody()->getVelocityInLocalPoint( relpos ); | 
|---|
|  | 334 |  | 
|---|
|  | 335 | if (wheel.m_raycastInfo.m_isInContact) | 
|---|
|  | 336 | { | 
|---|
|  | 337 | const btTransform&      chassisWorldTransform = getChassisWorldTransform(); | 
|---|
|  | 338 |  | 
|---|
|  | 339 | btVector3 fwd ( | 
|---|
|  | 340 | chassisWorldTransform.getBasis()[0][m_indexForwardAxis], | 
|---|
|  | 341 | chassisWorldTransform.getBasis()[1][m_indexForwardAxis], | 
|---|
|  | 342 | chassisWorldTransform.getBasis()[2][m_indexForwardAxis]); | 
|---|
|  | 343 |  | 
|---|
|  | 344 | btScalar proj = fwd.dot(wheel.m_raycastInfo.m_contactNormalWS); | 
|---|
|  | 345 | fwd -= wheel.m_raycastInfo.m_contactNormalWS * proj; | 
|---|
|  | 346 |  | 
|---|
|  | 347 | btScalar proj2 = fwd.dot(vel); | 
|---|
|  | 348 |  | 
|---|
|  | 349 | wheel.m_deltaRotation = (proj2 * step) / (wheel.m_wheelsRadius); | 
|---|
|  | 350 | wheel.m_rotation += wheel.m_deltaRotation; | 
|---|
|  | 351 |  | 
|---|
|  | 352 | } else | 
|---|
|  | 353 | { | 
|---|
|  | 354 | wheel.m_rotation += wheel.m_deltaRotation; | 
|---|
|  | 355 | } | 
|---|
|  | 356 |  | 
|---|
|  | 357 | wheel.m_deltaRotation *= btScalar(0.99);//damping of rotation when not in contact | 
|---|
|  | 358 |  | 
|---|
|  | 359 | } | 
|---|
|  | 360 |  | 
|---|
|  | 361 |  | 
|---|
|  | 362 |  | 
|---|
|  | 363 | } | 
|---|
|  | 364 |  | 
|---|
|  | 365 |  | 
|---|
|  | 366 | void    btRaycastVehicle::setSteeringValue(btScalar steering,int wheel) | 
|---|
|  | 367 | { | 
|---|
| [2882] | 368 | btAssert(wheel>=0 && wheel < getNumWheels()); | 
|---|
| [1963] | 369 |  | 
|---|
|  | 370 | btWheelInfo& wheelInfo = getWheelInfo(wheel); | 
|---|
|  | 371 | wheelInfo.m_steering = steering; | 
|---|
|  | 372 | } | 
|---|
|  | 373 |  | 
|---|
|  | 374 |  | 
|---|
|  | 375 |  | 
|---|
|  | 376 | btScalar        btRaycastVehicle::getSteeringValue(int wheel) const | 
|---|
|  | 377 | { | 
|---|
|  | 378 | return getWheelInfo(wheel).m_steering; | 
|---|
|  | 379 | } | 
|---|
|  | 380 |  | 
|---|
|  | 381 |  | 
|---|
|  | 382 | void    btRaycastVehicle::applyEngineForce(btScalar force, int wheel) | 
|---|
|  | 383 | { | 
|---|
| [2882] | 384 | btAssert(wheel>=0 && wheel < getNumWheels()); | 
|---|
| [1963] | 385 | btWheelInfo& wheelInfo = getWheelInfo(wheel); | 
|---|
|  | 386 | wheelInfo.m_engineForce = force; | 
|---|
|  | 387 | } | 
|---|
|  | 388 |  | 
|---|
|  | 389 |  | 
|---|
|  | 390 | const btWheelInfo&      btRaycastVehicle::getWheelInfo(int index) const | 
|---|
|  | 391 | { | 
|---|
|  | 392 | btAssert((index >= 0) && (index <       getNumWheels())); | 
|---|
|  | 393 |  | 
|---|
|  | 394 | return m_wheelInfo[index]; | 
|---|
|  | 395 | } | 
|---|
|  | 396 |  | 
|---|
|  | 397 | btWheelInfo&    btRaycastVehicle::getWheelInfo(int index) | 
|---|
|  | 398 | { | 
|---|
|  | 399 | btAssert((index >= 0) && (index <       getNumWheels())); | 
|---|
|  | 400 |  | 
|---|
|  | 401 | return m_wheelInfo[index]; | 
|---|
|  | 402 | } | 
|---|
|  | 403 |  | 
|---|
|  | 404 | void btRaycastVehicle::setBrake(btScalar brake,int wheelIndex) | 
|---|
|  | 405 | { | 
|---|
|  | 406 | btAssert((wheelIndex >= 0) && (wheelIndex <     getNumWheels())); | 
|---|
|  | 407 | getWheelInfo(wheelIndex).m_brake = brake; | 
|---|
|  | 408 | } | 
|---|
|  | 409 |  | 
|---|
|  | 410 |  | 
|---|
|  | 411 | void    btRaycastVehicle::updateSuspension(btScalar deltaTime) | 
|---|
|  | 412 | { | 
|---|
|  | 413 | (void)deltaTime; | 
|---|
|  | 414 |  | 
|---|
|  | 415 | btScalar chassisMass = btScalar(1.) / m_chassisBody->getInvMass(); | 
|---|
|  | 416 |  | 
|---|
|  | 417 | for (int w_it=0; w_it<getNumWheels(); w_it++) | 
|---|
|  | 418 | { | 
|---|
|  | 419 | btWheelInfo &wheel_info = m_wheelInfo[w_it]; | 
|---|
|  | 420 |  | 
|---|
|  | 421 | if ( wheel_info.m_raycastInfo.m_isInContact ) | 
|---|
|  | 422 | { | 
|---|
|  | 423 | btScalar force; | 
|---|
|  | 424 | //      Spring | 
|---|
|  | 425 | { | 
|---|
|  | 426 | btScalar        susp_length                     = wheel_info.getSuspensionRestLength(); | 
|---|
|  | 427 | btScalar        current_length = wheel_info.m_raycastInfo.m_suspensionLength; | 
|---|
|  | 428 |  | 
|---|
|  | 429 | btScalar length_diff = (susp_length - current_length); | 
|---|
|  | 430 |  | 
|---|
|  | 431 | force = wheel_info.m_suspensionStiffness | 
|---|
|  | 432 | * length_diff * wheel_info.m_clippedInvContactDotSuspension; | 
|---|
|  | 433 | } | 
|---|
|  | 434 |  | 
|---|
|  | 435 | // Damper | 
|---|
|  | 436 | { | 
|---|
|  | 437 | btScalar projected_rel_vel = wheel_info.m_suspensionRelativeVelocity; | 
|---|
|  | 438 | { | 
|---|
|  | 439 | btScalar        susp_damping; | 
|---|
|  | 440 | if ( projected_rel_vel < btScalar(0.0) ) | 
|---|
|  | 441 | { | 
|---|
|  | 442 | susp_damping = wheel_info.m_wheelsDampingCompression; | 
|---|
|  | 443 | } | 
|---|
|  | 444 | else | 
|---|
|  | 445 | { | 
|---|
|  | 446 | susp_damping = wheel_info.m_wheelsDampingRelaxation; | 
|---|
|  | 447 | } | 
|---|
|  | 448 | force -= susp_damping * projected_rel_vel; | 
|---|
|  | 449 | } | 
|---|
|  | 450 | } | 
|---|
|  | 451 |  | 
|---|
|  | 452 | // RESULT | 
|---|
|  | 453 | wheel_info.m_wheelsSuspensionForce = force * chassisMass; | 
|---|
|  | 454 | if (wheel_info.m_wheelsSuspensionForce < btScalar(0.)) | 
|---|
|  | 455 | { | 
|---|
|  | 456 | wheel_info.m_wheelsSuspensionForce = btScalar(0.); | 
|---|
|  | 457 | } | 
|---|
|  | 458 | } | 
|---|
|  | 459 | else | 
|---|
|  | 460 | { | 
|---|
|  | 461 | wheel_info.m_wheelsSuspensionForce = btScalar(0.0); | 
|---|
|  | 462 | } | 
|---|
|  | 463 | } | 
|---|
|  | 464 |  | 
|---|
|  | 465 | } | 
|---|
|  | 466 |  | 
|---|
|  | 467 |  | 
|---|
|  | 468 | struct btWheelContactPoint | 
|---|
|  | 469 | { | 
|---|
|  | 470 | btRigidBody* m_body0; | 
|---|
|  | 471 | btRigidBody* m_body1; | 
|---|
|  | 472 | btVector3       m_frictionPositionWorld; | 
|---|
|  | 473 | btVector3       m_frictionDirectionWorld; | 
|---|
|  | 474 | btScalar        m_jacDiagABInv; | 
|---|
|  | 475 | btScalar        m_maxImpulse; | 
|---|
|  | 476 |  | 
|---|
|  | 477 |  | 
|---|
|  | 478 | btWheelContactPoint(btRigidBody* body0,btRigidBody* body1,const btVector3& frictionPosWorld,const btVector3& frictionDirectionWorld, btScalar maxImpulse) | 
|---|
|  | 479 | :m_body0(body0), | 
|---|
|  | 480 | m_body1(body1), | 
|---|
|  | 481 | m_frictionPositionWorld(frictionPosWorld), | 
|---|
|  | 482 | m_frictionDirectionWorld(frictionDirectionWorld), | 
|---|
|  | 483 | m_maxImpulse(maxImpulse) | 
|---|
|  | 484 | { | 
|---|
|  | 485 | btScalar denom0 = body0->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); | 
|---|
|  | 486 | btScalar denom1 = body1->computeImpulseDenominator(frictionPosWorld,frictionDirectionWorld); | 
|---|
|  | 487 | btScalar        relaxation = 1.f; | 
|---|
|  | 488 | m_jacDiagABInv = relaxation/(denom0+denom1); | 
|---|
|  | 489 | } | 
|---|
|  | 490 |  | 
|---|
|  | 491 |  | 
|---|
|  | 492 |  | 
|---|
|  | 493 | }; | 
|---|
|  | 494 |  | 
|---|
|  | 495 | btScalar calcRollingFriction(btWheelContactPoint& contactPoint); | 
|---|
|  | 496 | btScalar calcRollingFriction(btWheelContactPoint& contactPoint) | 
|---|
|  | 497 | { | 
|---|
|  | 498 |  | 
|---|
|  | 499 | btScalar j1=0.f; | 
|---|
|  | 500 |  | 
|---|
|  | 501 | const btVector3& contactPosWorld = contactPoint.m_frictionPositionWorld; | 
|---|
|  | 502 |  | 
|---|
|  | 503 | btVector3 rel_pos1 = contactPosWorld - contactPoint.m_body0->getCenterOfMassPosition(); | 
|---|
|  | 504 | btVector3 rel_pos2 = contactPosWorld - contactPoint.m_body1->getCenterOfMassPosition(); | 
|---|
|  | 505 |  | 
|---|
|  | 506 | btScalar maxImpulse  = contactPoint.m_maxImpulse; | 
|---|
|  | 507 |  | 
|---|
|  | 508 | btVector3 vel1 = contactPoint.m_body0->getVelocityInLocalPoint(rel_pos1); | 
|---|
|  | 509 | btVector3 vel2 = contactPoint.m_body1->getVelocityInLocalPoint(rel_pos2); | 
|---|
|  | 510 | btVector3 vel = vel1 - vel2; | 
|---|
|  | 511 |  | 
|---|
|  | 512 | btScalar vrel = contactPoint.m_frictionDirectionWorld.dot(vel); | 
|---|
|  | 513 |  | 
|---|
|  | 514 | // calculate j that moves us to zero relative velocity | 
|---|
|  | 515 | j1 = -vrel * contactPoint.m_jacDiagABInv; | 
|---|
|  | 516 | btSetMin(j1, maxImpulse); | 
|---|
|  | 517 | btSetMax(j1, -maxImpulse); | 
|---|
|  | 518 |  | 
|---|
|  | 519 | return j1; | 
|---|
|  | 520 | } | 
|---|
|  | 521 |  | 
|---|
|  | 522 |  | 
|---|
|  | 523 |  | 
|---|
|  | 524 |  | 
|---|
|  | 525 | btScalar sideFrictionStiffness2 = btScalar(1.0); | 
|---|
|  | 526 | void    btRaycastVehicle::updateFriction(btScalar       timeStep) | 
|---|
|  | 527 | { | 
|---|
|  | 528 |  | 
|---|
|  | 529 | //calculate the impulse, so that the wheels don't move sidewards | 
|---|
|  | 530 | int numWheel = getNumWheels(); | 
|---|
|  | 531 | if (!numWheel) | 
|---|
|  | 532 | return; | 
|---|
|  | 533 |  | 
|---|
|  | 534 | m_forwardWS.resize(numWheel); | 
|---|
|  | 535 | m_axle.resize(numWheel); | 
|---|
|  | 536 | m_forwardImpulse.resize(numWheel); | 
|---|
|  | 537 | m_sideImpulse.resize(numWheel); | 
|---|
|  | 538 |  | 
|---|
|  | 539 | int numWheelsOnGround = 0; | 
|---|
|  | 540 |  | 
|---|
|  | 541 |  | 
|---|
|  | 542 | //collapse all those loops into one! | 
|---|
|  | 543 | for (int i=0;i<getNumWheels();i++) | 
|---|
|  | 544 | { | 
|---|
|  | 545 | btWheelInfo& wheelInfo = m_wheelInfo[i]; | 
|---|
|  | 546 | class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; | 
|---|
|  | 547 | if (groundObject) | 
|---|
|  | 548 | numWheelsOnGround++; | 
|---|
|  | 549 | m_sideImpulse[i] = btScalar(0.); | 
|---|
|  | 550 | m_forwardImpulse[i] = btScalar(0.); | 
|---|
|  | 551 |  | 
|---|
|  | 552 | } | 
|---|
|  | 553 |  | 
|---|
|  | 554 | { | 
|---|
|  | 555 |  | 
|---|
|  | 556 | for (int i=0;i<getNumWheels();i++) | 
|---|
|  | 557 | { | 
|---|
|  | 558 |  | 
|---|
|  | 559 | btWheelInfo& wheelInfo = m_wheelInfo[i]; | 
|---|
|  | 560 |  | 
|---|
|  | 561 | class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; | 
|---|
|  | 562 |  | 
|---|
|  | 563 | if (groundObject) | 
|---|
|  | 564 | { | 
|---|
|  | 565 |  | 
|---|
|  | 566 | const btTransform& wheelTrans = getWheelTransformWS( i ); | 
|---|
|  | 567 |  | 
|---|
|  | 568 | btMatrix3x3 wheelBasis0 = wheelTrans.getBasis(); | 
|---|
|  | 569 | m_axle[i] = btVector3( | 
|---|
|  | 570 | wheelBasis0[0][m_indexRightAxis], | 
|---|
|  | 571 | wheelBasis0[1][m_indexRightAxis], | 
|---|
|  | 572 | wheelBasis0[2][m_indexRightAxis]); | 
|---|
|  | 573 |  | 
|---|
|  | 574 | const btVector3& surfNormalWS = wheelInfo.m_raycastInfo.m_contactNormalWS; | 
|---|
|  | 575 | btScalar proj = m_axle[i].dot(surfNormalWS); | 
|---|
|  | 576 | m_axle[i] -= surfNormalWS * proj; | 
|---|
|  | 577 | m_axle[i] = m_axle[i].normalize(); | 
|---|
|  | 578 |  | 
|---|
|  | 579 | m_forwardWS[i] = surfNormalWS.cross(m_axle[i]); | 
|---|
|  | 580 | m_forwardWS[i].normalize(); | 
|---|
|  | 581 |  | 
|---|
|  | 582 |  | 
|---|
|  | 583 | resolveSingleBilateral(*m_chassisBody, wheelInfo.m_raycastInfo.m_contactPointWS, | 
|---|
|  | 584 | *groundObject, wheelInfo.m_raycastInfo.m_contactPointWS, | 
|---|
|  | 585 | btScalar(0.), m_axle[i],m_sideImpulse[i],timeStep); | 
|---|
|  | 586 |  | 
|---|
|  | 587 | m_sideImpulse[i] *= sideFrictionStiffness2; | 
|---|
|  | 588 |  | 
|---|
|  | 589 | } | 
|---|
|  | 590 |  | 
|---|
|  | 591 |  | 
|---|
|  | 592 | } | 
|---|
|  | 593 | } | 
|---|
|  | 594 |  | 
|---|
|  | 595 | btScalar sideFactor = btScalar(1.); | 
|---|
|  | 596 | btScalar fwdFactor = 0.5; | 
|---|
|  | 597 |  | 
|---|
|  | 598 | bool sliding = false; | 
|---|
|  | 599 | { | 
|---|
|  | 600 | for (int wheel =0;wheel <getNumWheels();wheel++) | 
|---|
|  | 601 | { | 
|---|
|  | 602 | btWheelInfo& wheelInfo = m_wheelInfo[wheel]; | 
|---|
|  | 603 | class btRigidBody* groundObject = (class btRigidBody*) wheelInfo.m_raycastInfo.m_groundObject; | 
|---|
|  | 604 |  | 
|---|
|  | 605 | btScalar        rollingFriction = 0.f; | 
|---|
|  | 606 |  | 
|---|
|  | 607 | if (groundObject) | 
|---|
|  | 608 | { | 
|---|
|  | 609 | if (wheelInfo.m_engineForce != 0.f) | 
|---|
|  | 610 | { | 
|---|
|  | 611 | rollingFriction = wheelInfo.m_engineForce* timeStep; | 
|---|
|  | 612 | } else | 
|---|
|  | 613 | { | 
|---|
|  | 614 | btScalar defaultRollingFrictionImpulse = 0.f; | 
|---|
|  | 615 | btScalar maxImpulse = wheelInfo.m_brake ? wheelInfo.m_brake : defaultRollingFrictionImpulse; | 
|---|
|  | 616 | btWheelContactPoint contactPt(m_chassisBody,groundObject,wheelInfo.m_raycastInfo.m_contactPointWS,m_forwardWS[wheel],maxImpulse); | 
|---|
|  | 617 | rollingFriction = calcRollingFriction(contactPt); | 
|---|
|  | 618 | } | 
|---|
|  | 619 | } | 
|---|
|  | 620 |  | 
|---|
|  | 621 | //switch between active rolling (throttle), braking and non-active rolling friction (no throttle/break) | 
|---|
|  | 622 |  | 
|---|
|  | 623 |  | 
|---|
|  | 624 |  | 
|---|
|  | 625 |  | 
|---|
|  | 626 | m_forwardImpulse[wheel] = btScalar(0.); | 
|---|
|  | 627 | m_wheelInfo[wheel].m_skidInfo= btScalar(1.); | 
|---|
|  | 628 |  | 
|---|
|  | 629 | if (groundObject) | 
|---|
|  | 630 | { | 
|---|
|  | 631 | m_wheelInfo[wheel].m_skidInfo= btScalar(1.); | 
|---|
|  | 632 |  | 
|---|
|  | 633 | btScalar maximp = wheelInfo.m_wheelsSuspensionForce * timeStep * wheelInfo.m_frictionSlip; | 
|---|
|  | 634 | btScalar maximpSide = maximp; | 
|---|
|  | 635 |  | 
|---|
|  | 636 | btScalar maximpSquared = maximp * maximpSide; | 
|---|
|  | 637 |  | 
|---|
|  | 638 |  | 
|---|
|  | 639 | m_forwardImpulse[wheel] = rollingFriction;//wheelInfo.m_engineForce* timeStep; | 
|---|
|  | 640 |  | 
|---|
|  | 641 | btScalar x = (m_forwardImpulse[wheel] ) * fwdFactor; | 
|---|
|  | 642 | btScalar y = (m_sideImpulse[wheel] ) * sideFactor; | 
|---|
|  | 643 |  | 
|---|
|  | 644 | btScalar impulseSquared = (x*x + y*y); | 
|---|
|  | 645 |  | 
|---|
|  | 646 | if (impulseSquared > maximpSquared) | 
|---|
|  | 647 | { | 
|---|
|  | 648 | sliding = true; | 
|---|
|  | 649 |  | 
|---|
|  | 650 | btScalar factor = maximp / btSqrt(impulseSquared); | 
|---|
|  | 651 |  | 
|---|
|  | 652 | m_wheelInfo[wheel].m_skidInfo *= factor; | 
|---|
|  | 653 | } | 
|---|
|  | 654 | } | 
|---|
|  | 655 |  | 
|---|
|  | 656 | } | 
|---|
|  | 657 | } | 
|---|
|  | 658 |  | 
|---|
|  | 659 |  | 
|---|
|  | 660 |  | 
|---|
|  | 661 |  | 
|---|
|  | 662 | if (sliding) | 
|---|
|  | 663 | { | 
|---|
|  | 664 | for (int wheel = 0;wheel < getNumWheels(); wheel++) | 
|---|
|  | 665 | { | 
|---|
|  | 666 | if (m_sideImpulse[wheel] != btScalar(0.)) | 
|---|
|  | 667 | { | 
|---|
|  | 668 | if (m_wheelInfo[wheel].m_skidInfo< btScalar(1.)) | 
|---|
|  | 669 | { | 
|---|
|  | 670 | m_forwardImpulse[wheel] *=      m_wheelInfo[wheel].m_skidInfo; | 
|---|
|  | 671 | m_sideImpulse[wheel] *= m_wheelInfo[wheel].m_skidInfo; | 
|---|
|  | 672 | } | 
|---|
|  | 673 | } | 
|---|
|  | 674 | } | 
|---|
|  | 675 | } | 
|---|
|  | 676 |  | 
|---|
|  | 677 | // apply the impulses | 
|---|
|  | 678 | { | 
|---|
|  | 679 | for (int wheel = 0;wheel<getNumWheels() ; wheel++) | 
|---|
|  | 680 | { | 
|---|
|  | 681 | btWheelInfo& wheelInfo = m_wheelInfo[wheel]; | 
|---|
|  | 682 |  | 
|---|
|  | 683 | btVector3 rel_pos = wheelInfo.m_raycastInfo.m_contactPointWS - | 
|---|
|  | 684 | m_chassisBody->getCenterOfMassPosition(); | 
|---|
|  | 685 |  | 
|---|
|  | 686 | if (m_forwardImpulse[wheel] != btScalar(0.)) | 
|---|
|  | 687 | { | 
|---|
|  | 688 | m_chassisBody->applyImpulse(m_forwardWS[wheel]*(m_forwardImpulse[wheel]),rel_pos); | 
|---|
|  | 689 | } | 
|---|
|  | 690 | if (m_sideImpulse[wheel] != btScalar(0.)) | 
|---|
|  | 691 | { | 
|---|
|  | 692 | class btRigidBody* groundObject = (class btRigidBody*) m_wheelInfo[wheel].m_raycastInfo.m_groundObject; | 
|---|
|  | 693 |  | 
|---|
|  | 694 | btVector3 rel_pos2 = wheelInfo.m_raycastInfo.m_contactPointWS - | 
|---|
|  | 695 | groundObject->getCenterOfMassPosition(); | 
|---|
|  | 696 |  | 
|---|
|  | 697 |  | 
|---|
|  | 698 | btVector3 sideImp = m_axle[wheel] * m_sideImpulse[wheel]; | 
|---|
|  | 699 |  | 
|---|
| [8393] | 700 | #if defined ROLLING_INFLUENCE_FIX // fix. It only worked if car's up was along Y - VT. | 
|---|
|  | 701 | btVector3 vChassisWorldUp = getRigidBody()->getCenterOfMassTransform().getBasis().getColumn(m_indexUpAxis); | 
|---|
|  | 702 | rel_pos -= vChassisWorldUp * (vChassisWorldUp.dot(rel_pos) * (1.f-wheelInfo.m_rollInfluence)); | 
|---|
|  | 703 | #else | 
|---|
| [8351] | 704 | rel_pos[m_indexUpAxis] *= wheelInfo.m_rollInfluence; | 
|---|
| [8393] | 705 | #endif | 
|---|
| [1963] | 706 | m_chassisBody->applyImpulse(sideImp,rel_pos); | 
|---|
|  | 707 |  | 
|---|
|  | 708 | //apply friction impulse on the ground | 
|---|
|  | 709 | groundObject->applyImpulse(-sideImp,rel_pos2); | 
|---|
|  | 710 | } | 
|---|
|  | 711 | } | 
|---|
|  | 712 | } | 
|---|
|  | 713 |  | 
|---|
|  | 714 |  | 
|---|
|  | 715 | } | 
|---|
|  | 716 |  | 
|---|
|  | 717 |  | 
|---|
| [2882] | 718 |  | 
|---|
|  | 719 | void    btRaycastVehicle::debugDraw(btIDebugDraw* debugDrawer) | 
|---|
|  | 720 | { | 
|---|
|  | 721 |  | 
|---|
|  | 722 | for (int v=0;v<this->getNumWheels();v++) | 
|---|
|  | 723 | { | 
|---|
| [8351] | 724 | btVector3 wheelColor(0,1,1); | 
|---|
| [2882] | 725 | if (getWheelInfo(v).m_raycastInfo.m_isInContact) | 
|---|
|  | 726 | { | 
|---|
| [8351] | 727 | wheelColor.setValue(0,0,1); | 
|---|
| [2882] | 728 | } else | 
|---|
|  | 729 | { | 
|---|
| [8351] | 730 | wheelColor.setValue(1,0,1); | 
|---|
| [2882] | 731 | } | 
|---|
|  | 732 |  | 
|---|
|  | 733 | btVector3 wheelPosWS = getWheelInfo(v).m_worldTransform.getOrigin(); | 
|---|
|  | 734 |  | 
|---|
|  | 735 | btVector3 axle = btVector3( | 
|---|
|  | 736 | getWheelInfo(v).m_worldTransform.getBasis()[0][getRightAxis()], | 
|---|
|  | 737 | getWheelInfo(v).m_worldTransform.getBasis()[1][getRightAxis()], | 
|---|
|  | 738 | getWheelInfo(v).m_worldTransform.getBasis()[2][getRightAxis()]); | 
|---|
|  | 739 |  | 
|---|
|  | 740 | //debug wheels (cylinders) | 
|---|
|  | 741 | debugDrawer->drawLine(wheelPosWS,wheelPosWS+axle,wheelColor); | 
|---|
|  | 742 | debugDrawer->drawLine(wheelPosWS,getWheelInfo(v).m_raycastInfo.m_contactPointWS,wheelColor); | 
|---|
|  | 743 |  | 
|---|
|  | 744 | } | 
|---|
|  | 745 | } | 
|---|
|  | 746 |  | 
|---|
|  | 747 |  | 
|---|
| [1963] | 748 | void* btDefaultVehicleRaycaster::castRay(const btVector3& from,const btVector3& to, btVehicleRaycasterResult& result) | 
|---|
|  | 749 | { | 
|---|
|  | 750 | //      RayResultCallback& resultCallback; | 
|---|
|  | 751 |  | 
|---|
|  | 752 | btCollisionWorld::ClosestRayResultCallback rayCallback(from,to); | 
|---|
|  | 753 |  | 
|---|
|  | 754 | m_dynamicsWorld->rayTest(from, to, rayCallback); | 
|---|
|  | 755 |  | 
|---|
|  | 756 | if (rayCallback.hasHit()) | 
|---|
|  | 757 | { | 
|---|
|  | 758 |  | 
|---|
|  | 759 | btRigidBody* body = btRigidBody::upcast(rayCallback.m_collisionObject); | 
|---|
|  | 760 | if (body && body->hasContactResponse()) | 
|---|
|  | 761 | { | 
|---|
|  | 762 | result.m_hitPointInWorld = rayCallback.m_hitPointWorld; | 
|---|
|  | 763 | result.m_hitNormalInWorld = rayCallback.m_hitNormalWorld; | 
|---|
|  | 764 | result.m_hitNormalInWorld.normalize(); | 
|---|
|  | 765 | result.m_distFraction = rayCallback.m_closestHitFraction; | 
|---|
|  | 766 | return body; | 
|---|
|  | 767 | } | 
|---|
|  | 768 | } | 
|---|
|  | 769 | return 0; | 
|---|
|  | 770 | } | 
|---|
| [2882] | 771 |  | 
|---|