2
0
Эх сурвалжийг харах

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

AzaezelX 5 жил өмнө
parent
commit
afb39d398f

+ 7 - 7
Engine/source/T3D/item.cpp

@@ -50,8 +50,6 @@ const S32 sCollisionTimeout = 15;       // Timout value in ticks
 static F32 sMinWarpTicks = 0.5 ;        // Fraction of tick at which instant warp occures
 static F32 sMinWarpTicks = 0.5 ;        // Fraction of tick at which instant warp occures
 static S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 static S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 
 
-F32 Item::mGravity = -20.0f;
-
 const U32 sClientCollisionMask = (TerrainObjectType     |
 const U32 sClientCollisionMask = (TerrainObjectType     |
                                   StaticShapeObjectType |
                                   StaticShapeObjectType |
                                   VehicleObjectType     |  
                                   VehicleObjectType     |  
@@ -716,18 +714,20 @@ void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
 
 
 void Item::updateVelocity(const F32 dt)
 void Item::updateVelocity(const F32 dt)
 {
 {
+   // Container buoyancy & drag
    // Acceleration due to gravity
    // Acceleration due to gravity
-   mVelocity.z += (mGravity * mDataBlock->gravityMod) * dt;
+   mVelocity.z += (mNetGravity * mDataBlock->gravityMod) * dt;
+   mVelocity   -= mVelocity * mDrag * dt;
+
+   // Add in physical zone force
+   mVelocity += mAppliedForce;
+
    F32 len;
    F32 len;
    if (mDataBlock->maxVelocity > 0 && (len = mVelocity.len()) > (mDataBlock->maxVelocity * 1.05)) {
    if (mDataBlock->maxVelocity > 0 && (len = mVelocity.len()) > (mDataBlock->maxVelocity * 1.05)) {
       Point3F excess = mVelocity * (1.0 - (mDataBlock->maxVelocity / len ));
       Point3F excess = mVelocity * (1.0 - (mDataBlock->maxVelocity / len ));
       excess *= 0.1f;
       excess *= 0.1f;
       mVelocity -= excess;
       mVelocity -= excess;
    }
    }
-
-   // Container buoyancy & drag
-   mVelocity.z -= mBuoyancy * (mGravity * mDataBlock->gravityMod * mGravityMod) * dt;
-   mVelocity   -= mVelocity * mDrag * dt;
 }
 }
 
 
 
 

+ 0 - 1
Engine/source/T3D/item.h

@@ -92,7 +92,6 @@ class Item: public ShapeBase
 
 
    // Static attributes
    // Static attributes
    ItemData* mDataBlock;
    ItemData* mDataBlock;
-   static F32 mGravity;
    bool mStatic;
    bool mStatic;
    bool mRotate;
    bool mRotate;
 
 

+ 1 - 27
Engine/source/T3D/player.cpp

@@ -1581,8 +1581,6 @@ ConsoleDocClass( Player,
    "@ingroup gameObjects\n"
    "@ingroup gameObjects\n"
 );
 );
 
 
-F32 Player::mGravity = -20;
-
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
 Player::Player()
 Player::Player()
@@ -2890,7 +2888,7 @@ void Player::updateMove(const Move* move)
    speed_bias = speed_bias + (speed_bias_goal - speed_bias)*0.1f;
    speed_bias = speed_bias + (speed_bias_goal - speed_bias)*0.1f;
    moveSpeed *= speed_bias;
    moveSpeed *= speed_bias;
    // Acceleration due to gravity
    // Acceleration due to gravity
-   VectorF acc(0.0f, 0.0f, mGravity * mGravityMod * TickSec);
+   VectorF acc(0.0f, 0.0f, mNetGravity/(1.0 - mBuoyancy) * TickSec);
 
 
    // Determine ground contact normal. Only look for contacts if
    // Determine ground contact normal. Only look for contacts if
    // we can move and aren't mounted.
    // we can move and aren't mounted.
@@ -3254,30 +3252,6 @@ void Player::updateMove(const Move* move)
       mVelocity.z -= mDataBlock->upResistFactor * TickSec * (mVelocity.z - mDataBlock->upResistSpeed);
       mVelocity.z -= mDataBlock->upResistFactor * TickSec * (mVelocity.z - mDataBlock->upResistSpeed);
    }
    }
 
 
-   // Container buoyancy & drag
-/* Commented out until the buoyancy calculation can be reworked so that a container and
-** player with the same density will result in neutral buoyancy.
-   if (mBuoyancy != 0)
-   {     
-      // Applying buoyancy when standing still causing some jitters-
-      if (mBuoyancy > 1.0 || !mVelocity.isZero() || !runSurface)
-      {
-         // A little hackery to prevent oscillation
-         // based on http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html
-
-         F32 buoyancyForce = mBuoyancy * mGravity * mGravityMod * TickSec;
-         F32 currHeight = getPosition().z;
-         const F32 C = 2.0f;
-         const F32 M = 0.1f;
-         
-         if ( currHeight + mVelocity.z * TickSec * C > mLiquidHeight )
-            buoyancyForce *= M;
-                  
-         mVelocity.z -= buoyancyForce;
-      }
-   }
-*/
-
    // Apply drag
    // Apply drag
    if ( mSwimming )
    if ( mSwimming )
       mVelocity -= mVelocity * mDrag * TickSec * ( mVelocity.len() / mDataBlock->maxUnderwaterForwardSpeed );
       mVelocity -= mVelocity * mDrag * TickSec * ( mVelocity.len() / mDataBlock->maxUnderwaterForwardSpeed );

+ 0 - 1
Engine/source/T3D/player.h

@@ -444,7 +444,6 @@ protected:
    Point3F mRot;                    ///< Body rotation, uses only z
    Point3F mRot;                    ///< Body rotation, uses only z
    VectorF mVelocity;               ///< Velocity
    VectorF mVelocity;               ///< Velocity
    Point3F mAnchorPoint;            ///< Pos compression anchor
    Point3F mAnchorPoint;            ///< Pos compression anchor
-   static F32 mGravity;             ///< Gravity
    S32 mImpactSound;
    S32 mImpactSound;
 
 
    bool mUseHeadZCalc;              ///< Including mHead.z in transform calculations
    bool mUseHeadZCalc;              ///< Including mHead.z in transform calculations

+ 152 - 68
Engine/source/T3D/rigidShape.cpp

@@ -47,7 +47,8 @@
 #include "sfx/sfxSystem.h"
 #include "sfx/sfxSystem.h"
 #include "T3D/fx/particleEmitter.h"
 #include "T3D/fx/particleEmitter.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
-
+#include "T3D/physics/physicsPlugin.h"
+#include "T3D/physics/physicsCollision.h"
 
 
 IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
 IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
 
 
@@ -152,45 +153,33 @@ ConsoleDocClass( RigidShape,
    "@ingroup Physics\n"
    "@ingroup Physics\n"
 );
 );
 
 
+IMPLEMENT_CALLBACK(RigidShapeData, onEnterLiquid, void, (RigidShape* 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( RigidShape, onEnterLiquid, void, ( const char* objId, F32 waterCoverage, const char* liquidType ),
-													 ( objId, waterCoverage, liquidType ),
-   "@brief Called whenever this RigidShape object enters liquid.\n\n"
-   "@param objId The ID of the rigidShape object.\n"
-   "@param waterCoverage Amount of water coverage the RigidShape has.\n"
-   "@param liquidType Type of liquid that was entered.\n\n"
-   "@tsexample\n"
-   "// The RigidShape object falls in a body of liquid, causing the callback to occur.\n"
-   "RigidShape::onEnterLiquid(%this,%objId,%waterCoverage,%liquidType)\n"
-   "	{\n"
-   "		// Code to run whenever this callback occurs.\n"
-   "	}\n"
-   "@endtsexample\n\n"
-   "@see ShapeBase\n\n"
-);
-
-IMPLEMENT_CALLBACK( RigidShape, onLeaveLiquid, void, ( const char* objId, const char* liquidType ),( objId, liquidType ),
-   "@brief Called whenever the RigidShape object exits liquid.\n\n"
-   "@param objId The ID of the RigidShape object.\n"
-   "@param liquidType Type if liquid that was exited.\n\n"
-   "@tsexample\n"
-   "// The RigidShape object exits in a body of liquid, causing the callback to occur.\n"
-   "RigidShape::onLeaveLiquid(%this,%objId,%liquidType)\n"
-   "	{\n"
-   "		// Code to run whenever this callback occurs.\n"
-   "	}\n"
-   "@endtsexample\n\n"
-   "@see ShapeBase\n\n"
-);
+IMPLEMENT_CALLBACK(RigidShapeData, onLeaveLiquid, void, (RigidShape* 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");
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
 namespace {
 namespace {
 
 
+   static U32 sWorkingQueryBoxStaleThreshold = 10;    // The maximum number of ticks that go by before
+                                                      // the mWorkingQueryBox is considered stale and
+                                                      // needs updating.  Set to -1 to disable.
+
+   static F32 sWorkingQueryBoxSizeMultiplier = 2.0f;  // How much larger should the mWorkingQueryBox be
+                                                      // made when updating the working collision list.
+                                                      // The larger this number the less often the working list
+                                                      // will be updated due to motion, but any non-static shape
+                                                      // that moves into the query box will not be noticed.
    // Client prediction
    // Client prediction
    const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
    const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
    const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
    const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
-   const F32 sRigidShapeGravity = -20;
 
 
    // Physics and collision constants
    // Physics and collision constants
    static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
    static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
@@ -265,6 +254,7 @@ RigidShapeData::RigidShapeData()
    softSplashSoundVel = 1.0;
    softSplashSoundVel = 1.0;
    medSplashSoundVel = 2.0;
    medSplashSoundVel = 2.0;
    hardSplashSoundVel = 3.0;
    hardSplashSoundVel = 3.0;
+   enablePhysicsRep = true;
 
 
    dMemset(waterSound, 0, sizeof(waterSound));
    dMemset(waterSound, 0, sizeof(waterSound));
 
 
@@ -390,6 +380,7 @@ void RigidShapeData::packData(BitStream* stream)
    stream->write(softSplashSoundVel);
    stream->write(softSplashSoundVel);
    stream->write(medSplashSoundVel);
    stream->write(medSplashSoundVel);
    stream->write(hardSplashSoundVel);
    stream->write(hardSplashSoundVel);
+   stream->write(enablePhysicsRep);
 
 
    // write the water sound profiles
    // write the water sound profiles
    for( U32 i = 0; i < MaxSounds; ++ i )
    for( U32 i = 0; i < MaxSounds; ++ i )
@@ -448,6 +439,7 @@ void RigidShapeData::unpackData(BitStream* stream)
    stream->read(&softSplashSoundVel);
    stream->read(&softSplashSoundVel);
    stream->read(&medSplashSoundVel);
    stream->read(&medSplashSoundVel);
    stream->read(&hardSplashSoundVel);
    stream->read(&hardSplashSoundVel);
+   stream->read(&enablePhysicsRep);
 
 
    // write the water sound profiles
    // write the water sound profiles
    for( U32 i = 0; i < MaxSounds; ++ i )
    for( U32 i = 0; i < MaxSounds; ++ i )
@@ -477,6 +469,11 @@ void RigidShapeData::unpackData(BitStream* stream)
 
 
 void RigidShapeData::initPersistFields()
 void RigidShapeData::initPersistFields()
 {
 {
+   addGroup("Physics");
+   addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, RigidShapeData),
+      "@brief Creates a representation of the object in the physics plugin.\n");
+   endGroup("Physics");
+
    addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
    addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
    addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
    addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
    addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
    addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
@@ -592,6 +589,12 @@ RigidShape::RigidShape()
    restCount = 0;
    restCount = 0;
 
 
    inLiquid = false;
    inLiquid = false;
+
+   mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
+
+   mPhysicsRep = NULL;
 }   
 }   
 
 
 RigidShape::~RigidShape()
 RigidShape::~RigidShape()
@@ -619,6 +622,9 @@ bool RigidShape::onAdd()
    if (!Parent::onAdd())
    if (!Parent::onAdd())
       return false;
       return false;
 
 
+   mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
+
    // When loading from a mission script, the base SceneObject's transform
    // When loading from a mission script, the base SceneObject's transform
    // will have been set and needs to be transfered to the rigid body.
    // will have been set and needs to be transfered to the rigid body.
    mRigid.setTransform(mObjToWorld);
    mRigid.setTransform(mObjToWorld);
@@ -672,6 +678,7 @@ bool RigidShape::onAdd()
    mConvex.box.minExtents.convolve(mObjScale);
    mConvex.box.minExtents.convolve(mObjScale);
    mConvex.box.maxExtents.convolve(mObjScale);
    mConvex.box.maxExtents.convolve(mObjScale);
    mConvex.findNodeTransform();
    mConvex.findNodeTransform();
+   _createPhysics();
 
 
    addToScene();
    addToScene();
 
 
@@ -722,14 +729,36 @@ void RigidShape::onRemove()
       }
       }
    }
    }
 
 
+   mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
    Parent::onRemove();
    Parent::onRemove();
 }
 }
 
 
+void RigidShape::_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());
+   }
+}
 
 
+//----------------------------------------------------------------------------
 void RigidShape::processTick(const Move* move)
 void RigidShape::processTick(const Move* move)
 {     
 {     
+   PROFILE_SCOPE(RigidShape_ProcessTick);
+
    Parent::processTick(move);
    Parent::processTick(move);
    if ( isMounted() )
    if ( isMounted() )
       return;
       return;
@@ -776,6 +805,8 @@ void RigidShape::processTick(const Move* move)
 
 
       // Update the physics based on the integration rate
       // Update the physics based on the integration rate
       S32 count = mDataBlock->integration;
       S32 count = mDataBlock->integration;
+      --mWorkingQueryBoxCountDown;
+
       if (!mDisableMove)
       if (!mDisableMove)
          updateWorkingCollisionSet(getCollisionMask());
          updateWorkingCollisionSet(getCollisionMask());
       for (U32 i = 0; i < count; i++)
       for (U32 i = 0; i < count; i++)
@@ -790,6 +821,11 @@ void RigidShape::processTick(const Move* move)
       setPosition(mRigid.linPosition, mRigid.angPosition);
       setPosition(mRigid.linPosition, mRigid.angPosition);
       setMaskBits(PositionMask);
       setMaskBits(PositionMask);
       updateContainer();
       updateContainer();
+
+      //TODO: Only update when position has actually changed
+      //no need to check if mDataBlock->enablePhysicsRep is false as mPhysicsRep will be NULL if it is
+      if (mPhysicsRep)
+         mPhysicsRep->moveKinematicTo(getTransform());
    }
    }
 }
 }
 
 
@@ -1036,6 +1072,8 @@ void RigidShape::enableCollision()
 
 
 void RigidShape::updatePos(F32 dt)
 void RigidShape::updatePos(F32 dt)
 {
 {
+   PROFILE_SCOPE(Vehicle_UpdatePos);
+
    Point3F origVelocity = mRigid.linVelocity;
    Point3F origVelocity = mRigid.linVelocity;
 
 
    // Update internal forces acting on the body.
    // Update internal forces acting on the body.
@@ -1044,19 +1082,19 @@ void RigidShape::updatePos(F32 dt)
 
 
    // Update collision information based on our current pos.
    // Update collision information based on our current pos.
    bool collided = false;
    bool collided = false;
-   if (!mRigid.atRest && !mDisableMove) 
+   if (!mRigid.atRest && !mDisableMove)
    {
    {
       collided = updateCollision(dt);
       collided = updateCollision(dt);
 
 
-      // Now that all the forces have been processed, lets       
+      // Now that all the forces have been processed, lets
       // see if we're at rest.  Basically, if the kinetic energy of
       // see if we're at rest.  Basically, if the kinetic energy of
-      // the shape is less than some percentage of the energy added
+      // the rigid body is less than some percentage of the energy added
       // by gravity for a short period, we're considered at rest.
       // by gravity for a short period, we're considered at rest.
       // This should really be part of the rigid class...
       // This should really be part of the rigid class...
-      if (mCollisionList.getCount()) 
+      if (mCollisionList.getCount())
       {
       {
          F32 k = mRigid.getKineticEnergy();
          F32 k = mRigid.getKineticEnergy();
-         F32 G = sRigidShapeGravity * dt;
+         F32 G = mNetGravity * dt;
          F32 Kg = 0.5 * mRigid.mass * G * G;
          F32 Kg = 0.5 * mRigid.mass * G * G;
          if (k < sRestTol * Kg && ++restCount > sRestCount)
          if (k < sRestTol * Kg && ++restCount > sRestCount)
             mRigid.setAtRest();
             mRigid.setAtRest();
@@ -1070,7 +1108,7 @@ void RigidShape::updatePos(F32 dt)
       mRigid.integrate(dt);
       mRigid.integrate(dt);
 
 
    // Deal with client and server scripting, sounds, etc.
    // Deal with client and server scripting, sounds, etc.
-   if (isServerObject()) 
+   if (isServerObject())
    {
    {
 
 
       // Check triggers and other objects that we normally don't
       // Check triggers and other objects that we normally don't
@@ -1083,7 +1121,7 @@ void RigidShape::updatePos(F32 dt)
       notifyCollision();
       notifyCollision();
 
 
       // Server side impact script callback
       // Server side impact script callback
-      if (collided) 
+      if (collided)
       {
       {
          VectorF collVec = mRigid.linVelocity - origVelocity;
          VectorF collVec = mRigid.linVelocity - origVelocity;
          F32 collSpeed = collVec.len();
          F32 collSpeed = collVec.len();
@@ -1091,15 +1129,15 @@ void RigidShape::updatePos(F32 dt)
             onImpact(collVec);
             onImpact(collVec);
       }
       }
 
 
-      // Water script callbacks      
-      if (!inLiquid && mWaterCoverage != 0.0f) 
+      // Water script callbacks
+      if (!inLiquid && mWaterCoverage != 0.0f)
       {
       {
-         onEnterLiquid_callback(getIdString(), mWaterCoverage, mLiquidType.c_str() );
+         mDataBlock->onEnterLiquid_callback(this, mWaterCoverage, mLiquidType.c_str());
          inLiquid = true;
          inLiquid = true;
       }
       }
-      else if (inLiquid && mWaterCoverage == 0.0f) 
+      else if (inLiquid && mWaterCoverage == 0.0f)
       {
       {
-		 onLeaveLiquid_callback(getIdString(), mLiquidType.c_str() );
+         mDataBlock->onLeaveLiquid_callback(this, mLiquidType.c_str());
          inLiquid = false;
          inLiquid = false;
       }
       }
 
 
@@ -1123,7 +1161,7 @@ void RigidShape::updatePos(F32 dt)
       // Water volume sounds
       // Water volume sounds
       F32 vSpeed = getVelocity().len();
       F32 vSpeed = getVelocity().len();
       if (!inLiquid && mWaterCoverage >= 0.8f) {
       if (!inLiquid && mWaterCoverage >= 0.8f) {
-         if (vSpeed >= mDataBlock->hardSplashSoundVel) 
+         if (vSpeed >= mDataBlock->hardSplashSoundVel)
             SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
             SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
          else
          else
             if (vSpeed >= mDataBlock->medSplashSoundVel)
             if (vSpeed >= mDataBlock->medSplashSoundVel)
@@ -1132,9 +1170,9 @@ void RigidShape::updatePos(F32 dt)
                if (vSpeed >= mDataBlock->softSplashSoundVel)
                if (vSpeed >= mDataBlock->softSplashSoundVel)
                   SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
                   SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
          inLiquid = true;
          inLiquid = true;
-      }   
+      }
       else
       else
-         if(inLiquid && mWaterCoverage < 0.8f) {
+         if (inLiquid && mWaterCoverage < 0.8f) {
             if (vSpeed >= mDataBlock->exitSplashSoundVel)
             if (vSpeed >= mDataBlock->exitSplashSoundVel)
                SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
                SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
             inLiquid = false;
             inLiquid = false;
@@ -1142,40 +1180,31 @@ void RigidShape::updatePos(F32 dt)
    }
    }
 }
 }
 
 
-
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
-void RigidShape::updateForces(F32 /*dt*/)
+void RigidShape::updateForces(F32 dt)
 {
 {
    if (mDisableMove) return;
    if (mDisableMove) return;
-   Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod);
-
-   MatrixF currTransform;
-   mRigid.getTransform(&currTransform);
 
 
    Point3F torque(0, 0, 0);
    Point3F torque(0, 0, 0);
-   Point3F force(0, 0, 0);
-
-   Point3F vel = mRigid.linVelocity;
-
-   // Gravity
-   force += gravForce;
+   Point3F force(0, 0, mRigid.mass * mNetGravity);
 
 
    // Apply drag
    // Apply drag
-   Point3F vDrag = mRigid.linVelocity;
-   vDrag.convolve(Point3F(1, 1, mDataBlock->vertFactor));
-   force -= vDrag * mDataBlock->dragForce;
+   Point3F vertDrag = mRigid.linVelocity*Point3F(1, 1, mDataBlock->vertFactor);
+   force -= vertDrag * mDataBlock->dragForce;
 
 
    // Add in physical zone force
    // Add in physical zone force
    force += mAppliedForce;
    force += mAppliedForce;
 
 
-   // Container buoyancy & drag
-   force  += Point3F(0, 0,-mBuoyancy * sRigidShapeGravity * mRigid.mass * mGravityMod);
    force  -= mRigid.linVelocity * mDrag;
    force  -= mRigid.linVelocity * mDrag;
    torque -= mRigid.angMomentum * mDrag;
    torque -= mRigid.angMomentum * mDrag;
 
 
    mRigid.force  = force;
    mRigid.force  = force;
    mRigid.torque = torque;
    mRigid.torque = torque;
+
+   // If we're still atRest, make sure we're not accumulating anything
+   if (mRigid.atRest)
+      mRigid.setAtRest();
 }
 }
 
 
 
 
@@ -1369,17 +1398,53 @@ bool RigidShape::resolveDisplacement(Rigid& ns,CollisionState *state, F32 dt)
 
 
 void RigidShape::updateWorkingCollisionSet(const U32 mask)
 void RigidShape::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());
    Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
    F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
    F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
    F32 l = (len * 1.1) + 0.1;  // fudge factor
    F32 l = (len * 1.1) + 0.1;  // fudge factor
    convexBox.minExtents -= Point3F(l, l, l);
    convexBox.minExtents -= Point3F(l, l, l);
    convexBox.maxExtents += Point3F(l, l, l);
    convexBox.maxExtents += Point3F(l, l, l);
 
 
-   disableCollision();
-   mConvex.updateWorkingList(convexBox, mask);
-   enableCollision();
-}
+   // 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
 /** Check collisions with trigger and items
@@ -1573,6 +1638,25 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream)
 
 
 //----------------------------------------------------------------------------
 //----------------------------------------------------------------------------
 
 
+//----------------------------------------------------------------------------
+
+void RigidShape::consoleInit()
+{
+   Con::addVariable("$rigidPhysics::workingQueryBoxStaleThreshold", TypeS32, &sWorkingQueryBoxStaleThreshold,
+      "@brief The maximum number of ticks that go by before the mWorkingQueryBox is considered stale and needs updating.\n\n"
+      "Other factors can cause the collision working query box to become invalidated, such as the rigid body moving far "
+      "enough outside of this cached box.  The smaller this number, the more times the working list of triangles that are "
+      "considered for collision is refreshed.  This has the greatest impact with colliding with high triangle count meshes.\n\n"
+      "@note Set to -1 to disable any time-based forced check.\n\n"
+      "@ingroup GameObjects\n");
+
+   Con::addVariable("$rigidPhysics::workingQueryBoxSizeMultiplier", TypeF32, &sWorkingQueryBoxSizeMultiplier,
+      "@brief How much larger the mWorkingQueryBox should be made when updating the working collision list.\n\n"
+      "The larger this number the less often the working list will be updated due to motion, but any non-static shape that "
+      "moves into the query box will not be noticed.\n\n"
+      "@ingroup GameObjects\n");
+}
+
 void RigidShape::initPersistFields()
 void RigidShape::initPersistFields()
 {
 {
    Parent::initPersistFields();
    Parent::initPersistFields();

+ 17 - 6
Engine/source/T3D/rigidShape.h

@@ -31,12 +31,14 @@
 #ifndef _BOXCONVEX_H_
 #ifndef _BOXCONVEX_H_
 #include "collision/boxConvex.h"
 #include "collision/boxConvex.h"
 #endif
 #endif
+#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
+#include "T3D/physics/physicsBody.h"
+#endif
 
 
 class ParticleEmitter;
 class ParticleEmitter;
 class ParticleEmitterData;
 class ParticleEmitterData;
 class ClippedPolyList;
 class ClippedPolyList;
 
 
-
 class RigidShapeData : public ShapeBaseData
 class RigidShapeData : public ShapeBaseData
 {
 {
    typedef ShapeBaseData Parent;
    typedef ShapeBaseData Parent;
@@ -112,6 +114,8 @@ class RigidShapeData : public ShapeBaseData
    F32 splashFreqMod;
    F32 splashFreqMod;
    F32 splashVelEpsilon;
    F32 splashVelEpsilon;
 
 
+   bool enablePhysicsRep;
+
 
 
    F32 dragForce;
    F32 dragForce;
    F32 vertFactor;
    F32 vertFactor;
@@ -132,6 +136,9 @@ class RigidShapeData : public ShapeBaseData
 
 
    DECLARE_CONOBJECT(RigidShapeData);
    DECLARE_CONOBJECT(RigidShapeData);
 
 
+   DECLARE_CALLBACK(void, onEnterLiquid, (RigidShape* obj, F32 coverage, const char* type));
+   DECLARE_CALLBACK(void, onLeaveLiquid, (RigidShape* obj, const char* type));
+
 };
 };
 
 
 
 
@@ -177,6 +184,8 @@ class RigidShape: public ShapeBase
       Point3F cameraRotVec;
       Point3F cameraRotVec;
    };
    };
 
 
+   PhysicsBody* mPhysicsRep;
+
    StateDelta mDelta;
    StateDelta mDelta;
    S32 mPredictionCount;            ///< Number of ticks to predict
    S32 mPredictionCount;            ///< Number of ticks to predict
    bool inLiquid;
    bool inLiquid;
@@ -196,6 +205,9 @@ class RigidShape: public ShapeBase
 
 
    GFXStateBlockRef  mSolidSB;
    GFXStateBlockRef  mSolidSB;
 
 
+   Box3F         mWorkingQueryBox;
+   S32           mWorkingQueryBoxCountDown;
+
    //
    //
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    void updatePos(F32 dt);
    void updatePos(F32 dt);
@@ -203,7 +215,6 @@ class RigidShape: public ShapeBase
    bool resolveCollision(Rigid& ns,CollisionList& cList);
    bool resolveCollision(Rigid& ns,CollisionList& cList);
    bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
    bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
    bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
    bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
-   bool findContacts(Rigid& ns,CollisionList& cList);
    void checkTriggers();
    void checkTriggers();
    static void findCallback(SceneObject* obj,void * key);
    static void findCallback(SceneObject* obj,void * key);
 
 
@@ -227,7 +238,7 @@ class RigidShape: public ShapeBase
 
 
    void _renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
    void _renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
 
 
-   void updateForces(F32);
+   void updateForces(F32 dt);
 
 
 public:
 public:
    // Test code...
    // Test code...
@@ -238,11 +249,13 @@ public:
    RigidShape();
    RigidShape();
    ~RigidShape();
    ~RigidShape();
 
 
+   static void consoleInit();
    static void initPersistFields();
    static void initPersistFields();
    void processTick(const Move *move);
    void processTick(const Move *move);
    bool onAdd();
    bool onAdd();
    void onRemove();
    void onRemove();
-   
+   void _createPhysics();
+
    /// Interpolates between move ticks @see processTick
    /// Interpolates between move ticks @see processTick
    /// @param   dt   Change in time between the last call and this call to the function
    /// @param   dt   Change in time between the last call and this call to the function
    void interpolateTick(F32 dt);
    void interpolateTick(F32 dt);
@@ -291,8 +304,6 @@ public:
    void unpackUpdate(NetConnection *conn,           BitStream *stream);
    void unpackUpdate(NetConnection *conn,           BitStream *stream);
 
 
    DECLARE_CONOBJECT(RigidShape);
    DECLARE_CONOBJECT(RigidShape);
-   DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objId, F32 waterCoverage, const char* liquidType ));
-   DECLARE_CALLBACK( void, onLeaveLiquid, ( const char* objId, const char* liquidType ));
 };
 };
 
 
 
 

+ 3 - 3
Engine/source/T3D/shapeBase.cpp

@@ -1000,7 +1000,7 @@ ShapeBase::ShapeBase()
    mLiquidHeight( 0.0f ),
    mLiquidHeight( 0.0f ),
    mWaterCoverage( 0.0f ),
    mWaterCoverage( 0.0f ),
    mAppliedForce( Point3F::Zero ),
    mAppliedForce( Point3F::Zero ),
-   mGravityMod( 1.0f ),
+   mNetGravity( 1.0f ),
    mDamageFlash( 0.0f ),
    mDamageFlash( 0.0f ),
    mWhiteOut( 0.0f ),
    mWhiteOut( 0.0f ),
    mFlipFadeVal( false ),
    mFlipFadeVal( false ),
@@ -1768,7 +1768,7 @@ void ShapeBase::updateContainer()
    // Set default values.
    // Set default values.
    mDrag = mDataBlock->drag;
    mDrag = mDataBlock->drag;
    mBuoyancy = 0.0f;      
    mBuoyancy = 0.0f;      
-   mGravityMod = 1.0;
+   mNetGravity = gGravity;
    mAppliedForce.set(0,0,0);
    mAppliedForce.set(0,0,0);
    
    
    ContainerQueryInfo info;
    ContainerQueryInfo info;
@@ -1797,7 +1797,7 @@ void ShapeBase::updateContainer()
    }
    }
 
 
    mAppliedForce = info.appliedForce;
    mAppliedForce = info.appliedForce;
-   mGravityMod = info.gravityScale;
+   mNetGravity = (1.0-mBuoyancy)*info.gravityScale* gGravity;
 
 
    //Con::printf( "WaterCoverage: %f", mWaterCoverage );
    //Con::printf( "WaterCoverage: %f", mWaterCoverage );
    //Con::printf( "Drag: %f", mDrag );
    //Con::printf( "Drag: %f", mDrag );

+ 2 - 1
Engine/source/T3D/shapeBase.h

@@ -86,6 +86,7 @@ class SFXProfile;
 
 
 typedef void* Light;
 typedef void* Light;
 
 
+const F32 gGravity = -20;
 
 
 //--------------------------------------------------------------------------
 //--------------------------------------------------------------------------
 
 
@@ -914,7 +915,7 @@ protected:
    F32 mWaterCoverage;              ///< Percent of this object covered by water
    F32 mWaterCoverage;              ///< Percent of this object covered by water
 
 
    Point3F mAppliedForce;
    Point3F mAppliedForce;
-   F32 mGravityMod;
+   F32 mNetGravity;
    /// @}
    /// @}
 
 
    F32 mDamageFlash;
    F32 mDamageFlash;

+ 3 - 6
Engine/source/T3D/vehicles/flyingVehicle.cpp

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

+ 1 - 4
Engine/source/T3D/vehicles/hoverVehicle.cpp

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

+ 1 - 272
Engine/source/T3D/vehicles/vehicle.cpp

@@ -66,7 +66,6 @@ static F32 sWorkingQueryBoxSizeMultiplier = 2.0f;  // How much larger should the
 // Client prediction
 // Client prediction
 const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
 const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
-const F32 sVehicleGravity = -20;
 
 
 // Physics and collision constants
 // Physics and collision constants
 static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
 static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
@@ -124,17 +123,6 @@ ConsoleDocClass( VehicleData,
    "@ingroup Vehicles\n"
    "@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()
 VehicleData::VehicleData()
@@ -678,9 +666,7 @@ Vehicle::Vehicle()
 
 
    mCameraOffset.set(0,0,0);
    mCameraOffset.set(0,0,0);
 
 
-   dMemset( mDustEmitterList, 0, sizeof( mDustEmitterList ) );
    dMemset( mDamageEmitterList, 0, sizeof( mDamageEmitterList ) );
    dMemset( mDamageEmitterList, 0, sizeof( mDamageEmitterList ) );
-   dMemset( mSplashEmitterList, 0, sizeof( mSplashEmitterList ) );
 
 
    mDisableMove = false;
    mDisableMove = false;
    restCount = 0;
    restCount = 0;
@@ -701,30 +687,6 @@ U32 Vehicle::getCollisionMask()
    return 0;
    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()
 bool Vehicle::onAdd()
@@ -747,21 +709,6 @@ bool Vehicle::onAdd()
    // Create Emitters on the client
    // Create Emitters on the client
    if( isClientObject() )
    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;
       U32 j;
       for( j=0; j<VehicleData::VC_NUM_DAMAGE_EMITTERS; 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.
    // 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)
 void Vehicle::advanceTime(F32 dt)
 {
 {
    PROFILE_SCOPE( Vehicle_AdvanceTime );
    PROFILE_SCOPE( Vehicle_AdvanceTime );
@@ -1080,22 +991,6 @@ void Vehicle::getCameraTransform(F32* pos, MatrixF* mat)
    mat->mul( gCamFXMgr.getTrans() );
    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)
 void Vehicle::updateMove(const Move* move)
@@ -1161,51 +1056,6 @@ void Vehicle::updateMove(const Move* move)
       mJetting = false;
       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
 /** Update the physics
 */
 */
@@ -1234,7 +1084,7 @@ void Vehicle::updatePos(F32 dt)
       if (mCollisionList.getCount()) 
       if (mCollisionList.getCount()) 
       {
       {
          F32 k = mRigid.getKineticEnergy();
          F32 k = mRigid.getKineticEnergy();
-         F32 G = sVehicleGravity * dt;
+         F32 G = mNetGravity * dt;
          F32 Kg = 0.5 * mRigid.mass * G * G;
          F32 Kg = 0.5 * mRigid.mass * G * G;
          if (k < sRestTol * Kg && ++restCount > sRestCount)
          if (k < sRestTol * Kg && ++restCount > sRestCount)
             mRigid.setAtRest();
             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 callback used in by the checkTriggers() method.
    The checkTriggers method uses a container search which will
    The checkTriggers method uses a container search which will
    invoke this callback on each obj that matches.
    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 )
 void Vehicle::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
 {
 {
    Parent::prepBatchRender( state, mountedImageIndex );
    Parent::prepBatchRender( state, mountedImageIndex );

+ 0 - 80
Engine/source/T3D/vehicles/vehicle.h

@@ -131,9 +131,6 @@ struct VehicleData : public RigidShapeData
    virtual void unpackData(BitStream* stream);
    virtual void unpackData(BitStream* stream);
 
 
    DECLARE_CONOBJECT(VehicleData);
    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;
    typedef RigidShape Parent;
 
 
   protected:
   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;
    VehicleData* mDataBlock;
-   bool inLiquid;
    SFXSource* mWakeSound;
    SFXSource* mWakeSound;
 
 
-   Point3F mCameraOffset; ///< 3rd person camera
-
    // Control
    // Control
    Point2F mSteering;
    Point2F mSteering;
    F32 mThrottle;
    F32 mThrottle;
    bool mJetting;
    bool mJetting;
 
 
-   // Rigid Body
-   bool mDisableMove;
-
    GFXStateBlockRef  mSolidSB;
    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> mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS];
-   SimObjectPtr<ParticleEmitter> mSplashEmitterList[VehicleData::VC_NUM_SPLASH_EMITTERS];
 
 
    //
    //
    virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
    virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
    void updatePos(F32 dt);
    void updatePos(F32 dt);
-   bool updateCollision(F32 dt);
-   bool findContacts(Rigid& ns,CollisionList& cList);
-   void checkTriggers();
    static void findCallback(SceneObject* obj,void * key);
    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 bool collideBody(const MatrixF& mat,Collision* info) = 0;
    virtual void updateMove(const Move* move);
    virtual void updateMove(const Move* move);
    virtual void updateForces(F32 dt);
    virtual void updateForces(F32 dt);
@@ -225,11 +172,9 @@ class Vehicle : public RigidShape
    void updateLiftoffDust( F32 dt );
    void updateLiftoffDust( F32 dt );
    void updateDamageSmoke( F32 dt );
    void updateDamageSmoke( F32 dt );
 
 
-   void updateWorkingCollisionSet(const U32 mask);
    virtual U32 getCollisionMask();
    virtual U32 getCollisionMask();
 
 
    void updateFroth( F32 dt );
    void updateFroth( F32 dt );
-   bool collidingWithWater( Point3F &waterHeight );
 
 
    /// ObjectRenderInst delegate hooked up in prepBatchRender 
    /// ObjectRenderInst delegate hooked up in prepBatchRender 
    /// if GameBase::gShowBoundingBox is true.
    /// if GameBase::gShowBoundingBox is true.
@@ -252,40 +197,15 @@ public:
    bool onAdd();
    bool onAdd();
    void onRemove();
    void onRemove();
 
 
-   void _createPhysics();
-
    /// Interpolates between move ticks @see processTick
    /// Interpolates between move ticks @see processTick
    /// @param   dt   Change in time between the last call and this call to the function
    /// @param   dt   Change in time between the last call and this call to the function
-   void interpolateTick(F32 dt);
    void advanceTime(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 );
    void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex );
 
 
    ///@name Rigid body methods
    ///@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 getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot);
    void getCameraTransform(F32* pos, MatrixF* mat);
    void getCameraTransform(F32* pos, MatrixF* mat);
    ///@}
    ///@}

+ 4 - 11
Engine/source/T3D/vehicles/wheeledVehicle.cpp

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