#include #include "vtPhysXAll.h" #include "pVehicleMotor.h" #include "pVehicleGears.h" #include "pSteer.h" #include #include "NxArray.h" float pVehicle::getBrakeAmountFromTable(pVehicleBreakLevel brakeLevel) { int value = abs((int(getMPH()) / 10)); if(value > BREAK_TABLE_ENTRIES - 1) value = BREAK_TABLE_ENTRIES - 1; if(value < 0 || value == BREAK_TABLE_ENTRIES) { return 1.0f; } switch(brakeLevel) { case BL_Small: return mSmallBrakeTable.brakeEntries[brakeLevel]; case BL_Medium: return mMediumBrakeTable.brakeEntries[brakeLevel]; case BL_High: return mHighBrakeTable.brakeEntries[brakeLevel]; } return 1.0f; } pVehicleBreakCase pVehicle::calculateBreakCase(int currentAccelerationStatus) { //---------------------------------------------------------------- // // is rolling or no user input ? // if( !(currentAccelerationStatus & VS_Handbrake ) && (currentAccelerationStatus & VS_IsMoving ) && !(currentAccelerationStatus & VS_IsAccelerated) ) return BC_NoUserInput; //---------------------------------------------------------------- // // direction change ? // if( !(currentAccelerationStatus & VS_Handbrake ) && (currentAccelerationStatus & VS_IsBraking ) && (currentAccelerationStatus & VS_IsMoving ) && (currentAccelerationStatus & VS_IsAccelerated) ) return BC_DirectionChange; //---------------------------------------------------------------- // // handbrake // if( (currentAccelerationStatus & VS_Handbrake ) ) return BC_Handbrake; return BC_NoUserInput; } void pVehicle::doSteering() { for(NxU32 i = 0; i < _wheels.size(); i++) { pWheel2* wheel = (pWheel2*)_wheels[i]; if(wheel->getWheelFlag(WF_SteerableInput)) { int i; // Send steering angle through to steering wheels float factor=steer->GetLock()/wheel->GetLock()*2.0f; float angle = steer->GetAngle(); float rAngle = wheel->getWheelShape()->getSteerAngle(); wheel->setSteering(steer->GetAngle()/factor); } } } int pVehicle::_performSteering(float dt) { _controlSteering(_cSteering, _cAnalogSteering); NxReal distanceSteeringAxisCarTurnAxis = _steeringSteerPoint.x - _steeringTurnPoint.x; //NX_ASSERT(_steeringSteerPoint.z == _steeringTurnPoint.z); NxReal distance2 = 0; if (NxMath::abs(_steeringWheelState) > 0.01f) distance2 = distanceSteeringAxisCarTurnAxis / NxMath::tan(_steeringWheelState * getMaxSteering()); float tanS = NxMath::tan(_steeringWheelState * getMaxSteering()); for(NxU32 i = 0; i < _wheels.size(); i++) { pWheel* wheel = _wheels[i]; if(wheel->getWheelFlag(WF_SteerableInput)) { if(distance2 != 0) { //NxReal xPos = wheel->getWheelPos().x; NxReal xPos = ((pWheel2*)wheel)->getWheelShape()->getLocalPosition().x; //NxReal xPos2 = _steeringSteerPoint.x- wheel->getWheelPos().x; //NxReal xPos2 = _steeringSteerPoint.x- ((pWheel2*)wheel)->getWheelShape()->getLocalPosition().z; NxReal zPos = ((pWheel2*)wheel)->getWheelShape()->getLocalPosition().z; //NxReal zPos = wheel->getWheelPos().z; NxReal dz = -zPos + distance2; NxReal dx = xPos - _steeringTurnPoint.x; float angle =(NxMath::atan(dx/dz)); if (dx < 0.0f) { angle*=-1.0f; } wheel->setAngle(angle); } else { wheel->setAngle(0.0f); } } else if(wheel->getWheelFlag(WF_SteerableAuto)) { NxVec3 localVelocity = getActor()->getLocalPointVelocity(getFrom(wheel->getWheelPos())); NxQuat local2Global = getActor()->getGlobalOrientationQuat(); local2Global.inverseRotate(localVelocity); // printf("%2.3f %2.3f %2.3f\n", wheel->getWheelPos().x,wheel->getWheelPos().y,wheel->getWheelPos().z); localVelocity.y = 0; if(localVelocity.magnitudeSquared() < 0.1f) { wheel->setAngle(0.0f); } else { localVelocity.normalize(); // printf("localVelocity: %2.3f %2.3f\n", localVelocity.x, localVelocity.z); if(localVelocity.x < 0) localVelocity = -localVelocity; NxReal angle = NxMath::clamp((NxReal)atan(localVelocity.z / localVelocity.x), 0.3f, -0.3f); wheel->setAngle(angle); } } } return 0; } float pVehicle::calculateBraking(float dt) { float breakTorque = 0.0f; pVehicleBreakCase currentBreakCase = calculateBreakCase(_currentStatus); /* int currentBreakLevel = getBreaklevelForCase(currentBreakCase); */ bool calculateBreaking = false; XString errMessage; if( ((_currentStatus & VS_IsBraking ) && (_currentStatus & VS_IsMoving)) ) calculateBreaking = true; if ( (_currentStatus & VS_IsMoving ) && (getBreakFlags() & VBF_Autobreak) && (currentBreakCase == BC_NoUserInput)&& (_currentStatus & VS_IsMoving ) && !(_currentStatus & VS_IsAccelerated ) ) { calculateBreaking = true; /* errMessage.Format("autobreak");*/ //xInfo(errMessage.Str()); } if (_currentStatus & VS_Handbrake) { /*errMessage.Format("handbrake"); xInfo(errMessage.Str());*/ goto performAcceleration; } //---------------------------------------------------------------- // // calculate break torque // if ( calculateBreaking ) { //---------------------------------------------------------------- // // increase break time counter // if(mBreakLastFrame) mTimeBreaking+=dt; //---------------------------------------------------------------- // // determine break amount by table // if ( (getBreakFlags() & VBF_UseTable) ) { if(mTimeBreaking < mBrakeMediumThresold) { breakTorque = getBrakeAmountFromTable(BL_Small); errMessage.Format("breaking at small : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); }else if(mTimeBreaking >= mBrakeMediumThresold && mTimeBreaking < mBrakeHighThresold ) { breakTorque = getBrakeAmountFromTable(BL_Medium); errMessage.Format("breaking at medium : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); }else { breakTorque = getBrakeAmountFromTable(BL_High); errMessage.Format("breaking at high : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); } }else { //---------------------------------------------------------------- // // use break pressures // float mCurrentBrakeTorque = getBrakeTorque()*0.01f; float AmountToBrakeFinal = 0.0f; if(mTimeBreaking < mBrakeMediumThresold) { breakTorque = mCurrentBrakeTorque * mBreakPressures[BL_Small]; errMessage.Format("breaking at small : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); } else if(mTimeBreaking >= mBrakeMediumThresold && mTimeBreaking < mBrakeHighThresold ) { breakTorque = mCurrentBrakeTorque * mBreakPressures[BL_Medium]; errMessage.Format("breaking at medium : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); } else { breakTorque = mCurrentBrakeTorque * mBreakPressures[BL_High]; errMessage.Format("breaking at high : bt : %f at %f",breakTorque,mTimeBreaking); //xInfo(errMessage.Str()); } if (breakTorque > 1000.f) { breakTorque= 1000.0f; } } }else { mBreakLastFrame = false; mTimeBreaking = 0.0f; } performAcceleration: if (breakTorque > 0.0f) { mBreakLastFrame = true; } return breakTorque; } int pVehicle::_performAcceleration(float dt) { motorTorque = 0.0f; if ( _nbTouching && _currentStatus & VS_IsAccelerated ) { NxReal axisTorque = _computeAxisTorqueV2(); NxReal wheelTorque = axisTorque / (NxReal)(_wheels.size() - _nbHandbrakeOn ); NxReal wheelTorqueNotTouching = _nbNotTouching > 0 ? wheelTorque * ( NxMath::pow(0.5f, (NxReal) _nbNotTouching )):0; NxReal wheelTorqueTouching = wheelTorque - wheelTorqueNotTouching; motorTorque = wheelTorqueTouching / (NxReal)_nbTouching; }else { _updateRpms(); } return 1; } void pVehicle::postStep() { for(NxU32 i = 0; i < _wheels.size(); i++) { //---------------------------------------------------------------- // // determine break torque : // // is moving in the opposite direction than its accelerated pWheel* wheel = _wheels[i]; wheel->tick( ( _currentStatus & VS_Handbrake) , motorTorque, breakTorque , _lastDT ); } } void pVehicle::setBreakPressure(int breakLevel,float pressure) { mBreakPressures[breakLevel]=pressure; } void pVehicle::setBreakCaseLevel(pVehicleBreakCase breakCase,pVehicleBreakLevel level) { breakConditionLevels[breakCase]=level; } // ( X * 10 * 60) / (5280* 12) * 100 = X * 0.9469696 //return (-((10 * GetWheelSizeWidth() * NxPi * mOurWheels[BACK_LEFT]->getAxleSpeed() * 60) / (5280 * 12)) * 100); //return -0.9469696 * GetWheelSizeWidth() * NxPi * mOurWheels[BACK_LEFT]->getAxleSpeed(); float pVehicle::getBrakeTorque() { int nbAWheels =0; float radius = 0.0; float axleSpeed = 0.0; for(NxU32 i = 0; i < _wheels.size(); i++) { pWheel* wheel = _wheels[i]; if(wheel->getWheelFlag(WF_Accelerated)) { nbAWheels++; if (wheel->getRadius() > radius) radius = wheel->getRadius(); pWheel2* w2 = (pWheel2*)wheel; if (w2->getWheelShape()->getAxleSpeed() > axleSpeed) { axleSpeed = w2->getWheelShape()->getAxleSpeed(); } } } if(fabs(axleSpeed) != 0) { return ((5252 * getMotorForce()) / (fabs(axleSpeed) * 10)); } return 0.0f; } float pVehicle::getMPH(int type) { int nbAWheels =0; float radius = 0.0; float axleSpeed = 0.0; for(NxU32 i = 0; i < _wheels.size(); i++) { pWheel* wheel = _wheels[i]; if(wheel->getWheelFlag(WF_Accelerated)) { nbAWheels++; if (wheel->getRadius() > radius) radius = wheel->getRadius(); pWheel2* w2 = (pWheel2*)wheel; if (w2->getWheelShape()->getAxleSpeed() > axleSpeed) { axleSpeed = w2->getWheelShape()->getAxleSpeed(); } } } // ( X * 10 * 60) / (5280* 12) * 100 = X * 0.9469696 //return (-((10 * GetWheelSizeWidth() * NxPi * mOurWheels[BACK_LEFT]->getAxleSpeed() * 60) / (5280 * 12)) * 100); return 0.9469696 * radius * NxPi * axleSpeed; } void pVehicle::_controlAcceleration(float acceleration, bool analogAcceleration) { if(NxMath::abs(acceleration) < 0.001f) { _releaseBraking = true; //xInfo("set release breaking = true"); } if(!_braking) { _accelerationPedal = NxMath::clamp(acceleration, 1.f, -1.f); _brakePedalChanged = _brakePedal == 0; _brakePedal = 0; //xInfo("breaking = false : clamp accPedal 1|-1"); } else { //xInfo("breaking = true : accPeal = 0"); _accelerationPedal = 0; NxReal newv = NxMath::clamp(NxMath::abs(acceleration), 1.f, 0.f); _brakePedalChanged = _brakePedal == newv; _brakePedal = newv; } char master[512]; sprintf(master,"Acceleration: %2.3f, Braking %2.3f\n", _accelerationPedal, _brakePedal); xInfo(master); //OutputDebugString(master); }