瀏覽代碼

Merge pull request #324 from Azaezel/alpha40_gravitas_clean

code review:
Brian Roberts 5 年之前
父節點
當前提交
5238d65faa

+ 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 S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
 
-F32 Item::mGravity = -20.0f;
-
 const U32 sClientCollisionMask = (TerrainObjectType     |
                                   StaticShapeObjectType |
                                   VehicleObjectType     |  
@@ -716,18 +714,20 @@ void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
 
 void Item::updateVelocity(const F32 dt)
 {
+   // Container buoyancy & drag
    // 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;
    if (mDataBlock->maxVelocity > 0 && (len = mVelocity.len()) > (mDataBlock->maxVelocity * 1.05)) {
       Point3F excess = mVelocity * (1.0 - (mDataBlock->maxVelocity / len ));
       excess *= 0.1f;
       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
    ItemData* mDataBlock;
-   static F32 mGravity;
    bool mStatic;
    bool mRotate;
 

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

@@ -1581,8 +1581,6 @@ ConsoleDocClass( Player,
    "@ingroup gameObjects\n"
 );
 
-F32 Player::mGravity = -20;
-
 //----------------------------------------------------------------------------
 
 Player::Player()
@@ -2890,7 +2888,7 @@ void Player::updateMove(const Move* move)
    speed_bias = speed_bias + (speed_bias_goal - speed_bias)*0.1f;
    moveSpeed *= speed_bias;
    // 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
    // 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);
    }
 
-   // 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
    if ( mSwimming )
       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
    VectorF mVelocity;               ///< Velocity
    Point3F mAnchorPoint;            ///< Pos compression anchor
-   static F32 mGravity;             ///< Gravity
    S32 mImpactSound;
 
    bool mUseHeadZCalc;              ///< Including mHead.z in transform calculations

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

@@ -47,7 +47,8 @@
 #include "sfx/sfxSystem.h"
 #include "T3D/fx/particleEmitter.h"
 #include "console/engineAPI.h"
-
+#include "T3D/physics/physicsPlugin.h"
+#include "T3D/physics/physicsCollision.h"
 
 IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
 
@@ -152,45 +153,33 @@ ConsoleDocClass( RigidShape,
    "@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 {
 
+   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
    const S32 sMaxWarpTicks = 3;           // Max warp duration in ticks
    const S32 sMaxPredictionTicks = 30;    // Number of ticks to predict
-   const F32 sRigidShapeGravity = -20;
 
    // Physics and collision constants
    static F32 sRestTol = 0.5;             // % of gravity energy to be at rest
@@ -265,6 +254,7 @@ RigidShapeData::RigidShapeData()
    softSplashSoundVel = 1.0;
    medSplashSoundVel = 2.0;
    hardSplashSoundVel = 3.0;
+   enablePhysicsRep = true;
 
    dMemset(waterSound, 0, sizeof(waterSound));
 
@@ -390,6 +380,7 @@ void RigidShapeData::packData(BitStream* stream)
    stream->write(softSplashSoundVel);
    stream->write(medSplashSoundVel);
    stream->write(hardSplashSoundVel);
+   stream->write(enablePhysicsRep);
 
    // write the water sound profiles
    for( U32 i = 0; i < MaxSounds; ++ i )
@@ -448,6 +439,7 @@ void RigidShapeData::unpackData(BitStream* stream)
    stream->read(&softSplashSoundVel);
    stream->read(&medSplashSoundVel);
    stream->read(&hardSplashSoundVel);
+   stream->read(&enablePhysicsRep);
 
    // write the water sound profiles
    for( U32 i = 0; i < MaxSounds; ++ i )
@@ -477,6 +469,11 @@ void RigidShapeData::unpackData(BitStream* stream)
 
 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("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.");
@@ -592,6 +589,12 @@ RigidShape::RigidShape()
    restCount = 0;
 
    inLiquid = false;
+
+   mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
+
+   mPhysicsRep = NULL;
 }   
 
 RigidShape::~RigidShape()
@@ -619,6 +622,9 @@ bool RigidShape::onAdd()
    if (!Parent::onAdd())
       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
    // will have been set and needs to be transfered to the rigid body.
    mRigid.setTransform(mObjToWorld);
@@ -672,6 +678,7 @@ bool RigidShape::onAdd()
    mConvex.box.minExtents.convolve(mObjScale);
    mConvex.box.maxExtents.convolve(mObjScale);
    mConvex.findNodeTransform();
+   _createPhysics();
 
    addToScene();
 
@@ -722,14 +729,36 @@ void RigidShape::onRemove()
       }
    }
 
+   mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
+   mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
    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)
 {     
+   PROFILE_SCOPE(RigidShape_ProcessTick);
+
    Parent::processTick(move);
    if ( isMounted() )
       return;
@@ -776,6 +805,8 @@ void RigidShape::processTick(const Move* move)
 
       // Update the physics based on the integration rate
       S32 count = mDataBlock->integration;
+      --mWorkingQueryBoxCountDown;
+
       if (!mDisableMove)
          updateWorkingCollisionSet(getCollisionMask());
       for (U32 i = 0; i < count; i++)
@@ -790,6 +821,11 @@ void RigidShape::processTick(const Move* move)
       setPosition(mRigid.linPosition, mRigid.angPosition);
       setMaskBits(PositionMask);
       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)
 {
+   PROFILE_SCOPE(RigidShape_UpdatePos);
+
    Point3F origVelocity = mRigid.linVelocity;
 
    // Update internal forces acting on the body.
@@ -1044,19 +1082,19 @@ void RigidShape::updatePos(F32 dt)
 
    // Update collision information based on our current pos.
    bool collided = false;
-   if (!mRigid.atRest && !mDisableMove) 
+   if (!mRigid.atRest && !mDisableMove)
    {
       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
-      // 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.
       // This should really be part of the rigid class...
-      if (mCollisionList.getCount()) 
+      if (mCollisionList.getCount())
       {
          F32 k = mRigid.getKineticEnergy();
-         F32 G = sRigidShapeGravity * dt;
+         F32 G = mNetGravity * dt;
          F32 Kg = 0.5 * mRigid.mass * G * G;
          if (k < sRestTol * Kg && ++restCount > sRestCount)
             mRigid.setAtRest();
@@ -1070,7 +1108,7 @@ void RigidShape::updatePos(F32 dt)
       mRigid.integrate(dt);
 
    // Deal with client and server scripting, sounds, etc.
-   if (isServerObject()) 
+   if (isServerObject())
    {
 
       // Check triggers and other objects that we normally don't
@@ -1083,7 +1121,7 @@ void RigidShape::updatePos(F32 dt)
       notifyCollision();
 
       // Server side impact script callback
-      if (collided) 
+      if (collided)
       {
          VectorF collVec = mRigid.linVelocity - origVelocity;
          F32 collSpeed = collVec.len();
@@ -1091,15 +1129,15 @@ void RigidShape::updatePos(F32 dt)
             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;
       }
-      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;
       }
 
@@ -1123,7 +1161,7 @@ void RigidShape::updatePos(F32 dt)
       // Water volume sounds
       F32 vSpeed = getVelocity().len();
       if (!inLiquid && mWaterCoverage >= 0.8f) {
-         if (vSpeed >= mDataBlock->hardSplashSoundVel) 
+         if (vSpeed >= mDataBlock->hardSplashSoundVel)
             SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
          else
             if (vSpeed >= mDataBlock->medSplashSoundVel)
@@ -1132,9 +1170,9 @@ void RigidShape::updatePos(F32 dt)
                if (vSpeed >= mDataBlock->softSplashSoundVel)
                   SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
          inLiquid = true;
-      }   
+      }
       else
-         if(inLiquid && mWaterCoverage < 0.8f) {
+         if (inLiquid && mWaterCoverage < 0.8f) {
             if (vSpeed >= mDataBlock->exitSplashSoundVel)
                SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
             inLiquid = false;
@@ -1142,40 +1180,31 @@ void RigidShape::updatePos(F32 dt)
    }
 }
 
-
 //----------------------------------------------------------------------------
 
-void RigidShape::updateForces(F32 /*dt*/)
+void RigidShape::updateForces(F32 dt)
 {
    if (mDisableMove) return;
-   Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod);
-
-   MatrixF currTransform;
-   mRigid.getTransform(&currTransform);
 
    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
-   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
    force += mAppliedForce;
 
-   // Container buoyancy & drag
-   force  += Point3F(0, 0,-mBuoyancy * sRigidShapeGravity * mRigid.mass * mGravityMod);
    force  -= mRigid.linVelocity * mDrag;
    torque -= mRigid.angMomentum * mDrag;
 
    mRigid.force  = force;
    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)
 {
+   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);
 
-   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
@@ -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()
 {
    Parent::initPersistFields();

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

@@ -31,12 +31,14 @@
 #ifndef _BOXCONVEX_H_
 #include "collision/boxConvex.h"
 #endif
+#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
+#include "T3D/physics/physicsBody.h"
+#endif
 
 class ParticleEmitter;
 class ParticleEmitterData;
 class ClippedPolyList;
 
-
 class RigidShapeData : public ShapeBaseData
 {
    typedef ShapeBaseData Parent;
@@ -112,6 +114,8 @@ class RigidShapeData : public ShapeBaseData
    F32 splashFreqMod;
    F32 splashVelEpsilon;
 
+   bool enablePhysicsRep;
+
 
    F32 dragForce;
    F32 vertFactor;
@@ -132,6 +136,9 @@ class RigidShapeData : public ShapeBaseData
 
    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;
    };
 
+   PhysicsBody* mPhysicsRep;
+
    StateDelta mDelta;
    S32 mPredictionCount;            ///< Number of ticks to predict
    bool inLiquid;
@@ -196,6 +205,9 @@ class RigidShape: public ShapeBase
 
    GFXStateBlockRef  mSolidSB;
 
+   Box3F         mWorkingQueryBox;
+   S32           mWorkingQueryBoxCountDown;
+
    //
    bool onNewDataBlock( GameBaseData *dptr, bool reload );
    void updatePos(F32 dt);
@@ -203,7 +215,6 @@ class RigidShape: public ShapeBase
    bool resolveCollision(Rigid& ns,CollisionList& cList);
    bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
    bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
-   bool findContacts(Rigid& ns,CollisionList& cList);
    void checkTriggers();
    static void findCallback(SceneObject* obj,void * key);
 
@@ -227,7 +238,7 @@ class RigidShape: public ShapeBase
 
    void _renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
 
-   void updateForces(F32);
+   void updateForces(F32 dt);
 
 public:
    // Test code...
@@ -238,11 +249,13 @@ public:
    RigidShape();
    ~RigidShape();
 
+   static void consoleInit();
    static void initPersistFields();
    void processTick(const Move *move);
    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);
@@ -291,8 +304,6 @@ public:
    void unpackUpdate(NetConnection *conn,           BitStream *stream);
 
    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 ),
    mWaterCoverage( 0.0f ),
    mAppliedForce( Point3F::Zero ),
-   mGravityMod( 1.0f ),
+   mNetGravity( 1.0f ),
    mDamageFlash( 0.0f ),
    mWhiteOut( 0.0f ),
    mFlipFadeVal( false ),
@@ -1768,7 +1768,7 @@ void ShapeBase::updateContainer()
    // Set default values.
    mDrag = mDataBlock->drag;
    mBuoyancy = 0.0f;      
-   mGravityMod = 1.0;
+   mNetGravity = gGravity;
    mAppliedForce.set(0,0,0);
    
    ContainerQueryInfo info;
@@ -1797,7 +1797,7 @@ void ShapeBase::updateContainer()
    }
 
    mAppliedForce = info.appliedForce;
-   mGravityMod = info.gravityScale;
+   mNetGravity = (1.0-mBuoyancy)*info.gravityScale* gGravity;
 
    //Con::printf( "WaterCoverage: %f", mWaterCoverage );
    //Con::printf( "Drag: %f", mDrag );

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

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

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

@@ -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;
 

+ 2 - 273
Engine/source/T3D/vehicles/vehicle.cpp

@@ -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.
@@ -839,7 +770,7 @@ void Vehicle::processTick(const Move* move)
 {
    PROFILE_SCOPE( Vehicle_ProcessTick );
 
-   Parent::processTick(move);
+   ShapeBase::processTick(move);
    if ( isMounted() )
       return;
 
@@ -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 );

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

@@ -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);
    ///@}

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

@@ -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)