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