1687 lines
51 KiB
C++
1687 lines
51 KiB
C++
//=============================================================================
|
|
// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File: physicslocomotioncontrollerforces.cpp
|
|
//
|
|
// Description: moved some methods into a different cpp file 'cause it was getting
|
|
// too big
|
|
//
|
|
// History: May 13, 2001 + Created -- gmayer
|
|
//
|
|
//=============================================================================
|
|
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
|
|
#include <simcommon/simstate.hpp>
|
|
#include <simcommon/simstatearticulated.hpp>
|
|
#include <simcommon/simulatedobject.hpp>
|
|
#include <simphysics/articulatedphysicsobject.hpp>
|
|
#include <simphysics/physicsobject.hpp>
|
|
#include <simcommon/simenvironment.hpp>
|
|
#include <simcollision/collisionobject.hpp>
|
|
#include <simcollision/collisionvolume.hpp>
|
|
|
|
#include <raddebug.hpp>
|
|
|
|
#include <gameflow/gameflow.h>
|
|
#include <worldsim/vehiclecentral.h>
|
|
#include <worldsim/avatarmanager.h>
|
|
|
|
|
|
#include <cheats/cheatinputsystem.h>
|
|
|
|
#include <poser/pose.hpp>
|
|
#include <poser/poseengine.hpp>
|
|
#include <poser/posedriver.hpp>
|
|
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
|
|
#include <worldsim/redbrick/physicslocomotion.h>
|
|
#include <worldsim/redbrick/vehicle.h>
|
|
#include <worldsim/redbrick/wheel.h>
|
|
|
|
#include <camera/supercammanager.h>
|
|
#include <camera/supercamcentral.h>
|
|
|
|
#ifdef WORKING_ON_GREG_PHIZTEST_RIGHT_NOW
|
|
#include "../../../../users/greg/phiztest/code/worldsim/redbrick/phizsim.h" // just for a temp hack using world up
|
|
#else
|
|
#include <worldsim/worldphysicsmanager.h>
|
|
#endif
|
|
|
|
#include <render/IntersectManager/IntersectManager.h>
|
|
|
|
using namespace sim;
|
|
|
|
|
|
// test of terrain friction
|
|
// enum value
|
|
const float TF_Road = 1.0f; // 0
|
|
const float TF_Grass = 0.7f; // 1
|
|
const float TF_Sand = 0.6f; // 2
|
|
const float TF_Gravel = 0.6f; // 3
|
|
const float TF_Water = 0.6f; // 4
|
|
const float TF_Wood = 1.0f; // 5
|
|
const float TF_Metal = 1.0f; // 6
|
|
const float TF_Dirt = 0.6f; // 7
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::ApplyControllerForces2
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (float dt)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::ApplyControllerForces2(float dt)
|
|
{
|
|
// for each wheel, calculate the total requested force, and then
|
|
// chop it based on the force circle?
|
|
|
|
mVehicle->mBurnoutLevel = 0.0f;
|
|
|
|
int i;
|
|
rmt::Vector totalForce[4];
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
totalForce[i].Clear();
|
|
|
|
|
|
if(/*mVehicle->mWheels[i]->mWheelInCollision &&*/ !(mVehicle->mWheels[i]->mWheelBottomedOutThisFrame))
|
|
{
|
|
|
|
// TODO
|
|
// only do loop if wheel in collision?
|
|
// else reset some shit like the wheel state
|
|
|
|
// TODO
|
|
// how about wheel bottomed out this frame?
|
|
// only affects steering? or all?
|
|
|
|
//rmt::Vector totalForce(0.0f, 0.0f, 0.0f);
|
|
|
|
GasForce2(totalForce[i], i, dt);
|
|
// TODO - make sure you set skid level and renderspinuprate and shit like that.
|
|
|
|
BrakeForce2(totalForce[i], i, dt);
|
|
// TODO - somewhere else add code to bring car to a standstill
|
|
|
|
ReverseForce2(totalForce[i], i);
|
|
|
|
EBrakeEffect(totalForce[i], i);
|
|
|
|
SteeringForce2(totalForce[i], i, dt);
|
|
|
|
|
|
|
|
}
|
|
//else
|
|
{
|
|
// reset wheel state?
|
|
}
|
|
|
|
}
|
|
|
|
// DoughnutTest(); I think we need a state for this.
|
|
|
|
|
|
// test if we should change vehicle state
|
|
// TODO - test for airborn etc.. before calling this?
|
|
|
|
TestControllerForces(totalForce); // <- mVehicleState only changed in here!
|
|
|
|
// new - Mar 12, 2003
|
|
//
|
|
// use state to set "target" steering force.
|
|
//
|
|
// move towards target based on time rate
|
|
//
|
|
//
|
|
|
|
// next step - make let-off gas get you out of slip state
|
|
|
|
// how does gasreducinggrip thing fit into all of this?
|
|
|
|
// next step - make skid level 0 to 1 based on have we gotten to our target level yet?
|
|
|
|
//UpdateSteeringForce(dt);
|
|
|
|
|
|
// not doing this anymore - only step is really to set good skid level
|
|
|
|
|
|
|
|
SetSkidLevel();
|
|
|
|
// TODO - actually limit locomotive and other forces??????
|
|
|
|
// cheap and easy test of terrain friction:
|
|
//ApplyTerrainFriction(totalForce);
|
|
|
|
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
((ArticulatedPhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject(-1)))->AddForce(totalForce[i], &(mForceApplicationPoints[i]));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::UpdateSteeringForce
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (float dt)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
/*
|
|
|
|
// I don't think plum wants this now
|
|
|
|
void PhysicsLocomotion::UpdateSteeringForce(float dt)
|
|
{
|
|
// default changerate: 50 units / second
|
|
//static float changeRate = 10.0f;
|
|
//static float changeRate = 5.0f;
|
|
static float changeRate = 1.0f;
|
|
|
|
float changethisframe = changeRate * dt;
|
|
|
|
float target = 80.0f; // just some default - should never use
|
|
|
|
|
|
// if we are not VT_USER, switch immediately.
|
|
|
|
|
|
if(mVehicle->mVehicleState == VS_NORMAL)
|
|
{
|
|
// "target" - mVehicle->mDesignerParams.mDpTireLateralResistanceNormal;
|
|
|
|
target = mVehicle->mDesignerParams.mDpTireLateralResistanceNormal;
|
|
|
|
}
|
|
else if(mVehicle->mVehicleState == VS_EBRAKE_SLIP)
|
|
{
|
|
// "target" - mVehicle->mDesignerParams.mDpTireLateralResistanceSlip
|
|
|
|
target = mVehicle->mDesignerParams.mDpTireLateralResistanceSlip;
|
|
|
|
}
|
|
else
|
|
{
|
|
// regular slip
|
|
// "target" - mVehicle->mDesignerParams.mDpTireLateralResistanceSlipNoEBrake
|
|
|
|
target = mVehicle->mDesignerParams.mDpTireLateralResistanceSlipNoEBrake;
|
|
|
|
}
|
|
|
|
if(mCurrentSteeringForce > target)
|
|
{
|
|
if( (mCurrentSteeringForce - changethisframe) > target)
|
|
{
|
|
mCurrentSteeringForce -= changethisframe;
|
|
}
|
|
else
|
|
{
|
|
mCurrentSteeringForce = target;
|
|
}
|
|
}
|
|
else if(mCurrentSteeringForce < target)
|
|
{
|
|
if((mCurrentSteeringForce + changethisframe) < target)
|
|
{
|
|
mCurrentSteeringForce += changethisframe;
|
|
}
|
|
else
|
|
{
|
|
mCurrentSteeringForce = target;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::ApplyTerrainFriction
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector* totalForce)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::ApplyTerrainFriction(rmt::Vector* totalForce)
|
|
{
|
|
int i;
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
switch (mTerrainIntersectCache[i].mTerrainType)
|
|
{
|
|
|
|
case TT_Road:
|
|
totalForce[i].Scale(TF_Road);
|
|
break;
|
|
|
|
case TT_Grass:
|
|
totalForce[i].Scale(TF_Grass);
|
|
break;
|
|
|
|
case TT_Dirt:
|
|
totalForce[i].Scale(TF_Dirt);
|
|
break;
|
|
|
|
case TT_Water:
|
|
totalForce[i].Scale(TF_Water);
|
|
break;
|
|
|
|
case TT_Gravel:
|
|
totalForce[i].Scale(TF_Gravel);
|
|
break;
|
|
|
|
case TT_Wood:
|
|
totalForce[i].Scale(TF_Wood);
|
|
break;
|
|
|
|
case TT_Sand:
|
|
totalForce[i].Scale(TF_Sand);
|
|
break;
|
|
|
|
case TT_Metal:
|
|
totalForce[i].Scale(TF_Metal);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::GasForce2
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector& forceResult, float dt, int wheelNum)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::GasForce2(rmt::Vector& forceResult, int wheelNum, float dt)
|
|
{
|
|
if(mVehicle->mWheels[wheelNum]->mDriveWheel)
|
|
{
|
|
float desiredForceMag = 0.0f;
|
|
|
|
// burnout check
|
|
//
|
|
// TODO
|
|
// only high powered vehicles should do this? or do for longer?
|
|
//if(mVehicle->mDesignerParams.mDpGasScale >
|
|
|
|
// maybe the % topspeed for which you do it is greater for high powered vehicles
|
|
|
|
// try mapping 5.0 (average value) to %20 topspeed
|
|
//static float burnouttunebullshit = 0.04f;
|
|
const float burnouttunebullshit = 0.03f;
|
|
|
|
//static float gasdecrease = 0.5f;
|
|
const float gasdecrease = 0.75f;
|
|
|
|
//static float burnoutsound = 0.7f;
|
|
const float gasvalue = 0.99f;
|
|
|
|
//float burnoutRange = mVehicle->mDesignerParams.mDpGasScale * burnouttunebullshit;
|
|
|
|
float burnoutRange = mVehicle->mDesignerParams.mDpBurnoutRange;
|
|
|
|
// need new designer param for this percent of top speed
|
|
//
|
|
// use same value for doing doughnut?
|
|
|
|
// !! TODO - get hard/soft press on ps2!
|
|
//
|
|
// this is not gonna happen
|
|
// if you put the ps2 button into analog mode, you gotta mash it to get _anything_!
|
|
|
|
if(mVehicle->mPercentOfTopSpeed < burnoutRange && mVehicle->mGas > gasvalue && mVehicle->mVehicleType == VT_USER)
|
|
{
|
|
// burnout
|
|
//
|
|
// skid, smoke, spin and non loco
|
|
|
|
// the regular calculation would give this:
|
|
//desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mSlipGasModifier * mVehicle->mGas * mVehicle->mDesignerParams.mDpMass;
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
//desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mSlipGasModifier * /*mVehicle->mGas*/ 1.0f * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mSlipGasModifier * mVehicle->mGas * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
|
|
desiredForceMag *= gasdecrease;
|
|
|
|
//mVehicle->mBurnoutLevel = burnoutsound;
|
|
mVehicle->mBurnoutLevel = (1.0f - (0.5f * (mVehicle->mPercentOfTopSpeed / burnoutRange)));
|
|
if(mVehicle->mBurnoutLevel < 0.0f)
|
|
{
|
|
mVehicle->mBurnoutLevel = 0.0f;
|
|
}
|
|
|
|
|
|
|
|
// additional test for donut?
|
|
// here?
|
|
if(rmt::Fabs(mVehicle->mUnmodifiedInputWheelTurnAngle) > 0.6)
|
|
{
|
|
//const float magicshit = 4.0f;
|
|
//float magicshit = 9.0f;
|
|
float magicshit = mVehicle->mDesignerParams.mDpDonutTorque;
|
|
|
|
rmt::Vector etorque = mVehicle->mVehicleUp;
|
|
float dir = 0.0f;
|
|
if(mVehicle->mWheelTurnAngle > 0.0f)
|
|
{
|
|
dir = 1.0f;
|
|
}
|
|
if(mVehicle->mWheelTurnAngle < 0.0f)
|
|
{
|
|
dir = -1.0f;
|
|
}
|
|
|
|
//float speedeffect = mVehicle->mPercentOfTopSpeed * 2.0f;
|
|
//if(speedeffect > 1.0f)
|
|
//{
|
|
// speedeffect = 1.0f;
|
|
//}
|
|
|
|
float speedmodifier = 1.0f - mVehicle->mPercentOfTopSpeed;
|
|
|
|
etorque.Scale(magicshit * dir * mVehicle->mDesignerParams.mDpMass * speedmodifier);
|
|
|
|
//mVehicle->mPhObj->AddTorque(etorque);
|
|
|
|
((ArticulatedPhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject(-1)))->AddTorque(etorque);
|
|
|
|
}
|
|
else
|
|
{
|
|
// speed burst build up here....
|
|
|
|
if(mVehicle->mEBrake > 0.5f)
|
|
{
|
|
mVehicle->mSpeedBurstTimer += dt;
|
|
mVehicle->mBuildingUpSpeedBurst = true;
|
|
mVehicle->mDoSpeedBurst = false;
|
|
|
|
//if(mVehicle->mSpeedBurstTimer > 3.0f)
|
|
if(mVehicle->mSpeedBurstTimer > mVehicle->mDesignerParams.mDpMaxSpeedBurstTime)
|
|
{
|
|
mVehicle->mSpeedBurstTimer = mVehicle->mDesignerParams.mDpMaxSpeedBurstTime;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(mVehicle->mBuildingUpSpeedBurst)
|
|
{
|
|
rAssert(mVehicle->mDoSpeedBurst == false);
|
|
// just let off the button
|
|
mVehicle->mBuildingUpSpeedBurst = false;
|
|
mVehicle->mDoSpeedBurst = true;
|
|
|
|
SuperCamCentral* scc = GetSuperCamManager()->GetSCC(0);
|
|
SuperCam* sc = scc->GetActiveSuperCam();
|
|
|
|
mVehicle->mFOVToRestore = sc->GetFOV();
|
|
|
|
mVehicle->mSpeedBurstTimerHalf = mVehicle->mSpeedBurstTimer * 0.5f;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//!
|
|
// TODO
|
|
//
|
|
// take analog gas usage out of here?
|
|
|
|
if(mVehicle->mGas > 0.0f)
|
|
{
|
|
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
|
|
if(mVehicle->mVehicleState == VS_NORMAL)
|
|
{
|
|
if(mVehicle->mVehicleType == VT_USER && mVehicle->mPercentOfTopSpeed > mVehicle->mDesignerParams.mDpGasScaleSpeedThreshold)
|
|
{
|
|
// use high speed gas scale
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpHighSpeedGasScale * mVehicle->mSlipGasModifier * mVehicle->mGas * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
|
|
}
|
|
else
|
|
{
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mSlipGasModifier * mVehicle->mGas * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// slip
|
|
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpSlipGasScale * mVehicle->mSlipGasModifier * mVehicle->mGas* mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
|
|
}
|
|
}
|
|
|
|
// if we get out of speedburst range we should probably null out
|
|
|
|
|
|
//mVehicle->mBuildingUpSpeedBurst = false;
|
|
//mVehicle->mSpeedBurstTimer = 0.0f;
|
|
//mVehicle->mDoSpeedBurst = false;
|
|
|
|
}
|
|
|
|
|
|
// regardless of burnout or normal
|
|
// test for wheelie down here
|
|
if(mVehicle->mPercentOfTopSpeed < mVehicle->mDesignerParams.mDpWheelieRange && mVehicle->mGas > gasvalue && mVehicle->mVehicleType == VT_USER)
|
|
{
|
|
// set wheelie offsets
|
|
|
|
if(!(mVehicle->mDoingWheelie) && !(mVehicle->mWeebleOn))
|
|
{
|
|
rmt::Vector wheelie = mVehicle->mCMOffset;
|
|
|
|
wheelie.y += mVehicle->mDesignerParams.mDpWheelieYOffset;
|
|
wheelie.z += mVehicle->mDesignerParams.mDpWheelieZOffset;
|
|
|
|
//mVehicle->mPhObj->SetExternalCMOffset(wheelie);
|
|
((ArticulatedPhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject(-1)))->SetExternalCMOffset(wheelie);
|
|
|
|
mVehicle->mDoingWheelie = true;
|
|
}
|
|
|
|
|
|
}
|
|
else if(mVehicle->mDoingWheelie)
|
|
{
|
|
//mVehicle->mPhObj->SetExternalCMOffset(mVehicle->mCMOffset);
|
|
((ArticulatedPhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject(-1)))->SetExternalCMOffset(mVehicle->mCMOffset);
|
|
mVehicle->mDoingWheelie = false;
|
|
}
|
|
|
|
|
|
|
|
rmt::Vector force = mVehicle->mVehicleTransverse;
|
|
//force.CrossProduct(mTerrainIntersectCache[wheelNum].planeNorm);
|
|
force.CrossProduct(mIntersectNormalUsed[wheelNum]);
|
|
|
|
// just in case
|
|
force.NormalizeSafe();
|
|
|
|
|
|
if(mVehicle->mDoSpeedBurst)
|
|
{
|
|
desiredForceMag *= 2.0f;
|
|
mVehicle->mSpeedBurstTimer -= dt;
|
|
|
|
SuperCamCentral* scc = GetSuperCamManager()->GetSCC(0);
|
|
SuperCam* sc = scc->GetActiveSuperCam();
|
|
|
|
|
|
if(mVehicle->mSpeedBurstTimer <= 0.0f)
|
|
{
|
|
mVehicle->mSpeedBurstTimer = 0.0f;
|
|
mVehicle->mDoSpeedBurst = false;
|
|
|
|
//sc->SetFOV(mVehicle->mFOVToRestore); - this shoudl all be moved to super cam
|
|
}
|
|
else
|
|
{
|
|
//static float camhack = 1.0f;
|
|
//static float camhack = 0.015f;
|
|
float camhack = 0.015f;
|
|
float fov;
|
|
|
|
if(mVehicle->mSpeedBurstTimer > (mVehicle->mSpeedBurstTimerHalf * 1.5f))
|
|
{
|
|
fov = sc->GetFOV();
|
|
fov = fov + camhack;
|
|
//sc->SetFOV(fov); this shoudl all be moved to super cam
|
|
}
|
|
else if(mVehicle->mSpeedBurstTimer < (mVehicle->mSpeedBurstTimerHalf * 0.5f))
|
|
{
|
|
fov = sc->GetFOV();
|
|
fov = fov - camhack;
|
|
//sc->SetFOV(fov); this shoudl all be moved to super cam
|
|
}
|
|
// else do nothing in the mid-range
|
|
}
|
|
|
|
}
|
|
|
|
if(mVehicle->mDoingJumpBoost)
|
|
{
|
|
// want to boost the jump
|
|
// proportioal to the cars power, and current speed, and should have gas held down
|
|
if(mVehicle->mGas > 0.5f && mVehicle->mPercentOfTopSpeed > 0.3f && mVehicle->GetSpeedKmh() < 140.0f)
|
|
{
|
|
//static float gasscaleboosteffect = 0.1f;
|
|
//const float gasscaleboosteffect = 0.08f;
|
|
float boostEffect = 0.0f;
|
|
if( GetGameFlow()->GetCurrentContext() == CONTEXT_SUPERSPRINT )
|
|
{
|
|
// do special boost only for AI in supersprint
|
|
rAssert( mVehicle->mVehicleType == VT_AI );
|
|
boostEffect = 1.4f;
|
|
}
|
|
else
|
|
{
|
|
boostEffect = 0.07f;
|
|
}
|
|
const float gasscaleboosteffect = boostEffect;
|
|
|
|
//float multiplier = 1.0f + /* mVehicle->mPercentOfTopSpeed */ + (mVehicle->mDesignerParams.mDpGasScale * gasscaleboosteffect);
|
|
const float avgGasScale = 7.0f;
|
|
|
|
float multiplier = 1.0f + /* mVehicle->mPercentOfTopSpeed */ + (avgGasScale * gasscaleboosteffect);
|
|
|
|
desiredForceMag *= multiplier;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//rmt::Vector force = mVehicle->mVehicleFacing;
|
|
|
|
// just in case
|
|
// you only get speed burst of buildup if you hold down gas
|
|
if(mVehicle->mGas == 0.0f && (mVehicle->mDoSpeedBurst || mVehicle->mSpeedBurstTimer > 0.0f))
|
|
{
|
|
mVehicle->mSpeedBurstTimer = 0.0f;
|
|
mVehicle->mDoSpeedBurst = false;
|
|
}
|
|
|
|
if(GetAvatarManager()->GetAvatarForPlayer(0)->GetVehicle() == mVehicle)
|
|
{
|
|
if(GetCheatInputSystem()->IsCheatEnabled(CHEAT_ID_HIGH_ACCELERATION))
|
|
{
|
|
desiredForceMag *= 2.0f;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
force.Scale(desiredForceMag);
|
|
|
|
forceResult.Add(force);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::DoughnutTest
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (int wheelNum)
|
|
//
|
|
// Return: float
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::DoughnutTest()
|
|
{
|
|
// already know this is a drive wheel
|
|
/*
|
|
static float test1 = 0.3f;
|
|
static float test2 = 0.8f;
|
|
static float gastest = 0.9f;
|
|
static float amount = 18.0f;
|
|
|
|
if( mVehicle->mPercentOfTopSpeed < test1 && rmt::Fabs(mVehicle->mUnmodifiedInputWheelTurnAngle) > test2 && mVehicle->mGas > gastest)
|
|
{
|
|
rmt::Vector doughnutTorque = mVehicle->mVehicleUp;
|
|
|
|
// nasty hardcoded logic
|
|
// -ve is left turn
|
|
|
|
if(mVehicle->mUnmodifiedInputWheelTurnAngle < 0.0f)
|
|
{
|
|
doughnutTorque.Scale(-amount * mVehicle->mDesignerParams.mDpMass);
|
|
}
|
|
else
|
|
{
|
|
doughnutTorque.Scale(amount* mVehicle->mDesignerParams.mDpMass);
|
|
}
|
|
|
|
mVehicle->mPhObj->AddTorque(doughnutTorque);
|
|
|
|
}
|
|
*/
|
|
}
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::BrakeForce2
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector& forceResult, int wheelNum)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::BrakeForce2(rmt::Vector& forceResult, int wheelNum, float dt)
|
|
{
|
|
|
|
//mBrakeTimer = 0.0f;
|
|
//mBrakeActingAsReverse = false;
|
|
|
|
// this is exactly reverse force
|
|
|
|
if(mVehicle->mWheels[wheelNum]->mDriveWheel)
|
|
{
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
// if we're coming to a stop we want to use brakescale
|
|
// if we're going backwards want to use gasscale
|
|
|
|
float desiredForceMag = 0.0f;
|
|
|
|
|
|
float proj = mVehicle->mVelocityCM.DotProduct(mVehicle->mVehicleFacing);
|
|
|
|
// don't want just any slight backwards motion to trigger
|
|
const float cos120 = -0.5f;
|
|
|
|
//if(proj < cos120)
|
|
if(proj < 0.0f)
|
|
{
|
|
// going backwards
|
|
|
|
// same accel and top speed reverse as forward
|
|
|
|
if(mVehicle->mVehicleType == VT_USER && mVehicle->mPercentOfTopSpeed > mVehicle->mDesignerParams.mDpGasScaleSpeedThreshold)
|
|
{
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpHighSpeedGasScale * mVehicle->mBrake * mVehicle->mDesignerParams.mDpMass;
|
|
}
|
|
else
|
|
{
|
|
desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mBrake * mVehicle->mDesignerParams.mDpMass;
|
|
}
|
|
|
|
if(mVehicle->mSpeedKmh < 50.0f)
|
|
{
|
|
mVehicle->mBurnoutLevel = mVehicle->mBrake;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(mVehicle->mGas > 0.1f)
|
|
{
|
|
desiredForceMag = (mVehicle->mDesignerParams.mDpGasScale) * mVehicle->mBrake * mVehicle->mDesignerParams.mDpMass * 0.75f;// magic number is gasdecrease when doing burnout
|
|
}
|
|
else
|
|
{
|
|
desiredForceMag = (mVehicle->mDesignerParams.mDpBrakeScale + 3.0f) * mVehicle->mBrake * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rmt::Vector force = mVehicle->mVehicleFacing;
|
|
force.Scale(-1.0f * desiredForceMag);
|
|
|
|
// TODO - make this a state?
|
|
// so that we can reduce the grip on the rear wheels and totally up the front?
|
|
|
|
forceResult.Add(force);
|
|
|
|
// if we are actually going in reverse
|
|
//if(mVehicle->mVehicleFacing.DotProduct(mVehicle->mVelocityCM) < 0.0f)
|
|
//{
|
|
// mVehicle->mBurnoutLevel = mVehicle->mBrake;
|
|
//}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
//static float test = 0.8f;
|
|
const float test = 0.8f;
|
|
|
|
//const float lowspeed = 1.0f;
|
|
const float lowspeed = 1.0f;
|
|
|
|
|
|
|
|
|
|
// copy of test from rolling friction -
|
|
// holding brake down should hold car perfectly still....
|
|
if(mVehicle->mBrakeActingAsReverse)
|
|
{
|
|
if(mVehicle->mSpeed > lowspeed)
|
|
{
|
|
float desiredForceMag = mVehicle->mBrake * mVehicle->mDesignerParams.mDpBrakeScale * mVehicle->mDesignerParams.mDpMass;
|
|
|
|
rmt::Vector force = mSuspensionPointVelocities[wheelNum];
|
|
|
|
force.NormalizeSafe();
|
|
force.Scale(-1.0f * desiredForceMag);
|
|
|
|
forceResult.Add(force);
|
|
}
|
|
else if(mVehicle->mBrake > 0.7f)
|
|
{
|
|
// TODO - this may have to change with brakestands!
|
|
|
|
// whittle away speed
|
|
rmt::Vector& linearVel = mVehicle->mSimStateArticulated->GetLinearVelocity();
|
|
rmt::Vector& angularVel = mVehicle->mSimStateArticulated->GetAngularVelocity();
|
|
|
|
linearVel.Scale(test);
|
|
angularVel.Scale(test);
|
|
|
|
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::ReverseForce2
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector& forceResult, int wheelNum)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::ReverseForce2(rmt::Vector& forceResult, int wheelNum)
|
|
{
|
|
if(mVehicle->mWheels[wheelNum]->mDriveWheel)
|
|
{
|
|
float desiredForceMag = mVehicle->mDesignerParams.mDpGasScale * mVehicle->mReverse * mVehicle->mDesignerParams.mDpMass;
|
|
|
|
rmt::Vector force = mVehicle->mVehicleFacing;
|
|
force.Scale(-1.0f * desiredForceMag);
|
|
|
|
// TODO - make this a state?
|
|
// so that we can reduce the grip on the rear wheels and totally up the front?
|
|
|
|
forceResult.Add(force);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::EBrakeEffect
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ()
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::EBrakeEffect(rmt::Vector& forceResult, int wheelNum)
|
|
{
|
|
// in addition to reducing the rear grip, we want to apply (weak?) brakes too?
|
|
|
|
// since people are using the handbrake like a parking brake, I guess I better acknowledge...
|
|
static const float reallylowspeed = 0.5f;
|
|
if(mVehicle->mSpeed < reallylowspeed && mVehicle->mEBrake == 1.0f)
|
|
{
|
|
// someone's trying to use it to hold the car in place, so just let the rest test do it's thing
|
|
return;
|
|
}
|
|
|
|
if(mVehicle->mWheels[wheelNum]->mDriveWheel && mVehicle->mWheels[wheelNum]->mWheelTurnAngle == 0.0f)
|
|
{
|
|
// just lock up steer/drive wheels?????
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
//float desiredForceMag = mVehicle->mEBrake * mVehicle->mDesignerParams.mDpBrakeScale * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
const float defaultebrakebrakescalethatplumishappywith = 3.0f;
|
|
float desiredForceMag = mVehicle->mEBrake * defaultebrakebrakescalethatplumishappywith /*mVehicle->mDesignerParams.mDpBrakeScale*/ * mVehicle->mDesignerParams.mDpMass;// * gravFactor;
|
|
|
|
rmt::Vector force = mSuspensionPointVelocities[wheelNum];
|
|
|
|
force.NormalizeSafe();
|
|
force.Scale(-1.0f * desiredForceMag);
|
|
|
|
forceResult.Add(force);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//mVehicle->mVehicleState = VS_SLIP;
|
|
|
|
// instead of adding another state variable, just put this calculation right in steering code?
|
|
//mVehicle->mTireLateralResistance = mVehicle->mDesignerParams.mDpTireLateralResistanceSlip * (1.0f - mVehicle->mEBrake);
|
|
|
|
}
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::SteeringForce2
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector& forceResult, int wheelNum)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::SteeringForce2(rmt::Vector& forceResult, int wheelNum, float dt)
|
|
{
|
|
rmt::Vector lateralDirection = mVehicle->mVehicleTransverse;
|
|
|
|
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
rmt::Matrix steeringMatrix; // TODO - make this a class member?
|
|
steeringMatrix.Identity();
|
|
steeringMatrix.FillRotateY(mVehicle->mWheels[wheelNum]->mWheelTurnAngle);
|
|
|
|
lateralDirection.Transform(steeringMatrix);
|
|
}
|
|
|
|
//float lateralVelocityProjection = lateralDirection.DotProduct(mSuspensionPointVelocities[wheelNum]);
|
|
|
|
|
|
|
|
rmt::Vector temp = mSuspensionPointVelocities[wheelNum];
|
|
|
|
//rmt::Vector temp = mVehicle->mVelocityCM;
|
|
|
|
|
|
float desiredLateralResistanceForce = 0.0f;
|
|
|
|
//const float threshold = 0.15f;
|
|
//static float threshold = 0.15f;
|
|
const float threshold = 0.15f;
|
|
if(mVehicle->mPercentOfTopSpeed > threshold)
|
|
{
|
|
//-------
|
|
// normal
|
|
//-------
|
|
|
|
// this is the normal thing to do for regular and high-speed driving
|
|
temp.NormalizeSafe();
|
|
|
|
float lateralVelocityProjection = lateralDirection.DotProduct(temp);
|
|
// the higher this is the more we're asking this tire to do for us!
|
|
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
if(mVehicle->mVehicleState == VS_NORMAL)
|
|
{
|
|
desiredLateralResistanceForce = (mVehicle->mDesignerParams.mDpMass * lateralVelocityProjection *
|
|
mVehicle->mDesignerParams.mDpTireLateralResistanceNormal) /*mCurrentSteeringForce)*/ * 0.25f;
|
|
}
|
|
else if(mVehicle->mVehicleState == VS_EBRAKE_SLIP)
|
|
{
|
|
// slip
|
|
{
|
|
|
|
desiredLateralResistanceForce = (mVehicle->mDesignerParams.mDpMass * lateralVelocityProjection *
|
|
mVehicle->mDesignerParams.mDpTireLateralResistanceSlip) /*mCurrentSteeringForce)*/ * 0.25f;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
else // just VS_SLIP
|
|
{
|
|
// slip without ebrake!
|
|
desiredLateralResistanceForce = (mVehicle->mDesignerParams.mDpMass * lateralVelocityProjection *
|
|
mVehicle->mDesignerParams.mDpTireLateralResistanceSlipNoEBrake /*mCurrentSteeringForce*/) * 0.25f;
|
|
|
|
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
desiredLateralResistanceForce *= (1.0f + mVehicle->mDesignerParams.mDpSlipEffectNoEBrake);
|
|
|
|
}
|
|
else
|
|
{
|
|
desiredLateralResistanceForce *= (1.0f - mVehicle->mDesignerParams.mDpSlipEffectNoEBrake);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
// put ebrake effect outside of any state
|
|
|
|
if(mVehicle->mEBrake > 0.1) // note: we can be in this state without always holding the button down
|
|
{
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
// increase resistance on steer wheels
|
|
//desiredLateralResistanceForce *= (1.0f + mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f + mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
|
|
}
|
|
else
|
|
{
|
|
// decrease resistance on rear
|
|
//desiredLateralResistanceForce *= (1.0f - mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f - mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// rockford...?
|
|
|
|
|
|
// this is the condition for beginning a rockford
|
|
if( mVehicle->mVehicleFacing.DotProduct(mVehicle->mVelocityCM) < 0.0f && mVehicle->mEBrake < 0.1 && rmt::Fabs(mVehicle->mUnmodifiedInputWheelTurnAngle) > 0.5f && mVehicle->mGas == 0.0f )//||
|
|
//mVehicle->mDoingRockford )
|
|
{
|
|
|
|
mVehicle->mDoingRockford = true;
|
|
// rockford in proportion to ebrake setting
|
|
|
|
// note - the + and - are inverted from regular ebrake effect
|
|
|
|
|
|
//static float magicshit = 20.0f;
|
|
//static float mDpRockfordEffect = 0.5f;
|
|
float mDpRockfordEffect = 0.5f;
|
|
|
|
|
|
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
// increase resistance on steer wheels
|
|
//desiredLateralResistanceForce *= (1.0f + mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f - mDpRockfordEffect);
|
|
}
|
|
else
|
|
{
|
|
// decrease resistance on rear
|
|
//desiredLateralResistanceForce *= (1.0f - mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f + mDpRockfordEffect);
|
|
}
|
|
|
|
|
|
float hackbullshit = 10.0f;
|
|
float magicshit = hackbullshit * mDpRockfordEffect;
|
|
|
|
rmt::Vector rockfordtorque = mVehicle->mVehicleUp;
|
|
float dir = 0.0f;
|
|
if(mVehicle->mWheelTurnAngle > 0.0f)
|
|
{
|
|
dir = -1.0f;
|
|
}
|
|
if(mVehicle->mWheelTurnAngle < 0.0f)
|
|
{
|
|
dir = 1.0f;
|
|
}
|
|
|
|
|
|
float speedeffect = mVehicle->mPercentOfTopSpeed;
|
|
|
|
rockfordtorque.Scale(magicshit * dir * mVehicle->mDesignerParams.mDpMass * speedeffect);
|
|
|
|
//mVehicle->mPhObj->AddTorque(rockfordtorque);
|
|
((ArticulatedPhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject(-1)))->AddTorque(rockfordtorque);
|
|
|
|
|
|
mVehicle->mBurnoutLevel = 1.0f;
|
|
|
|
|
|
|
|
|
|
//hmmm....
|
|
//static float resdrop = 0.001f;
|
|
float resdrop = 0.001f;
|
|
//desiredLateralResistanceForce *= resdrop;
|
|
|
|
// new place to set this
|
|
mVehicle->mCollisionLateralResistanceDropFactor = resdrop;
|
|
|
|
}
|
|
|
|
|
|
// new - reduce traction on drive wheels if givin 'er gas
|
|
const float gasmodifierthreshold = 0.7f;
|
|
const float absoluteSpeedThreshold = 90.0f;
|
|
if( mVehicle->mWheels[wheelNum]->mDriveWheel && mVehicle->mVehicleType == VT_USER && mVehicle->mGas > 0.0f &&
|
|
mVehicle->mPercentOfTopSpeed > gasmodifierthreshold && rmt::Fabs(mVehicle->mWheelTurnAngleInputValue) > 0.1f &&
|
|
mVehicle->mSpeedKmh > absoluteSpeedThreshold)
|
|
{
|
|
const float maxPenalty = 0.2f;
|
|
float modifier = 1.0f - (maxPenalty * mVehicle->mGas); // ? also include speed??
|
|
|
|
desiredLateralResistanceForce *= modifier;
|
|
|
|
mVehicle->mDrawWireFrame = true;
|
|
mVehicle->mLosingTractionDueToAccel = true; // for plum
|
|
//mVehicle->mBurnoutLevel = 1.0f;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
//----------
|
|
// low speed
|
|
//----------
|
|
|
|
temp.NormalizeSafe();
|
|
|
|
float lateralVelocityProjection = lateralDirection.DotProduct(temp);
|
|
|
|
// at low speeds we want to account for the (small) magnitude of the velocity
|
|
lateralVelocityProjection *= (mVehicle->mPercentOfTopSpeed / threshold);
|
|
|
|
|
|
const rmt::Vector& gravity = GetWorldPhysicsManager()->mSimEnvironment->Gravity();
|
|
float gravFactor = gravity.y * -1.0f / 9.81f;
|
|
|
|
if(mVehicle->mVehicleState == VS_NORMAL)
|
|
{
|
|
desiredLateralResistanceForce = (mVehicle->mDesignerParams.mDpMass * lateralVelocityProjection * mVehicle->mDesignerParams.mDpTireLateralResistanceNormal) * 0.25f;// * gravFactor;
|
|
}
|
|
else
|
|
{
|
|
// slip
|
|
desiredLateralResistanceForce = (mVehicle->mDesignerParams.mDpMass * lateralVelocityProjection * mVehicle->mDesignerParams.mDpTireLateralResistanceSlip) * 0.25f;// * gravFactor;
|
|
|
|
/*
|
|
if(mVehicle->mEBrake > 0.0)
|
|
{
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
// increase resistance on steer wheels
|
|
desiredLateralResistanceForce *= (1.0f + mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
|
|
}
|
|
else
|
|
{
|
|
// decrease resistance on rear
|
|
desiredLateralResistanceForce *= (1.0f - mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
|
|
}
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// put ebrake effect outside of any state
|
|
if(mVehicle->mPercentOfTopSpeed > 0.02f)
|
|
{
|
|
if(mVehicle->mEBrake > 0.1) // note: we can be in this state without always holding the button down
|
|
{
|
|
if(mVehicle->mWheels[wheelNum]->mSteerWheel)
|
|
{
|
|
// increase resistance on steer wheels
|
|
//desiredLateralResistanceForce *= (1.0f + mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f + mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
|
|
}
|
|
else
|
|
{
|
|
// decrease resistance on rear
|
|
//desiredLateralResistanceForce *= (1.0f - mVehicle->mEBrake * mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
desiredLateralResistanceForce *= (1.0f - mVehicle->mDesignerParams.mDpEBrakeEffect);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
//rmt::Vector force = lateralDirection;
|
|
|
|
// assumign these are good?
|
|
|
|
//mTerrainIntersectCache[i].planePosn = planePosn;
|
|
//mTerrainIntersectCache[i].planeNorm = planeNormal;
|
|
|
|
|
|
//rmt::Vector force = mTerrainIntersectCache[wheelNum].planeNorm;
|
|
|
|
rmt::Vector force = mIntersectNormalUsed[wheelNum];
|
|
force.CrossProduct(mVehicle->mVehicleFacing);
|
|
|
|
// just in case
|
|
force.NormalizeSafe();
|
|
|
|
//rmt::Vector force = mVehicle->mVehicleTransverse; // I think this is better!
|
|
|
|
|
|
|
|
|
|
|
|
/// new quick terrain based friction test
|
|
// only affect steering
|
|
|
|
switch (mTerrainIntersectCache[wheelNum].mTerrainType)
|
|
{
|
|
case TT_Road:
|
|
desiredLateralResistanceForce *= TF_Road;
|
|
break;
|
|
|
|
case TT_Grass:
|
|
desiredLateralResistanceForce *= TF_Grass;
|
|
break;
|
|
|
|
case TT_Dirt:
|
|
desiredLateralResistanceForce *= TF_Dirt;
|
|
break;
|
|
|
|
case TT_Water:
|
|
desiredLateralResistanceForce *= TF_Water;
|
|
break;
|
|
|
|
case TT_Gravel:
|
|
desiredLateralResistanceForce *= TF_Gravel;
|
|
break;
|
|
|
|
case TT_Wood:
|
|
desiredLateralResistanceForce *= TF_Wood;
|
|
break;
|
|
|
|
case TT_Sand:
|
|
desiredLateralResistanceForce *= TF_Sand;
|
|
break;
|
|
|
|
case TT_Metal:
|
|
desiredLateralResistanceForce *= TF_Metal;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
force.Scale(-1.0f * desiredLateralResistanceForce);
|
|
|
|
|
|
if(1)//mVehicle->mBurnoutLevel == 0.0f)
|
|
{
|
|
// test
|
|
// scale lateral resistance way down if we have just had a collision
|
|
force.Scale(mVehicle->mCollisionLateralResistanceDropFactor);
|
|
}
|
|
|
|
|
|
// test before or after the above drop?
|
|
//TestSteeringForce(force, wheelNum);
|
|
|
|
|
|
|
|
forceResult.Add(force);
|
|
|
|
|
|
|
|
// new test
|
|
// faked high speed instability
|
|
/*
|
|
const float highSpeedInstabilityThreshold = 0.6f;
|
|
if(mVehicle->mPercentOfTopSpeed > highSpeedInstabilityThreshold)
|
|
{
|
|
// add some magic torque depending on the input wheel turn angle.
|
|
if(mVehicle->mWheelTurnAngleInputValue != 0.0f && !(mVehicle->mAirBorn))
|
|
{
|
|
static float magicshit = 10.0f;
|
|
|
|
rmt::Vector instabilityTorque = mVehicle->mVehicleFacing;
|
|
instabilityTorque.Scale(magicshit * mVehicle->mDesignerParams.mDpMass * mVehicle->mPercentOfTopSpeed * mVehicle->mWheelTurnAngleInputValue);
|
|
|
|
sim::PhysicsObject* phobj = (sim::PhysicsObject*)(mVehicle->mSimStateArticulated->GetSimulatedObject());
|
|
rAssert(phobj);
|
|
|
|
phobj->AddTorque(instabilityTorque);
|
|
|
|
|
|
}
|
|
}
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::TestSteeringForce
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector& force)
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::TestSteeringForce(rmt::Vector& force, int index)
|
|
{
|
|
//mVehicleState not changed here - this is just used to limit the lateral force
|
|
|
|
//static float forceCap = 1.0f;
|
|
|
|
|
|
rAssert(0);
|
|
|
|
|
|
/*
|
|
static float rearWheelMult = 1.0f;
|
|
|
|
if(mVehicle->mVehicleState == VS_SLIP)
|
|
{
|
|
|
|
float suspensionEffect = mCachedSuspensionForceResults[index];
|
|
|
|
float suspensionMinEffect = mVehicle->mSuspensionRestValue;
|
|
|
|
if(suspensionEffect < suspensionMinEffect)
|
|
{
|
|
suspensionEffect = suspensionMinEffect;
|
|
}
|
|
|
|
float maxTireForce = mVehicle->mDesignerParams.mDpTireLateralStaticGrip * suspensionEffect;
|
|
|
|
|
|
// cap all forces
|
|
int j;
|
|
for(j = 0; j < 4; j++)
|
|
{
|
|
|
|
//if(totalForce[j].Magnitude() > forceCap)
|
|
//{
|
|
// totalForce[j].NormalizeSafe();
|
|
// totalForce[j].Scale(forceCap);
|
|
//}
|
|
|
|
if(j < 2)
|
|
{
|
|
|
|
if(force.Magnitude() > maxTireForce * rearWheelMult)
|
|
{
|
|
force.NormalizeSafe();
|
|
force.Scale(maxTireForce * rearWheelMult);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(force.Magnitude() > maxTireForce)
|
|
{
|
|
force.NormalizeSafe();
|
|
force.Scale(maxTireForce);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
}
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::TestControllerForces
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: (rmt::Vector* totalForce) -- points to array of 4
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::TestControllerForces(rmt::Vector* totalForce)
|
|
{
|
|
|
|
// mVehicleState only changed in here!
|
|
|
|
|
|
// find wheel with highest down force
|
|
int i;
|
|
int index = 0;
|
|
for(i = 1; i < 4; i++)
|
|
{
|
|
if(mCachedSuspensionForceResults[i] > mCachedSuspensionForceResults[index])
|
|
{
|
|
index = i;
|
|
}
|
|
}
|
|
|
|
// TODO - fix this for airborn!
|
|
/*
|
|
float suspensionEffect = mCachedSuspensionForceResults[index];
|
|
|
|
float suspensionMinEffect = mVehicle->mSuspensionRestValue;
|
|
|
|
if(suspensionEffect < suspensionMinEffect)
|
|
{
|
|
suspensionEffect = suspensionMinEffect;
|
|
}
|
|
*/
|
|
|
|
// new test
|
|
float suspensionEffect = mVehicle->mSuspensionRestValue;
|
|
|
|
|
|
float maxTireForce = mVehicle->mDesignerParams.mDpTireLateralStaticGrip * suspensionEffect;
|
|
|
|
/*
|
|
// new Mar 12, 2003
|
|
// affect the maxTireForce calculation by gas
|
|
const float gasmodifierthreshold = 0.7f;
|
|
const float absoluteSpeedThreshold = 90.0f;
|
|
|
|
if(mVehicle->mVehicleType == VT_USER && mVehicle->mGas > 0.0f &&
|
|
mVehicle->mPercentOfTopSpeed > gasmodifierthreshold && rmt::Fabs(mVehicle->mWheelTurnAngleInputValue) > 0.1f &&
|
|
mVehicle->mSpeedKmh > absoluteSpeedThreshold)
|
|
{
|
|
//const float maxPenalty = 0.2f;
|
|
static float maxPenalty = 0.4f;
|
|
float modifier = 1.0f - (maxPenalty * mVehicle->mGas); // ? also include speed??
|
|
|
|
// *** desiredLateralResistanceForce *= modifier;
|
|
maxTireForce *= modifier;
|
|
|
|
mVehicle->mDrawWireFrame = true;
|
|
mVehicle->mLosingTractionDueToAccel = true; // for plum
|
|
//mVehicle->mBurnoutLevel = 1.0f;
|
|
|
|
|
|
}
|
|
*/
|
|
|
|
|
|
if(mVehicle->mVehicleState == VS_NORMAL)
|
|
{
|
|
// if the wheel with the greatest down force is slipping
|
|
// make whole car slip
|
|
|
|
if(mVehicle->mEBrake > 0.1f && mVehicle->mPercentOfTopSpeed > 0.05f)
|
|
{
|
|
// change state to controlled skid
|
|
mVehicle->mVehicleState = VS_EBRAKE_SLIP;
|
|
}
|
|
else
|
|
{
|
|
// now if wheel index is slipping, whole fucking car is slipping
|
|
float totalForceMag = totalForce[index].Magnitude();
|
|
//float maxTireForce = mVehicle->mDesignerParams.mDpTireLateralStaticGrip * suspensionEffect;
|
|
if(totalForceMag > maxTireForce)
|
|
{
|
|
// fucker is sliding
|
|
mVehicle->mVehicleState = VS_SLIP;
|
|
//mVehicle->mTireLateralResistance = mVehicle->mDesignerParams.mDpTireLateralResistanceSlip;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if( !mVehicle->mOutOfControl )
|
|
{
|
|
// need heruistic to go back to normal
|
|
rmt::Vector velDir = mVehicle->mVelocityCM;
|
|
velDir.NormalizeSafe();
|
|
|
|
float cos5 = 0.9962f;
|
|
float cos10 = 0.9848f;
|
|
float cos20 = 0.9397f;
|
|
float cos15 = 0.9659f;
|
|
|
|
// in addition to the alignment test, should not go into VS_SLIP if you're going very slow,
|
|
// ebrake or not.
|
|
|
|
if( (velDir.DotProduct(mVehicle->mVehicleFacing) > cos15 && rmt::Fabs(mVehicle->mWheelTurnAngleInputValue) < 0.1f) ||
|
|
mVehicle->mSpeed < 1.0f ||
|
|
mVehicle->mGas == 0.0f)
|
|
{
|
|
mVehicle->mVehicleState = VS_NORMAL;
|
|
//mVehicle->mTireLateralResistance = mVehicle->mDesignerParams.mDpTireLateralResistanceNormal;
|
|
}
|
|
|
|
/*
|
|
// duplicate this here in case we only got in here cause the ebrake is held down.
|
|
if(mVehicle->mEBrake > 0.1f && mVehicle->mSpeed > 1.0f)
|
|
{
|
|
mVehicle->mVehicleState = VS_SLIP;
|
|
//mVehicle->mTireLateralResistance = mVehicle->mDesignerParams.mDpTireLateralResistanceSlip;
|
|
// return;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
// PhysicsLocomotion::SetSkidLevel
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ()
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void PhysicsLocomotion::SetSkidLevel()
|
|
{
|
|
mVehicle->mSkidLevel = 0.0f;
|
|
mVehicle->mSlipGasModifier = 1.0f;
|
|
|
|
//static float hack = 0.7f;
|
|
//mVehicle->mSkidLevel = hack;
|
|
|
|
|
|
float skid = 0.0f;
|
|
float speedfactor = mVehicle->mPercentOfTopSpeed;
|
|
|
|
|
|
|
|
rmt::Vector velDir = mVehicle->mVelocityCM;
|
|
velDir.NormalizeSafe();
|
|
|
|
|
|
float projectionOnly = rmt::Fabs(velDir.DotProduct(mVehicle->mVehicleTransverse));
|
|
|
|
|
|
if(mVehicle->mVehicleState == VS_SLIP || mVehicle->mVehicleState == VS_EBRAKE_SLIP)
|
|
{
|
|
// static float hack = 0.7f;
|
|
// mVehicle->mSkidLevel = hack;
|
|
|
|
|
|
if(1)//projectionOnly > 0.7f)
|
|
{
|
|
// this actually works quite well
|
|
skid = projectionOnly;
|
|
}
|
|
else
|
|
{
|
|
skid = projectionOnly * speedfactor;
|
|
}
|
|
|
|
|
|
// if they're using the ebrake, we want whichever is loudest:
|
|
if(mVehicle->mEBrake * 0.5f > skid)
|
|
{
|
|
skid = mVehicle->mEBrake * 0.5f;
|
|
}
|
|
|
|
}
|
|
|
|
if(mVehicle->mBrake > 0.05f && speedfactor > 0.07f)
|
|
{
|
|
/*
|
|
rmt::Vector velDir = mVehicle->mVelocityCM;
|
|
velDir.NormalizeSafe();
|
|
|
|
float proj = velDir.DotProduct(mVehicle->mVehicleFacing);
|
|
|
|
// hmm..
|
|
if(mVehicle->mBrake * 0.5f > skid && proj > 0.0f)
|
|
{
|
|
skid = mVehicle->mBrake * 0.5f;
|
|
}
|
|
*/
|
|
|
|
// not sure if values lower than 0.5 are working...
|
|
//
|
|
//
|
|
float forward = velDir.DotProduct(mVehicle->mVehicleFacing);
|
|
if(forward > 0.0f && speedfactor < 0.5f)
|
|
{
|
|
skid = 1.0f;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
if(mVehicle->mEBrake > 0.85f && speedfactor > 0.07f)// && mVehicle->mWheelTurnAngle == 0.0f)
|
|
{
|
|
// hmm..
|
|
if(mVehicle->mEBrake * 0.5f > skid)
|
|
{
|
|
skid = mVehicle->mEBrake * 0.5f;
|
|
}
|
|
}
|
|
|
|
|
|
// compare to burnout level
|
|
if(mVehicle->mBurnoutLevel > skid)
|
|
{
|
|
mVehicle->mSkidLevel = mVehicle->mBurnoutLevel;
|
|
}
|
|
else
|
|
{
|
|
mVehicle->mSkidLevel = skid;
|
|
}
|
|
|
|
|
|
// still too quiet
|
|
if(mVehicle->mSkidLevel > 0.0f)
|
|
{
|
|
if(mVehicle->mSkidLevel < 0.5f)
|
|
{
|
|
mVehicle->mSkidLevel = 0.5f;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
|
|
// override any of the above shit if wheels are not in contact with ground
|
|
int i;
|
|
if(mBurnoutLevel > 0.0f)
|
|
{
|
|
if(mWheels[0]->mWheelInCollision
|
|
|
|
|
|
for(i = 0; i < 2; i++)
|
|
{
|
|
if(mWheels[i]->mWheelInCollision) // will this value still be valid here?
|
|
{
|
|
mGeometryVehicle->SetSkidValues(i, mSkidLevel);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i < 4; i++)
|
|
{
|
|
if(mWheels[i]->mWheelInCollision) // will this value still be valid here?
|
|
{
|
|
mGeometryVehicle->SetSkidValues(i, mSkidLevel);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|