mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-02 20:10:32 +00:00
Merge pull request #324 from Azaezel/alpha40_gravitas_clean
code review:
This commit is contained in:
commit
5238d65faa
13 changed files with 192 additions and 488 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ class Item: public ShapeBase
|
|||
|
||||
// Static attributes
|
||||
ItemData* mDataBlock;
|
||||
static F32 mGravity;
|
||||
bool mStatic;
|
||||
bool mRotate;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 ));
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
///@}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue