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 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::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::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); } } }