code review:

1) got rid of evey class having it's own gravity
2) rigidshape inheritance simplifications
3) gravitymod from physicszones taking buoyancy into account natively (we still track raw bouyancy to cancel it out for player)
4) disableMove used throughout
5) items can now also be influenced by the appliedforce from physicszones
This commit is contained in:
AzaezelX 2020-10-02 13:53:46 -05:00
parent 76c5e30869
commit afb39d398f
13 changed files with 191 additions and 487 deletions

View file

@ -50,8 +50,6 @@ const static U32 sCollisionMoveMask = ( TerrainObjectType | WaterObjectType
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
static U32 sClientCollisionMask = sCollisionMoveMask;
static F32 sFlyingVehicleGravity = -20.0f;
//
const char* FlyingVehicle::sJetSequence[FlyingVehicle::JetAnimCount] =
{
@ -485,6 +483,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
{
PROFILE_SCOPE( FlyingVehicle_UpdateForces );
if (mDisableMove) return;
MatrixF currPosMat;
mRigid.getTransform(&currPosMat);
mRigid.atRest = false;
@ -498,7 +497,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
currPosMat.getColumn(2,&zv);
F32 speed = mRigid.linVelocity.len();
Point3F force = Point3F(0, 0, sFlyingVehicleGravity * mRigid.mass * mGravityMod);
Point3F force = Point3F(0, 0, mRigid.mass * mNetGravity);
Point3F torque = Point3F(0, 0, 0);
// Drag at any speed
@ -520,7 +519,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
}
// Hovering Jet
F32 vf = -sFlyingVehicleGravity * mRigid.mass * mGravityMod;
F32 vf = mRigid.mass * -mNetGravity;
F32 h = getHeight();
if (h <= 1) {
if (h > 0) {
@ -567,8 +566,6 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
// Add in force from physical zones...
force += mAppliedForce;
// Container buoyancy & drag
force -= Point3F(0, 0, 1) * (mBuoyancy * sFlyingVehicleGravity * mRigid.mass * mGravityMod);
force -= mRigid.linVelocity * mDrag;
//

View file

@ -69,7 +69,6 @@ ConsoleDocClass( HoverVehicle,
);
namespace {
const F32 sHoverVehicleGravity = -20;
const U32 sCollisionMoveMask = (TerrainObjectType | PlayerObjectType |
StaticShapeObjectType | VehicleObjectType |
@ -674,7 +673,7 @@ void HoverVehicle::updateForces(F32 /*dt*/)
{
PROFILE_SCOPE( HoverVehicle_UpdateForces );
Point3F gravForce(0, 0, sHoverVehicleGravity * mRigid.mass * mGravityMod);
Point3F gravForce(0, 0, mRigid.mass * mNetGravity);
MatrixF currTransform;
mRigid.getTransform(&currTransform);
@ -872,8 +871,6 @@ void HoverVehicle::updateForces(F32 /*dt*/)
// Add in physical zone force
force += mAppliedForce;
// Container buoyancy & drag
force += Point3F(0, 0,-mBuoyancy * sHoverVehicleGravity * mRigid.mass * mGravityMod);
force -= mRigid.linVelocity * mDrag;
torque -= mRigid.angMomentum * mDrag;

View file

@ -66,7 +66,6 @@ static F32 sWorkingQueryBoxSizeMultiplier = 2.0f; // How much larger should the
// Client prediction
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
const F32 sVehicleGravity = -20;
// Physics and collision constants
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
@ -124,17 +123,6 @@ ConsoleDocClass( VehicleData,
"@ingroup Vehicles\n"
);
IMPLEMENT_CALLBACK( VehicleData, onEnterLiquid, void, ( Vehicle* obj, F32 coverage, const char* type ), ( obj, coverage, type ),
"Called when the vehicle enters liquid.\n"
"@param obj the Vehicle object\n"
"@param coverage percentage of the vehicle's bounding box covered by the liquid\n"
"@param type type of liquid the vehicle has entered\n" );
IMPLEMENT_CALLBACK( VehicleData, onLeaveLiquid, void, ( Vehicle* obj, const char* type ), ( obj, type ),
"Called when the vehicle leaves liquid.\n"
"@param obj the Vehicle object\n"
"@param type type of liquid the vehicle has left\n" );
//----------------------------------------------------------------------------
VehicleData::VehicleData()
@ -678,9 +666,7 @@ Vehicle::Vehicle()
mCameraOffset.set(0,0,0);
dMemset( mDustEmitterList, 0, sizeof( mDustEmitterList ) );
dMemset( mDamageEmitterList, 0, sizeof( mDamageEmitterList ) );
dMemset( mSplashEmitterList, 0, sizeof( mSplashEmitterList ) );
mDisableMove = false;
restCount = 0;
@ -701,30 +687,6 @@ U32 Vehicle::getCollisionMask()
return 0;
}
Point3F Vehicle::getVelocity() const
{
return mRigid.linVelocity;
}
void Vehicle::_createPhysics()
{
SAFE_DELETE(mPhysicsRep);
if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep)
return;
TSShape *shape = mShapeInstance->getShape();
PhysicsCollision *colShape = NULL;
colShape = shape->buildColShape(false, getScale());
if (colShape)
{
PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
mPhysicsRep = PHYSICSMGR->createBody();
mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world);
mPhysicsRep->setTransform(getTransform());
}
}
//----------------------------------------------------------------------------
bool Vehicle::onAdd()
@ -747,21 +709,6 @@ bool Vehicle::onAdd()
// Create Emitters on the client
if( isClientObject() )
{
if( mDataBlock->dustEmitter )
{
for( S32 i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
{
mDustEmitterList[i] = new ParticleEmitter;
mDustEmitterList[i]->onNewDataBlock( mDataBlock->dustEmitter, false );
if( !mDustEmitterList[i]->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
delete mDustEmitterList[i];
mDustEmitterList[i] = NULL;
}
}
}
U32 j;
for( j=0; j<VehicleData::VC_NUM_DAMAGE_EMITTERS; j++ )
{
@ -778,22 +725,6 @@ bool Vehicle::onAdd()
}
}
for( j=0; j<VehicleData::VC_NUM_SPLASH_EMITTERS; j++ )
{
if( mDataBlock->splashEmitterList[j] )
{
mSplashEmitterList[j] = new ParticleEmitter;
mSplashEmitterList[j]->onNewDataBlock( mDataBlock->splashEmitterList[j], false );
if( !mSplashEmitterList[j]->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register splash emitter for class: %s", mDataBlock->getName() );
delete mSplashEmitterList[j];
mSplashEmitterList[j] = NULL;
}
}
}
}
// Create a new convex.
@ -909,26 +840,6 @@ void Vehicle::processTick(const Move* move)
}
}
void Vehicle::interpolateTick(F32 dt)
{
PROFILE_SCOPE( Vehicle_InterpolateTick );
Parent::interpolateTick(dt);
if ( isMounted() )
return;
if(dt == 0.0f)
setRenderPosition(mDelta.pos, mDelta.rot[1]);
else
{
QuatF rot;
rot.interpolate(mDelta.rot[1], mDelta.rot[0], dt);
Point3F pos = mDelta.pos + mDelta.posVec * dt;
setRenderPosition(pos,rot);
}
mDelta.dt = dt;
}
void Vehicle::advanceTime(F32 dt)
{
PROFILE_SCOPE( Vehicle_AdvanceTime );
@ -1080,22 +991,6 @@ void Vehicle::getCameraTransform(F32* pos, MatrixF* mat)
mat->mul( gCamFXMgr.getTrans() );
}
//----------------------------------------------------------------------------
void Vehicle::getVelocity(const Point3F& r, Point3F* v)
{
mRigid.getVelocity(r, v);
}
void Vehicle::applyImpulse(const Point3F &pos, const Point3F &impulse)
{
Point3F r;
mRigid.getOriginVector(pos,&r);
mRigid.applyImpulse(r, impulse);
}
//----------------------------------------------------------------------------
void Vehicle::updateMove(const Move* move)
@ -1161,51 +1056,6 @@ void Vehicle::updateMove(const Move* move)
mJetting = false;
}
//----------------------------------------------------------------------------
void Vehicle::setPosition(const Point3F& pos,const QuatF& rot)
{
MatrixF mat;
rot.setMatrix(&mat);
mat.setColumn(3,pos);
Parent::setTransform(mat);
}
void Vehicle::setRenderPosition(const Point3F& pos, const QuatF& rot)
{
MatrixF mat;
rot.setMatrix(&mat);
mat.setColumn(3,pos);
Parent::setRenderTransform(mat);
}
void Vehicle::setTransform(const MatrixF& newMat)
{
mRigid.setTransform(newMat);
Parent::setTransform(newMat);
mRigid.atRest = false;
mContacts.clear();
}
//-----------------------------------------------------------------------------
void Vehicle::disableCollision()
{
Parent::disableCollision();
for (SceneObject* ptr = getMountList(); ptr; ptr = ptr->getMountLink())
ptr->disableCollision();
}
void Vehicle::enableCollision()
{
Parent::enableCollision();
for (SceneObject* ptr = getMountList(); ptr; ptr = ptr->getMountLink())
ptr->enableCollision();
}
//----------------------------------------------------------------------------
/** Update the physics
*/
@ -1234,7 +1084,7 @@ void Vehicle::updatePos(F32 dt)
if (mCollisionList.getCount())
{
F32 k = mRigid.getKineticEnergy();
F32 G = sVehicleGravity * dt;
F32 G = mNetGravity * dt;
F32 Kg = 0.5 * mRigid.mass * G * G;
if (k < sRestTol * Kg && ++restCount > sRestCount)
mRigid.setAtRest();
@ -1325,101 +1175,6 @@ void Vehicle::updateForces(F32 /*dt*/)
}
//-----------------------------------------------------------------------------
/** Update collision information
Update the convex state and check for collisions. If the object is in
collision, impact and contact forces are generated.
*/
bool Vehicle::updateCollision(F32 dt)
{
PROFILE_SCOPE( Vehicle_UpdateCollision );
// Update collision information
MatrixF mat,cmat;
mConvex.transform = &mat;
mRigid.getTransform(&mat);
cmat = mConvex.getTransform();
mCollisionList.clear();
CollisionState *state = mConvex.findClosestState(cmat, getScale(), mDataBlock->collisionTol);
if (state && state->mDist <= mDataBlock->collisionTol)
{
//resolveDisplacement(ns,state,dt);
mConvex.getCollisionInfo(cmat, getScale(), &mCollisionList, mDataBlock->collisionTol);
}
// Resolve collisions
bool collided = resolveCollision(mRigid,mCollisionList);
resolveContacts(mRigid,mCollisionList,dt);
return collided;
}
//----------------------------------------------------------------------------
void Vehicle::updateWorkingCollisionSet(const U32 mask)
{
PROFILE_SCOPE( Vehicle_UpdateWorkingCollisionSet );
// First, we need to adjust our velocity for possible acceleration. It is assumed
// that we will never accelerate more than 20 m/s for gravity, plus 30 m/s for
// jetting, and an equivalent 10 m/s for vehicle accel. We also assume that our
// working list is updated on a Tick basis, which means we only expand our box by
// the possible movement in that tick, plus some extra for caching purposes
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
F32 l = (len * 1.1) + 0.1; // fudge factor
convexBox.minExtents -= Point3F(l, l, l);
convexBox.maxExtents += Point3F(l, l, l);
// Check to see if it is actually necessary to construct the new working list,
// or if we can use the cached version from the last query. We use the x
// component of the min member of the mWorkingQueryBox, which is lame, but
// it works ok.
bool updateSet = false;
// Check containment
if ((sWorkingQueryBoxStaleThreshold == -1 || mWorkingQueryBoxCountDown > 0) && mWorkingQueryBox.minExtents.x != -1e9f)
{
if (mWorkingQueryBox.isContained(convexBox) == false)
// Needed region is outside the cached region. Update it.
updateSet = true;
}
else
{
// Must update
updateSet = true;
}
// Actually perform the query, if necessary
if (updateSet == true)
{
mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
const Point3F lPoint( sWorkingQueryBoxSizeMultiplier * l );
mWorkingQueryBox = convexBox;
mWorkingQueryBox.minExtents -= lPoint;
mWorkingQueryBox.maxExtents += lPoint;
disableCollision();
mConvex.updateWorkingList(mWorkingQueryBox, mask);
enableCollision();
}
}
//----------------------------------------------------------------------------
/** Check collisions with trigger and items
Perform a container search using the current bounding box
of the main body, wheels are not included. This method should
only be called on the server.
*/
void Vehicle::checkTriggers()
{
Box3F bbox = mConvex.getBoundingBox(getTransform(), getScale());
gServerContainer.findObjects(bbox,sTriggerMask,findCallback,this);
}
/** The callback used in by the checkTriggers() method.
The checkTriggers method uses a container search which will
invoke this callback on each obj that matches.
@ -1743,32 +1498,6 @@ void Vehicle::updateFroth( F32 dt )
}
//--------------------------------------------------------------------------
// Returns true if vehicle is intersecting a water surface (roughly)
//--------------------------------------------------------------------------
bool Vehicle::collidingWithWater( Point3F &waterHeight )
{
Point3F curPos = getPosition();
F32 height = mFabs( mObjBox.maxExtents.z - mObjBox.minExtents.z );
RayInfo rInfo;
if( gClientContainer.castRay( curPos + Point3F(0.0, 0.0, height), curPos, WaterObjectType, &rInfo) )
{
waterHeight = rInfo.point;
return true;
}
return false;
}
void Vehicle::setEnergyLevel(F32 energy)
{
Parent::setEnergyLevel(energy);
setMaskBits(EnergyMask);
}
void Vehicle::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
{
Parent::prepBatchRender( state, mountedImageIndex );

View file

@ -131,9 +131,6 @@ struct VehicleData : public RigidShapeData
virtual void unpackData(BitStream* stream);
DECLARE_CONOBJECT(VehicleData);
DECLARE_CALLBACK( void, onEnterLiquid, ( Vehicle* obj, F32 coverage, const char* type ) );
DECLARE_CALLBACK( void, onLeaveLiquid, ( Vehicle* obj, const char* type ) );
};
@ -145,74 +142,24 @@ class Vehicle : public RigidShape
typedef RigidShape Parent;
protected:
enum CollisionFaceFlags {
BodyCollision = 0x1,
WheelCollision = 0x2,
};
struct StateDelta {
Move move; ///< Last move from server
F32 dt; ///< Last interpolation time
// Interpolation data
Point3F pos;
Point3F posVec;
QuatF rot[2];
// Warp data
S32 warpTicks; ///< Number of ticks to warp
S32 warpCount; ///< Current pos in warp
Point3F warpOffset;
QuatF warpRot[2];
//
Point3F cameraOffset;
Point3F cameraVec;
Point3F cameraRot;
Point3F cameraRotVec;
};
PhysicsBody *mPhysicsRep;
StateDelta mDelta;
S32 mPredictionCount; ///< Number of ticks to predict
VehicleData* mDataBlock;
bool inLiquid;
SFXSource* mWakeSound;
Point3F mCameraOffset; ///< 3rd person camera
// Control
Point2F mSteering;
F32 mThrottle;
bool mJetting;
// Rigid Body
bool mDisableMove;
GFXStateBlockRef mSolidSB;
Box3F mWorkingQueryBox;
S32 mWorkingQueryBoxCountDown;
CollisionList mCollisionList;
CollisionList mContacts;
ShapeBaseConvex mConvex;
S32 restCount;
SimObjectPtr<ParticleEmitter> mDustEmitterList[VehicleData::VC_NUM_DUST_EMITTERS];
SimObjectPtr<ParticleEmitter> mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS];
SimObjectPtr<ParticleEmitter> mSplashEmitterList[VehicleData::VC_NUM_SPLASH_EMITTERS];
//
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
void updatePos(F32 dt);
bool updateCollision(F32 dt);
bool findContacts(Rigid& ns,CollisionList& cList);
void checkTriggers();
static void findCallback(SceneObject* obj,void * key);
void setPosition(const Point3F& pos,const QuatF& rot);
void setRenderPosition(const Point3F& pos,const QuatF& rot);
void setTransform(const MatrixF& mat);
// virtual bool collideBody(const MatrixF& mat,Collision* info) = 0;
virtual void updateMove(const Move* move);
virtual void updateForces(F32 dt);
@ -225,11 +172,9 @@ class Vehicle : public RigidShape
void updateLiftoffDust( F32 dt );
void updateDamageSmoke( F32 dt );
void updateWorkingCollisionSet(const U32 mask);
virtual U32 getCollisionMask();
void updateFroth( F32 dt );
bool collidingWithWater( Point3F &waterHeight );
/// ObjectRenderInst delegate hooked up in prepBatchRender
/// if GameBase::gShowBoundingBox is true.
@ -252,40 +197,15 @@ public:
bool onAdd();
void onRemove();
void _createPhysics();
/// Interpolates between move ticks @see processTick
/// @param dt Change in time between the last call and this call to the function
void interpolateTick(F32 dt);
void advanceTime(F32 dt);
/// Disables collisions for this vehicle and all mounted objects
void disableCollision();
/// Enables collisions for this vehicle and all mounted objects
void enableCollision();
/// Returns the velocity of the vehicle
Point3F getVelocity() const;
void setEnergyLevel(F32 energy);
void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex );
///@name Rigid body methods
///@{
/// This method will get the velocity of the object, taking into account
/// angular velocity.
/// @param r Point on the object you want the velocity of, relative to Center of Mass
/// @param vel Velocity (out)
void getVelocity(const Point3F& r, Point3F* vel);
/// Applies an impulse force
/// @param r Point on the object to apply impulse to, r is relative to Center of Mass
/// @param impulse Impulse vector to apply.
void applyImpulse(const Point3F &r, const Point3F &impulse);
void getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot);
void getCameraTransform(F32* pos, MatrixF* mat);
///@}

View file

@ -54,9 +54,6 @@ static U32 sClientCollisionMask =
StaticShapeObjectType | VehicleObjectType |
VehicleBlockerObjectType;
// Gravity constant
static F32 sWheeledVehicleGravity = -20;
// Misc. sound constants
static F32 sMinSquealVolume = 0.05f;
static F32 sIdleEngineVolume = 0.2f;
@ -857,6 +854,7 @@ void WheeledVehicle::updateForces(F32 dt)
extendWheels();
if (mDisableMove) return;
F32 aMomentum = mMass / mDataBlock->wheelCount;
// Get the current matrix and extact vectors
@ -902,8 +900,7 @@ void WheeledVehicle::updateForces(F32 dt)
// Integrate forces, we'll do this ourselves here instead of
// relying on the rigid class which does it during movement.
Wheel* wend = &mWheel[mDataBlock->wheelCount];
mRigid.force.set(0, 0, 0);
mRigid.torque.set(0, 0, 0);
mRigid.clearForces();
// Calculate vertical load for friction. Divide up the spring
// forces across all the wheels that are in contact with
@ -1095,7 +1092,7 @@ void WheeledVehicle::updateForces(F32 dt)
mRigid.force += mAppliedForce;
// Container drag & buoyancy
mRigid.force += Point3F(0, 0, -mBuoyancy * sWheeledVehicleGravity * mRigid.mass);
mRigid.force += Point3F(0, 0, mRigid.mass * mNetGravity);
mRigid.force -= mRigid.linVelocity * mDrag;
mRigid.torque -= mRigid.angMomentum * mDrag;
@ -1104,17 +1101,13 @@ void WheeledVehicle::updateForces(F32 dt)
if (mRigid.atRest && (mRigid.force.len() || mRigid.torque.len()))
mRigid.atRest = false;
// Gravity
mRigid.force += Point3F(0, 0, sWheeledVehicleGravity * mRigid.mass);
// Integrate and update velocity
mRigid.linMomentum += mRigid.force * dt;
mRigid.angMomentum += mRigid.torque * dt;
mRigid.updateVelocity();
// Since we've already done all the work, just need to clear this out.
mRigid.force.set(0, 0, 0);
mRigid.torque.set(0, 0, 0);
mRigid.clearForces();
// If we're still atRest, make sure we're not accumulating anything
if (mRigid.atRest)