void UWheeledVehicleMovementComponent4W::UpdateSimulation(float DeltaTime) { if (PVehicleDrive == NULL) return; PxVehicleDrive4WRawInputData RawInputData; RawInputData.setAnalogAccel(ThrottleInput); RawInputData.setAnalogSteer(SteeringInput); RawInputData.setAnalogBrake(BrakeInput); RawInputData.setAnalogHandbrake(HandbrakeInput); if (!PVehicleDrive->mDriveDynData.getUseAutoGears()) { RawInputData.setGearUp(bRawGearUpInput); RawInputData.setGearDown(bRawGearDownInput); } PxFixedSizeLookupTable<8> SpeedSteerLookup(SteeringMap,4); PxVehiclePadSmoothingData SmoothData = { { ThrottleInputRate.RiseRate, BrakeInputRate.RiseRate, HandbrakeInputRate.RiseRate, SteeringInputRate.RiseRate, SteeringInputRate.RiseRate }, { ThrottleInputRate.FallRate, BrakeInputRate.FallRate, HandbrakeInputRate.FallRate, SteeringInputRate.FallRate, SteeringInputRate.FallRate } }; PxVehicleDrive4W* PVehicleDrive4W = (PxVehicleDrive4W*)PVehicleDrive; PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(SmoothData, SpeedSteerLookup, RawInputData, DeltaTime, false, *PVehicleDrive4W); }
void PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs (const PxVehiclePadSmoothingData& padSmoothing, const PxFixedSizeLookupTable<8>& steerVsForwardSpeedTable, const PxVehicleDrive4WRawInputData& rawInputData, const PxF32 timestep, PxVehicleDrive4W& focusVehicle) { //gearup/geardown const bool gearup=rawInputData.getGearUp(); const bool geardown=rawInputData.getGearDown(); focusVehicle.mDriveDynData.setGearUp(gearup); focusVehicle.mDriveDynData.setGearDown(geardown); //Update analog inputs for focus vehicle. //Process the accel. { const PxF32 riseRate=padSmoothing.mRiseRates[PxVehicleDrive4W::eANALOG_INPUT_ACCEL]; const PxF32 fallRate=padSmoothing.mFallRates[PxVehicleDrive4W::eANALOG_INPUT_ACCEL]; const PxF32 currentVal=focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_ACCEL); const PxF32 targetVal=rawInputData.getAnalogAccel(); const PxF32 accel=processPositiveAnalogValue(riseRate,fallRate,currentVal,targetVal,timestep); focusVehicle.mDriveDynData.setAnalogInput(accel,PxVehicleDrive4W::eANALOG_INPUT_ACCEL); } //Process the brake { const PxF32 riseRate=padSmoothing.mRiseRates[PxVehicleDrive4W::eANALOG_INPUT_BRAKE]; const PxF32 fallRate=padSmoothing.mFallRates[PxVehicleDrive4W::eANALOG_INPUT_BRAKE]; const PxF32 currentVal=focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_BRAKE); const PxF32 targetVal=rawInputData.getAnalogBrake(); const PxF32 brake=processPositiveAnalogValue(riseRate,fallRate,currentVal,targetVal,timestep); focusVehicle.mDriveDynData.setAnalogInput(brake,PxVehicleDrive4W::eANALOG_INPUT_BRAKE); } //Process the handbrake. { const PxF32 riseRate=padSmoothing.mRiseRates[PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE]; const PxF32 fallRate=padSmoothing.mFallRates[PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE]; const PxF32 currentVal=focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE); const PxF32 targetVal=rawInputData.getAnalogHandbrake(); const PxF32 handbrake=processPositiveAnalogValue(riseRate,fallRate,currentVal,targetVal,timestep); focusVehicle.mDriveDynData.setAnalogInput(handbrake,PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE); } //Process the steer { const PxF32 vz=focusVehicle.computeForwardSpeed(); const PxF32 vzAbs=PxAbs(vz); const bool isInAir=focusVehicle.isInAir(); const PxF32 riseRate=padSmoothing.mRiseRates[PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT]; const PxF32 fallRate=padSmoothing.mFallRates[PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT]; const PxF32 currentVal=focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT)-focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_STEER_LEFT); const PxF32 targetVal=rawInputData.getAnalogSteer()*(isInAir ? 1.0f :steerVsForwardSpeedTable.getYVal(vzAbs)); const PxF32 steer=processAnalogValue(riseRate,fallRate,currentVal,targetVal,timestep); focusVehicle.mDriveDynData.setAnalogInput(0.0f, PxVehicleDrive4W::eANALOG_INPUT_STEER_LEFT); focusVehicle.mDriveDynData.setAnalogInput(steer, PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT); } }
void PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs (const PxVehicleKeySmoothingData& keySmoothing, const PxFixedSizeLookupTable<8>& steerVsForwardSpeedTable, const PxVehicleDrive4WRawInputData& rawInputData, const PxF32 timestep, PxVehicleDrive4W& focusVehicle) { const bool gearup=rawInputData.getGearUp(); const bool geardown=rawInputData.getGearDown(); focusVehicle.mDriveDynData.setGearDown(geardown); focusVehicle.mDriveDynData.setGearUp(gearup); const PxF32 accel=processDigitalValue(PxVehicleDrive4W::eANALOG_INPUT_ACCEL,keySmoothing,rawInputData.getDigitalAccel(),timestep,focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_ACCEL)); focusVehicle.mDriveDynData.setAnalogInput(accel,PxVehicleDrive4W::eANALOG_INPUT_ACCEL); const PxF32 brake=processDigitalValue(PxVehicleDrive4W::eANALOG_INPUT_BRAKE,keySmoothing,rawInputData.getDigitalBrake(),timestep,focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_BRAKE)); focusVehicle.mDriveDynData.setAnalogInput(brake,PxVehicleDrive4W::eANALOG_INPUT_BRAKE); const PxF32 handbrake=processDigitalValue(PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE,keySmoothing,rawInputData.getDigitalHandbrake(),timestep,focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE)); focusVehicle.mDriveDynData.setAnalogInput(handbrake,PxVehicleDrive4W::eANALOG_INPUT_HANDBRAKE); PxF32 steerLeft=processDigitalValue(PxVehicleDrive4W::eANALOG_INPUT_STEER_LEFT,keySmoothing,rawInputData.getDigitalSteerLeft(),timestep,focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_STEER_LEFT)); PxF32 steerRight=processDigitalValue(PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT,keySmoothing,rawInputData.getDigitalSteerRight(),timestep,focusVehicle.mDriveDynData.getAnalogInput(PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT)); const PxF32 vz=focusVehicle.computeForwardSpeed(); const PxF32 vzAbs=PxAbs(vz); const bool isInAir=focusVehicle.isInAir(); const PxF32 maxSteer=(isInAir ? 1.0f :steerVsForwardSpeedTable.getYVal(vzAbs)); const PxF32 steer=PxAbs(steerRight-steerLeft); if(steer>maxSteer) { const PxF32 k=maxSteer/steer; steerLeft*=k; steerRight*=k; } focusVehicle.mDriveDynData.setAnalogInput(steerLeft, PxVehicleDrive4W::eANALOG_INPUT_STEER_LEFT); focusVehicle.mDriveDynData.setAnalogInput(steerRight, PxVehicleDrive4W::eANALOG_INPUT_STEER_RIGHT); }
void UWheeledVehicleMovementComponent4W::UpdateSimulation(float DeltaTime) { if (PVehicleDrive == NULL) return; UpdatedPrimitive->GetBodyInstance()->ExecuteOnPhysicsReadWrite([&] { PxVehicleDrive4WRawInputData RawInputData; RawInputData.setAnalogAccel(ThrottleInput); RawInputData.setAnalogSteer(SteeringInput); RawInputData.setAnalogBrake(BrakeInput); RawInputData.setAnalogHandbrake(HandbrakeInput); if (!PVehicleDrive->mDriveDynData.getUseAutoGears()) { RawInputData.setGearUp(bRawGearUpInput); RawInputData.setGearDown(bRawGearDownInput); } // Convert from our curve to PxFixedSizeLookupTable PxFixedSizeLookupTable<8> SpeedSteerLookup; TArray<FRichCurveKey> SteerKeys = SteeringCurve.GetRichCurve()->GetCopyOfKeys(); const int32 MaxSteeringSamples = FMath::Min(8, SteerKeys.Num()); for (int32 KeyIdx = 0; KeyIdx < MaxSteeringSamples; KeyIdx++) { FRichCurveKey& Key = SteerKeys[KeyIdx]; SpeedSteerLookup.addPair(KmHToCmS(Key.Time), FMath::Clamp(Key.Value, 0.f, 1.f)); } PxVehiclePadSmoothingData SmoothData = { { ThrottleInputRate.RiseRate, BrakeInputRate.RiseRate, HandbrakeInputRate.RiseRate, SteeringInputRate.RiseRate, SteeringInputRate.RiseRate }, { ThrottleInputRate.FallRate, BrakeInputRate.FallRate, HandbrakeInputRate.FallRate, SteeringInputRate.FallRate, SteeringInputRate.FallRate } }; PxVehicleDrive4W* PVehicleDrive4W = (PxVehicleDrive4W*)PVehicleDrive; PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(SmoothData, SpeedSteerLookup, RawInputData, DeltaTime, false, *PVehicleDrive4W); }); }
void SampleVehicle_VehicleController::update(const PxF32 timestep, PxVehicleWheels& focusVehicle) { PX_ASSERT(eVEHICLE_TYPE_DRIVE4W==focusVehicle.getVehicleType()); PxVehicleDrive4W& vehDrive4W=(PxVehicleDrive4W&)focusVehicle; PxVehicleDriveDynData& driveDynData=vehDrive4W.mDriveDynData; //Toggle autogear flag if(mToggleAutoGears) { driveDynData.toggleAutoGears(); mToggleAutoGears = false; } //Store raw inputs in replay stream if in recording mode. //Set raw inputs from replay stream if in replay mode. //Store raw inputs from active stream in handy arrays so we don't need to worry //about which stream (live input or replay) is active. //Work out if we are using keys or gamepad controls depending on which is being used //(gamepad selected if both are being used). PxVehicleDrive4WRawInputData carRawInputs; processRawInputs(timestep,driveDynData.getUseAutoGears(),carRawInputs); //Work out if the car is to flip from reverse to forward gear or from forward gear to reverse. //Store if the car is moving slowly to help decide if the car is to toggle from reverse to forward in the next update. bool toggleAutoReverse = false; bool newIsMovingForwardSlowly = false; processAutoReverse(focusVehicle, driveDynData, carRawInputs, toggleAutoReverse, newIsMovingForwardSlowly); mIsMovingForwardSlowly = newIsMovingForwardSlowly; //If the car is to flip gear direction then switch gear as appropriate. if(toggleAutoReverse) { mInReverseMode = !mInReverseMode; if(mInReverseMode) { driveDynData.forceGearChange(PxVehicleGearsData::eREVERSE); } else { driveDynData.forceGearChange(PxVehicleGearsData::eFIRST); } } //If in reverse mode then swap the accel and brake. if(mInReverseMode) { if(mUseKeyInputs) { const bool accel=carRawInputs.getDigitalAccel(); const bool brake=carRawInputs.getDigitalBrake(); carRawInputs.setDigitalAccel(brake); carRawInputs.setDigitalBrake(accel); } else { const PxF32 accel=carRawInputs.getAnalogAccel(); const PxF32 brake=carRawInputs.getAnalogBrake(); carRawInputs.setAnalogAccel(brake); carRawInputs.setAnalogBrake(accel); } } // Now filter the raw input values and apply them to focus vehicle // as floats for brake,accel,handbrake,steer and bools for gearup,geardown. if(mUseKeyInputs) { PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs(gKeySmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,(PxVehicleDrive4W&)focusVehicle); } else { PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs(gCarPadSmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,(PxVehicleDrive4W&)focusVehicle); } }
void SampleVehicle_VehicleController::processAutoReverse (const PxVehicleWheels& focusVehicle, const PxVehicleDriveDynData& driveDynData, const PxVehicleDrive4WRawInputData& carRawInputs, bool& toggleAutoReverse, bool& newIsMovingForwardSlowly) const { newIsMovingForwardSlowly = false; toggleAutoReverse = false; if(driveDynData.getUseAutoGears()) { //If the car is travelling very slowly in forward gear without player input and the player subsequently presses the brake then we want the car to go into reverse gear //If the car is travelling very slowly in reverse gear without player input and the player subsequently presses the accel then we want the car to go into forward gear //If the car is in forward gear and is travelling backwards then we want to automatically put the car into reverse gear. //If the car is in reverse gear and is travelling forwards then we want to automatically put the car into forward gear. //(If the player brings the car to rest with the brake the player needs to release the brake then reapply it //to indicate they want to toggle between forward and reverse.) const bool prevIsMovingForwardSlowly=mIsMovingForwardSlowly; bool isMovingForwardSlowly=false; bool isMovingBackwards=false; const bool isInAir = focusVehicle.isInAir(); if(!isInAir) { bool accelRaw,brakeRaw,handbrakeRaw; if(mUseKeyInputs) { accelRaw=carRawInputs.getDigitalAccel(); brakeRaw=carRawInputs.getDigitalBrake(); handbrakeRaw=carRawInputs.getDigitalHandbrake(); } else { accelRaw=carRawInputs.getAnalogAccel() > 0 ? true : false; brakeRaw=carRawInputs.getAnalogBrake() > 0 ? true : false; handbrakeRaw=carRawInputs.getAnalogHandbrake() > 0 ? true : false; } const PxF32 forwardSpeed = focusVehicle.computeForwardSpeed(); const PxF32 forwardSpeedAbs = PxAbs(forwardSpeed); const PxF32 sidewaysSpeedAbs = PxAbs(focusVehicle.computeSidewaysSpeed()); const PxU32 currentGear = driveDynData.getCurrentGear(); const PxU32 targetGear = driveDynData.getTargetGear(); //Check if the car is rolling against the gear (backwards in forward gear or forwards in reverse gear). if(PxVehicleGearsData::eFIRST == currentGear && forwardSpeed < -THRESHOLD_ROLLING_BACKWARDS_SPEED) { isMovingBackwards = true; } else if(PxVehicleGearsData::eREVERSE == currentGear && forwardSpeed > THRESHOLD_ROLLING_BACKWARDS_SPEED) { isMovingBackwards = true; } //Check if the car is moving slowly. if(forwardSpeedAbs < THRESHOLD_FORWARD_SPEED && sidewaysSpeedAbs < THRESHOLD_SIDEWAYS_SPEED) { isMovingForwardSlowly=true; } //Now work if we need to toggle from forwards gear to reverse gear or vice versa. if(isMovingBackwards) { if(!accelRaw && !brakeRaw && !handbrakeRaw && (currentGear == targetGear)) { //The car is rolling against the gear and the player is doing nothing to stop this. toggleAutoReverse = true; } } else if(prevIsMovingForwardSlowly && isMovingForwardSlowly) { if((currentGear > PxVehicleGearsData::eNEUTRAL) && brakeRaw && !accelRaw && (currentGear == targetGear)) { //The car was moving slowly in forward gear without player input and is now moving slowly with player input that indicates the //player wants to switch to reverse gear. toggleAutoReverse = true; } else if(currentGear == PxVehicleGearsData::eREVERSE && accelRaw && !brakeRaw && (currentGear == targetGear)) { //The car was moving slowly in reverse gear without player input and is now moving slowly with player input that indicates the //player wants to switch to forward gear. toggleAutoReverse = true; } } //If the car was brought to rest through braking then the player needs to release the brake then reapply //to indicate that the gears should toggle between reverse and forward. if(isMovingForwardSlowly && !brakeRaw && !accelRaw && !handbrakeRaw) { newIsMovingForwardSlowly = true; } } } }
void SampleVehicle_VehicleController::processRawInputs (const PxF32 dtime, const bool useAutoGears, PxVehicleDrive4WRawInputData& rawInputData) { // Keyboard { if(mRecord) { if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES) { mKeyboardAccelValues[mNumSamples] = mKeyPressedAccel; mKeyboardBrakeValues[mNumSamples] = mKeyPressedBrake; mKeyboardHandbrakeValues[mNumSamples] = mKeyPressedHandbrake; mKeyboardSteerLeftValues[mNumSamples] = mKeyPressedSteerLeft; mKeyboardSteerRightValues[mNumSamples] = mKeyPressedSteerRight; mKeyboardGearupValues[mNumSamples] = mKeyPressedGearUp; mKeyboardGeardownValues[mNumSamples] = mKeyPressedGearDown; } } else if(mReplay) { if(mNumSamples<mNumRecordedSamples) { mKeyPressedAccel = mKeyboardAccelValues[mNumSamples]; mKeyPressedBrake = mKeyboardBrakeValues[mNumSamples]; mKeyPressedHandbrake = mKeyboardHandbrakeValues[mNumSamples]; mKeyPressedSteerLeft = mKeyboardSteerLeftValues[mNumSamples]; mKeyPressedSteerRight = mKeyboardSteerRightValues[mNumSamples]; mKeyPressedGearUp = mKeyboardGearupValues[mNumSamples]; mKeyPressedGearDown = mKeyboardGeardownValues[mNumSamples]; } } rawInputData.setDigitalAccel(mKeyPressedAccel); rawInputData.setDigitalBrake(mKeyPressedBrake); rawInputData.setDigitalHandbrake(mKeyPressedHandbrake); rawInputData.setDigitalSteerLeft(mKeyPressedSteerLeft); rawInputData.setDigitalSteerRight(mKeyPressedSteerRight); rawInputData.setGearUp(mKeyPressedGearUp); rawInputData.setGearDown(mKeyPressedGearDown); mUseKeyInputs= (mKeyPressedAccel || mKeyPressedBrake || mKeyPressedHandbrake || mKeyPressedSteerLeft || mKeyPressedSteerRight || mKeyPressedGearUp || mKeyPressedGearDown); } // Gamepad { if(mRecord) { if(mNumSamples<MAX_NUM_RECORD_REPLAY_SAMPLES) { mGamepadAccelValues[mNumSamples] = mGamepadAccel; mGamepadCarBrakeValues[mNumSamples] = mGamepadCarBrake; mGamepadCarSteerValues[mNumSamples] = mGamepadCarSteer; mGamepadGearupValues[mNumSamples] = mGamepadGearup; mGamepadGeardownValues[mNumSamples] = mGamepadGeardown; mGamepadCarHandbrakeValues[mNumSamples] = mGamepadCarHandbrake; } } else if(mReplay) { if(mNumSamples<mNumRecordedSamples) { mGamepadAccel = mGamepadAccelValues[mNumSamples]; mGamepadCarBrake = mGamepadCarBrakeValues[mNumSamples]; mGamepadCarSteer = mGamepadCarSteerValues[mNumSamples]; mGamepadGearup = mGamepadGearupValues[mNumSamples]; mGamepadGeardown = mGamepadGeardownValues[mNumSamples]; mGamepadCarHandbrake = mGamepadCarHandbrakeValues[mNumSamples]; } } if(mGamepadAccel<0.0f || mGamepadAccel>1.01f) getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal accel value from gamepad", __FILE__, __LINE__); if(mGamepadCarBrake<0.0f || mGamepadCarBrake>1.01f) getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal brake value from gamepad", __FILE__, __LINE__); if(PxAbs(mGamepadCarSteer)>1.01f) getSampleErrorCallback().reportError(PxErrorCode::eINTERNAL_ERROR, "Illegal steer value from gamepad", __FILE__, __LINE__); if(mUseKeyInputs && ((mGamepadAccel+mGamepadCarBrake+mGamepadCarSteer)!=0.0f || mGamepadGearup || mGamepadGeardown || mGamepadCarHandbrake)) { mUseKeyInputs=false; } if(!mUseKeyInputs) { rawInputData.setAnalogAccel(mGamepadAccel); rawInputData.setAnalogBrake(mGamepadCarBrake); rawInputData.setAnalogHandbrake(mGamepadCarHandbrake ? 1.0f : 0.0f); rawInputData.setAnalogSteer(mGamepadCarSteer); rawInputData.setGearUp(mGamepadGearup); rawInputData.setGearDown(mGamepadGeardown); } } if(useAutoGears && (rawInputData.getGearDown() || rawInputData.getGearUp())) { rawInputData.setGearDown(false); rawInputData.setGearUp(false); } mNumSamples++; }
void SampleVehicle_VehicleController::update(const PxF32 timestep, const PxVehicleWheelQueryResult& vehicleWheelQueryResults, PxVehicleWheels& focusVehicle) { PxVehicleDriveDynData* driveDynData=NULL; bool isTank=false; PxVehicleDriveTankControlModel::Enum tankDriveModel=PxVehicleDriveTankControlModel::eSTANDARD; switch(focusVehicle.getVehicleType()) { case PxVehicleTypes::eDRIVE4W: { PxVehicleDrive4W& vehDrive4W=(PxVehicleDrive4W&)focusVehicle; driveDynData=&vehDrive4W.mDriveDynData; isTank=false; } break; case PxVehicleTypes::eDRIVENW: { PxVehicleDriveNW& vehDriveNW=(PxVehicleDriveNW&)focusVehicle; driveDynData=&vehDriveNW.mDriveDynData; isTank=false; } break; case PxVehicleTypes::eDRIVETANK: { PxVehicleDriveTank& vehDriveTank=(PxVehicleDriveTank&)focusVehicle; driveDynData=&vehDriveTank.mDriveDynData; isTank=true; tankDriveModel=vehDriveTank.getDriveModel(); } break; default: PX_ASSERT(false); break; } //Toggle autogear flag if(mToggleAutoGears) { driveDynData->toggleAutoGears(); mToggleAutoGears = false; } //Store raw inputs in replay stream if in recording mode. //Set raw inputs from replay stream if in replay mode. //Store raw inputs from active stream in handy arrays so we don't need to worry //about which stream (live input or replay) is active. //Work out if we are using keys or gamepad controls depending on which is being used //(gamepad selected if both are being used). PxVehicleDrive4WRawInputData carRawInputs; PxVehicleDriveTankRawInputData tankRawInputs(tankDriveModel); if(!isTank) { processRawInputs(timestep,driveDynData->getUseAutoGears(),carRawInputs); } else { processRawInputs(timestep,driveDynData->getUseAutoGears(),tankRawInputs); } //Work out if the car is to flip from reverse to forward gear or from forward gear to reverse. bool toggleAutoReverse = false; bool newIsMovingForwardSlowly = false; if(!isTank) { processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, carRawInputs, toggleAutoReverse, newIsMovingForwardSlowly); } else { processAutoReverse(focusVehicle, *driveDynData, vehicleWheelQueryResults, tankRawInputs, toggleAutoReverse, newIsMovingForwardSlowly); } mIsMovingForwardSlowly = newIsMovingForwardSlowly; //If the car is to flip gear direction then switch gear as appropriate. if(toggleAutoReverse) { mInReverseMode = !mInReverseMode; if(mInReverseMode) { driveDynData->forceGearChange(PxVehicleGearsData::eREVERSE); } else { driveDynData->forceGearChange(PxVehicleGearsData::eFIRST); } } //If in reverse mode then swap the accel and brake. if(mInReverseMode) { if(mUseKeyInputs) { if(!isTank) { const bool accel=carRawInputs.getDigitalAccel(); const bool brake=carRawInputs.getDigitalBrake(); carRawInputs.setDigitalAccel(brake); carRawInputs.setDigitalBrake(accel); } else { //Keyboard controls for tank not implemented yet. const bool accelLeft=tankRawInputs.getDigitalLeftThrust(); const bool accelRight=tankRawInputs.getDigitalRightThrust(); const bool brakeLeft=tankRawInputs.getDigitalLeftBrake(); const bool brakeRight=tankRawInputs.getDigitalRightBrake(); tankRawInputs.setDigitalLeftThrust(brakeLeft); tankRawInputs.setDigitalRightThrust(brakeRight); tankRawInputs.setDigitalLeftBrake(accelLeft); tankRawInputs.setDigitalRightBrake(accelRight); } } else { if(!isTank) { const PxF32 accel=carRawInputs.getAnalogAccel(); const PxF32 brake=carRawInputs.getAnalogBrake(); carRawInputs.setAnalogAccel(brake); carRawInputs.setAnalogBrake(accel); } else if(PxVehicleDriveTankControlModel::eSPECIAL==tankDriveModel) { const PxF32 thrustLeft=tankRawInputs.getAnalogLeftThrust(); const PxF32 thrustRight=tankRawInputs.getAnalogRightThrust(); tankRawInputs.setAnalogLeftThrust(-thrustLeft); tankRawInputs.setAnalogRightThrust(-thrustRight); } else { const PxF32 thrustLeft=tankRawInputs.getAnalogLeftThrust(); const PxF32 thrustRight=tankRawInputs.getAnalogRightThrust(); const PxF32 brakeLeft=tankRawInputs.getAnalogLeftBrake(); const PxF32 brakeRight=tankRawInputs.getAnalogRightBrake(); tankRawInputs.setAnalogLeftThrust(brakeLeft); tankRawInputs.setAnalogLeftBrake(thrustLeft); tankRawInputs.setAnalogRightThrust(brakeRight); tankRawInputs.setAnalogRightBrake(thrustRight); } } } // Now filter the raw input values and apply them to focus vehicle // as floats for brake,accel,handbrake,steer and bools for gearup,geardown. if(mUseKeyInputs) { if(!isTank) { const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults); PxVehicleDrive4WSmoothDigitalRawInputsAndSetAnalogInputs (gKeySmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,isInAir,(PxVehicleDrive4W&)focusVehicle); } else { PxVehicleDriveTankSmoothDigitalRawInputsAndSetAnalogInputs (gKeySmoothingData,tankRawInputs,timestep,(PxVehicleDriveTank&)focusVehicle); } } else { if(!isTank) { const bool isInAir = PxVehicleIsInAir(vehicleWheelQueryResults); PxVehicleDrive4WSmoothAnalogRawInputsAndSetAnalogInputs (gCarPadSmoothingData,gSteerVsForwardSpeedTable,carRawInputs,timestep,isInAir,(PxVehicleDrive4W&)focusVehicle); } else { PxVehicleDriveTankSmoothAnalogRawInputsAndSetAnalogInputs (gTankPadSmoothingData,tankRawInputs,timestep,(PxVehicleDriveTank&)focusVehicle); } } }