mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-15 16:44:36 +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 F32 sMinWarpTicks = 0.5 ; // Fraction of tick at which instant warp occures
|
||||||
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
static S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
||||||
|
|
||||||
F32 Item::mGravity = -20.0f;
|
|
||||||
|
|
||||||
const U32 sClientCollisionMask = (TerrainObjectType |
|
const U32 sClientCollisionMask = (TerrainObjectType |
|
||||||
StaticShapeObjectType |
|
StaticShapeObjectType |
|
||||||
VehicleObjectType |
|
VehicleObjectType |
|
||||||
|
|
@ -716,18 +714,20 @@ void Item::updateWorkingCollisionSet(const U32 mask, const F32 dt)
|
||||||
|
|
||||||
void Item::updateVelocity(const F32 dt)
|
void Item::updateVelocity(const F32 dt)
|
||||||
{
|
{
|
||||||
|
// Container buoyancy & drag
|
||||||
// Acceleration due to gravity
|
// Acceleration due to gravity
|
||||||
mVelocity.z += (mGravity * mDataBlock->gravityMod) * dt;
|
mVelocity.z += (mNetGravity * mDataBlock->gravityMod) * dt;
|
||||||
|
mVelocity -= mVelocity * mDrag * dt;
|
||||||
|
|
||||||
|
// Add in physical zone force
|
||||||
|
mVelocity += mAppliedForce;
|
||||||
|
|
||||||
F32 len;
|
F32 len;
|
||||||
if (mDataBlock->maxVelocity > 0 && (len = mVelocity.len()) > (mDataBlock->maxVelocity * 1.05)) {
|
if (mDataBlock->maxVelocity > 0 && (len = mVelocity.len()) > (mDataBlock->maxVelocity * 1.05)) {
|
||||||
Point3F excess = mVelocity * (1.0 - (mDataBlock->maxVelocity / len ));
|
Point3F excess = mVelocity * (1.0 - (mDataBlock->maxVelocity / len ));
|
||||||
excess *= 0.1f;
|
excess *= 0.1f;
|
||||||
mVelocity -= excess;
|
mVelocity -= excess;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container buoyancy & drag
|
|
||||||
mVelocity.z -= mBuoyancy * (mGravity * mDataBlock->gravityMod * mGravityMod) * dt;
|
|
||||||
mVelocity -= mVelocity * mDrag * dt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ class Item: public ShapeBase
|
||||||
|
|
||||||
// Static attributes
|
// Static attributes
|
||||||
ItemData* mDataBlock;
|
ItemData* mDataBlock;
|
||||||
static F32 mGravity;
|
|
||||||
bool mStatic;
|
bool mStatic;
|
||||||
bool mRotate;
|
bool mRotate;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1581,8 +1581,6 @@ ConsoleDocClass( Player,
|
||||||
"@ingroup gameObjects\n"
|
"@ingroup gameObjects\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
F32 Player::mGravity = -20;
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
Player::Player()
|
Player::Player()
|
||||||
|
|
@ -2890,7 +2888,7 @@ void Player::updateMove(const Move* move)
|
||||||
speed_bias = speed_bias + (speed_bias_goal - speed_bias)*0.1f;
|
speed_bias = speed_bias + (speed_bias_goal - speed_bias)*0.1f;
|
||||||
moveSpeed *= speed_bias;
|
moveSpeed *= speed_bias;
|
||||||
// Acceleration due to gravity
|
// Acceleration due to gravity
|
||||||
VectorF acc(0.0f, 0.0f, mGravity * mGravityMod * TickSec);
|
VectorF acc(0.0f, 0.0f, mNetGravity/(1.0 - mBuoyancy) * TickSec);
|
||||||
|
|
||||||
// Determine ground contact normal. Only look for contacts if
|
// Determine ground contact normal. Only look for contacts if
|
||||||
// we can move and aren't mounted.
|
// we can move and aren't mounted.
|
||||||
|
|
@ -3254,30 +3252,6 @@ void Player::updateMove(const Move* move)
|
||||||
mVelocity.z -= mDataBlock->upResistFactor * TickSec * (mVelocity.z - mDataBlock->upResistSpeed);
|
mVelocity.z -= mDataBlock->upResistFactor * TickSec * (mVelocity.z - mDataBlock->upResistSpeed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container buoyancy & drag
|
|
||||||
/* Commented out until the buoyancy calculation can be reworked so that a container and
|
|
||||||
** player with the same density will result in neutral buoyancy.
|
|
||||||
if (mBuoyancy != 0)
|
|
||||||
{
|
|
||||||
// Applying buoyancy when standing still causing some jitters-
|
|
||||||
if (mBuoyancy > 1.0 || !mVelocity.isZero() || !runSurface)
|
|
||||||
{
|
|
||||||
// A little hackery to prevent oscillation
|
|
||||||
// based on http://reinot.blogspot.com/2005/11/oh-yes-they-float-georgie-they-all.html
|
|
||||||
|
|
||||||
F32 buoyancyForce = mBuoyancy * mGravity * mGravityMod * TickSec;
|
|
||||||
F32 currHeight = getPosition().z;
|
|
||||||
const F32 C = 2.0f;
|
|
||||||
const F32 M = 0.1f;
|
|
||||||
|
|
||||||
if ( currHeight + mVelocity.z * TickSec * C > mLiquidHeight )
|
|
||||||
buoyancyForce *= M;
|
|
||||||
|
|
||||||
mVelocity.z -= buoyancyForce;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Apply drag
|
// Apply drag
|
||||||
if ( mSwimming )
|
if ( mSwimming )
|
||||||
mVelocity -= mVelocity * mDrag * TickSec * ( mVelocity.len() / mDataBlock->maxUnderwaterForwardSpeed );
|
mVelocity -= mVelocity * mDrag * TickSec * ( mVelocity.len() / mDataBlock->maxUnderwaterForwardSpeed );
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,6 @@ protected:
|
||||||
Point3F mRot; ///< Body rotation, uses only z
|
Point3F mRot; ///< Body rotation, uses only z
|
||||||
VectorF mVelocity; ///< Velocity
|
VectorF mVelocity; ///< Velocity
|
||||||
Point3F mAnchorPoint; ///< Pos compression anchor
|
Point3F mAnchorPoint; ///< Pos compression anchor
|
||||||
static F32 mGravity; ///< Gravity
|
|
||||||
S32 mImpactSound;
|
S32 mImpactSound;
|
||||||
|
|
||||||
bool mUseHeadZCalc; ///< Including mHead.z in transform calculations
|
bool mUseHeadZCalc; ///< Including mHead.z in transform calculations
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,8 @@
|
||||||
#include "sfx/sfxSystem.h"
|
#include "sfx/sfxSystem.h"
|
||||||
#include "T3D/fx/particleEmitter.h"
|
#include "T3D/fx/particleEmitter.h"
|
||||||
#include "console/engineAPI.h"
|
#include "console/engineAPI.h"
|
||||||
|
#include "T3D/physics/physicsPlugin.h"
|
||||||
|
#include "T3D/physics/physicsCollision.h"
|
||||||
|
|
||||||
IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
|
IMPLEMENT_CO_DATABLOCK_V1(RigidShapeData);
|
||||||
|
|
||||||
|
|
@ -152,45 +153,33 @@ ConsoleDocClass( RigidShape,
|
||||||
"@ingroup Physics\n"
|
"@ingroup Physics\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
IMPLEMENT_CALLBACK(RigidShapeData, onEnterLiquid, void, (RigidShape* obj, F32 coverage, const char* type), (obj, coverage, type),
|
||||||
|
"Called when the vehicle enters liquid.\n"
|
||||||
|
"@param obj the Vehicle object\n"
|
||||||
|
"@param coverage percentage of the vehicle's bounding box covered by the liquid\n"
|
||||||
|
"@param type type of liquid the vehicle has entered\n");
|
||||||
|
|
||||||
IMPLEMENT_CALLBACK( RigidShape, onEnterLiquid, void, ( const char* objId, F32 waterCoverage, const char* liquidType ),
|
IMPLEMENT_CALLBACK(RigidShapeData, onLeaveLiquid, void, (RigidShape* obj, const char* type), (obj, type),
|
||||||
( objId, waterCoverage, liquidType ),
|
"Called when the vehicle leaves liquid.\n"
|
||||||
"@brief Called whenever this RigidShape object enters liquid.\n\n"
|
"@param obj the Vehicle object\n"
|
||||||
"@param objId The ID of the rigidShape object.\n"
|
"@param type type of liquid the vehicle has left\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"
|
|
||||||
);
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
static U32 sWorkingQueryBoxStaleThreshold = 10; // The maximum number of ticks that go by before
|
||||||
|
// the mWorkingQueryBox is considered stale and
|
||||||
|
// needs updating. Set to -1 to disable.
|
||||||
|
|
||||||
|
static F32 sWorkingQueryBoxSizeMultiplier = 2.0f; // How much larger should the mWorkingQueryBox be
|
||||||
|
// made when updating the working collision list.
|
||||||
|
// The larger this number the less often the working list
|
||||||
|
// will be updated due to motion, but any non-static shape
|
||||||
|
// that moves into the query box will not be noticed.
|
||||||
// Client prediction
|
// Client prediction
|
||||||
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
||||||
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
|
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
|
||||||
const F32 sRigidShapeGravity = -20;
|
|
||||||
|
|
||||||
// Physics and collision constants
|
// Physics and collision constants
|
||||||
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
||||||
|
|
@ -265,6 +254,7 @@ RigidShapeData::RigidShapeData()
|
||||||
softSplashSoundVel = 1.0;
|
softSplashSoundVel = 1.0;
|
||||||
medSplashSoundVel = 2.0;
|
medSplashSoundVel = 2.0;
|
||||||
hardSplashSoundVel = 3.0;
|
hardSplashSoundVel = 3.0;
|
||||||
|
enablePhysicsRep = true;
|
||||||
|
|
||||||
dMemset(waterSound, 0, sizeof(waterSound));
|
dMemset(waterSound, 0, sizeof(waterSound));
|
||||||
|
|
||||||
|
|
@ -390,6 +380,7 @@ void RigidShapeData::packData(BitStream* stream)
|
||||||
stream->write(softSplashSoundVel);
|
stream->write(softSplashSoundVel);
|
||||||
stream->write(medSplashSoundVel);
|
stream->write(medSplashSoundVel);
|
||||||
stream->write(hardSplashSoundVel);
|
stream->write(hardSplashSoundVel);
|
||||||
|
stream->write(enablePhysicsRep);
|
||||||
|
|
||||||
// write the water sound profiles
|
// write the water sound profiles
|
||||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||||
|
|
@ -448,6 +439,7 @@ void RigidShapeData::unpackData(BitStream* stream)
|
||||||
stream->read(&softSplashSoundVel);
|
stream->read(&softSplashSoundVel);
|
||||||
stream->read(&medSplashSoundVel);
|
stream->read(&medSplashSoundVel);
|
||||||
stream->read(&hardSplashSoundVel);
|
stream->read(&hardSplashSoundVel);
|
||||||
|
stream->read(&enablePhysicsRep);
|
||||||
|
|
||||||
// write the water sound profiles
|
// write the water sound profiles
|
||||||
for( U32 i = 0; i < MaxSounds; ++ i )
|
for( U32 i = 0; i < MaxSounds; ++ i )
|
||||||
|
|
@ -477,6 +469,11 @@ void RigidShapeData::unpackData(BitStream* stream)
|
||||||
|
|
||||||
void RigidShapeData::initPersistFields()
|
void RigidShapeData::initPersistFields()
|
||||||
{
|
{
|
||||||
|
addGroup("Physics");
|
||||||
|
addField("enablePhysicsRep", TypeBool, Offset(enablePhysicsRep, RigidShapeData),
|
||||||
|
"@brief Creates a representation of the object in the physics plugin.\n");
|
||||||
|
endGroup("Physics");
|
||||||
|
|
||||||
addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
|
addField("massCenter", TypePoint3F, Offset(massCenter, RigidShapeData), "Center of mass for rigid body.");
|
||||||
addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
|
addField("massBox", TypePoint3F, Offset(massBox, RigidShapeData), "Size of inertial box.");
|
||||||
addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
|
addField("bodyRestitution", TypeF32, Offset(body.restitution, RigidShapeData), "The percentage of kinetic energy kept by this object in a collision.");
|
||||||
|
|
@ -592,6 +589,12 @@ RigidShape::RigidShape()
|
||||||
restCount = 0;
|
restCount = 0;
|
||||||
|
|
||||||
inLiquid = false;
|
inLiquid = false;
|
||||||
|
|
||||||
|
mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
|
mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
|
mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
|
||||||
|
|
||||||
|
mPhysicsRep = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RigidShape::~RigidShape()
|
RigidShape::~RigidShape()
|
||||||
|
|
@ -619,6 +622,9 @@ bool RigidShape::onAdd()
|
||||||
if (!Parent::onAdd())
|
if (!Parent::onAdd())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
|
mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
|
|
||||||
// When loading from a mission script, the base SceneObject's transform
|
// When loading from a mission script, the base SceneObject's transform
|
||||||
// will have been set and needs to be transfered to the rigid body.
|
// will have been set and needs to be transfered to the rigid body.
|
||||||
mRigid.setTransform(mObjToWorld);
|
mRigid.setTransform(mObjToWorld);
|
||||||
|
|
@ -672,6 +678,7 @@ bool RigidShape::onAdd()
|
||||||
mConvex.box.minExtents.convolve(mObjScale);
|
mConvex.box.minExtents.convolve(mObjScale);
|
||||||
mConvex.box.maxExtents.convolve(mObjScale);
|
mConvex.box.maxExtents.convolve(mObjScale);
|
||||||
mConvex.findNodeTransform();
|
mConvex.findNodeTransform();
|
||||||
|
_createPhysics();
|
||||||
|
|
||||||
addToScene();
|
addToScene();
|
||||||
|
|
||||||
|
|
@ -722,14 +729,36 @@ void RigidShape::onRemove()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mWorkingQueryBox.minExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
|
mWorkingQueryBox.maxExtents.set(-1e9f, -1e9f, -1e9f);
|
||||||
Parent::onRemove();
|
Parent::onRemove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RigidShape::_createPhysics()
|
||||||
|
{
|
||||||
|
SAFE_DELETE(mPhysicsRep);
|
||||||
|
|
||||||
|
if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TSShape* shape = mShapeInstance->getShape();
|
||||||
|
PhysicsCollision* colShape = NULL;
|
||||||
|
colShape = shape->buildColShape(false, getScale());
|
||||||
|
|
||||||
|
if (colShape)
|
||||||
|
{
|
||||||
|
PhysicsWorld* world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
|
||||||
|
mPhysicsRep = PHYSICSMGR->createBody();
|
||||||
|
mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world);
|
||||||
|
mPhysicsRep->setTransform(getTransform());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
void RigidShape::processTick(const Move* move)
|
void RigidShape::processTick(const Move* move)
|
||||||
{
|
{
|
||||||
|
PROFILE_SCOPE(RigidShape_ProcessTick);
|
||||||
|
|
||||||
Parent::processTick(move);
|
Parent::processTick(move);
|
||||||
if ( isMounted() )
|
if ( isMounted() )
|
||||||
return;
|
return;
|
||||||
|
|
@ -776,6 +805,8 @@ void RigidShape::processTick(const Move* move)
|
||||||
|
|
||||||
// Update the physics based on the integration rate
|
// Update the physics based on the integration rate
|
||||||
S32 count = mDataBlock->integration;
|
S32 count = mDataBlock->integration;
|
||||||
|
--mWorkingQueryBoxCountDown;
|
||||||
|
|
||||||
if (!mDisableMove)
|
if (!mDisableMove)
|
||||||
updateWorkingCollisionSet(getCollisionMask());
|
updateWorkingCollisionSet(getCollisionMask());
|
||||||
for (U32 i = 0; i < count; i++)
|
for (U32 i = 0; i < count; i++)
|
||||||
|
|
@ -790,6 +821,11 @@ void RigidShape::processTick(const Move* move)
|
||||||
setPosition(mRigid.linPosition, mRigid.angPosition);
|
setPosition(mRigid.linPosition, mRigid.angPosition);
|
||||||
setMaskBits(PositionMask);
|
setMaskBits(PositionMask);
|
||||||
updateContainer();
|
updateContainer();
|
||||||
|
|
||||||
|
//TODO: Only update when position has actually changed
|
||||||
|
//no need to check if mDataBlock->enablePhysicsRep is false as mPhysicsRep will be NULL if it is
|
||||||
|
if (mPhysicsRep)
|
||||||
|
mPhysicsRep->moveKinematicTo(getTransform());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1036,6 +1072,8 @@ void RigidShape::enableCollision()
|
||||||
|
|
||||||
void RigidShape::updatePos(F32 dt)
|
void RigidShape::updatePos(F32 dt)
|
||||||
{
|
{
|
||||||
|
PROFILE_SCOPE(RigidShape_UpdatePos);
|
||||||
|
|
||||||
Point3F origVelocity = mRigid.linVelocity;
|
Point3F origVelocity = mRigid.linVelocity;
|
||||||
|
|
||||||
// Update internal forces acting on the body.
|
// Update internal forces acting on the body.
|
||||||
|
|
@ -1044,19 +1082,19 @@ void RigidShape::updatePos(F32 dt)
|
||||||
|
|
||||||
// Update collision information based on our current pos.
|
// Update collision information based on our current pos.
|
||||||
bool collided = false;
|
bool collided = false;
|
||||||
if (!mRigid.atRest && !mDisableMove)
|
if (!mRigid.atRest && !mDisableMove)
|
||||||
{
|
{
|
||||||
collided = updateCollision(dt);
|
collided = updateCollision(dt);
|
||||||
|
|
||||||
// Now that all the forces have been processed, lets
|
// Now that all the forces have been processed, lets
|
||||||
// see if we're at rest. Basically, if the kinetic energy of
|
// see if we're at rest. Basically, if the kinetic energy of
|
||||||
// the shape is less than some percentage of the energy added
|
// the rigid body is less than some percentage of the energy added
|
||||||
// by gravity for a short period, we're considered at rest.
|
// by gravity for a short period, we're considered at rest.
|
||||||
// This should really be part of the rigid class...
|
// This should really be part of the rigid class...
|
||||||
if (mCollisionList.getCount())
|
if (mCollisionList.getCount())
|
||||||
{
|
{
|
||||||
F32 k = mRigid.getKineticEnergy();
|
F32 k = mRigid.getKineticEnergy();
|
||||||
F32 G = sRigidShapeGravity * dt;
|
F32 G = mNetGravity * dt;
|
||||||
F32 Kg = 0.5 * mRigid.mass * G * G;
|
F32 Kg = 0.5 * mRigid.mass * G * G;
|
||||||
if (k < sRestTol * Kg && ++restCount > sRestCount)
|
if (k < sRestTol * Kg && ++restCount > sRestCount)
|
||||||
mRigid.setAtRest();
|
mRigid.setAtRest();
|
||||||
|
|
@ -1070,7 +1108,7 @@ void RigidShape::updatePos(F32 dt)
|
||||||
mRigid.integrate(dt);
|
mRigid.integrate(dt);
|
||||||
|
|
||||||
// Deal with client and server scripting, sounds, etc.
|
// Deal with client and server scripting, sounds, etc.
|
||||||
if (isServerObject())
|
if (isServerObject())
|
||||||
{
|
{
|
||||||
|
|
||||||
// Check triggers and other objects that we normally don't
|
// Check triggers and other objects that we normally don't
|
||||||
|
|
@ -1083,7 +1121,7 @@ void RigidShape::updatePos(F32 dt)
|
||||||
notifyCollision();
|
notifyCollision();
|
||||||
|
|
||||||
// Server side impact script callback
|
// Server side impact script callback
|
||||||
if (collided)
|
if (collided)
|
||||||
{
|
{
|
||||||
VectorF collVec = mRigid.linVelocity - origVelocity;
|
VectorF collVec = mRigid.linVelocity - origVelocity;
|
||||||
F32 collSpeed = collVec.len();
|
F32 collSpeed = collVec.len();
|
||||||
|
|
@ -1091,15 +1129,15 @@ void RigidShape::updatePos(F32 dt)
|
||||||
onImpact(collVec);
|
onImpact(collVec);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Water script callbacks
|
// Water script callbacks
|
||||||
if (!inLiquid && mWaterCoverage != 0.0f)
|
if (!inLiquid && mWaterCoverage != 0.0f)
|
||||||
{
|
{
|
||||||
onEnterLiquid_callback(getIdString(), mWaterCoverage, mLiquidType.c_str() );
|
mDataBlock->onEnterLiquid_callback(this, mWaterCoverage, mLiquidType.c_str());
|
||||||
inLiquid = true;
|
inLiquid = true;
|
||||||
}
|
}
|
||||||
else if (inLiquid && mWaterCoverage == 0.0f)
|
else if (inLiquid && mWaterCoverage == 0.0f)
|
||||||
{
|
{
|
||||||
onLeaveLiquid_callback(getIdString(), mLiquidType.c_str() );
|
mDataBlock->onLeaveLiquid_callback(this, mLiquidType.c_str());
|
||||||
inLiquid = false;
|
inLiquid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1123,7 +1161,7 @@ void RigidShape::updatePos(F32 dt)
|
||||||
// Water volume sounds
|
// Water volume sounds
|
||||||
F32 vSpeed = getVelocity().len();
|
F32 vSpeed = getVelocity().len();
|
||||||
if (!inLiquid && mWaterCoverage >= 0.8f) {
|
if (!inLiquid && mWaterCoverage >= 0.8f) {
|
||||||
if (vSpeed >= mDataBlock->hardSplashSoundVel)
|
if (vSpeed >= mDataBlock->hardSplashSoundVel)
|
||||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
|
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
|
||||||
else
|
else
|
||||||
if (vSpeed >= mDataBlock->medSplashSoundVel)
|
if (vSpeed >= mDataBlock->medSplashSoundVel)
|
||||||
|
|
@ -1132,9 +1170,9 @@ void RigidShape::updatePos(F32 dt)
|
||||||
if (vSpeed >= mDataBlock->softSplashSoundVel)
|
if (vSpeed >= mDataBlock->softSplashSoundVel)
|
||||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
|
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
|
||||||
inLiquid = true;
|
inLiquid = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if(inLiquid && mWaterCoverage < 0.8f) {
|
if (inLiquid && mWaterCoverage < 0.8f) {
|
||||||
if (vSpeed >= mDataBlock->exitSplashSoundVel)
|
if (vSpeed >= mDataBlock->exitSplashSoundVel)
|
||||||
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
|
SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
|
||||||
inLiquid = false;
|
inLiquid = false;
|
||||||
|
|
@ -1142,40 +1180,31 @@ void RigidShape::updatePos(F32 dt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
void RigidShape::updateForces(F32 /*dt*/)
|
void RigidShape::updateForces(F32 dt)
|
||||||
{
|
{
|
||||||
if (mDisableMove) return;
|
if (mDisableMove) return;
|
||||||
Point3F gravForce(0, 0, sRigidShapeGravity * mRigid.mass * mGravityMod);
|
|
||||||
|
|
||||||
MatrixF currTransform;
|
|
||||||
mRigid.getTransform(&currTransform);
|
|
||||||
|
|
||||||
Point3F torque(0, 0, 0);
|
Point3F torque(0, 0, 0);
|
||||||
Point3F force(0, 0, 0);
|
Point3F force(0, 0, mRigid.mass * mNetGravity);
|
||||||
|
|
||||||
Point3F vel = mRigid.linVelocity;
|
|
||||||
|
|
||||||
// Gravity
|
|
||||||
force += gravForce;
|
|
||||||
|
|
||||||
// Apply drag
|
// Apply drag
|
||||||
Point3F vDrag = mRigid.linVelocity;
|
Point3F vertDrag = mRigid.linVelocity*Point3F(1, 1, mDataBlock->vertFactor);
|
||||||
vDrag.convolve(Point3F(1, 1, mDataBlock->vertFactor));
|
force -= vertDrag * mDataBlock->dragForce;
|
||||||
force -= vDrag * mDataBlock->dragForce;
|
|
||||||
|
|
||||||
// Add in physical zone force
|
// Add in physical zone force
|
||||||
force += mAppliedForce;
|
force += mAppliedForce;
|
||||||
|
|
||||||
// Container buoyancy & drag
|
|
||||||
force += Point3F(0, 0,-mBuoyancy * sRigidShapeGravity * mRigid.mass * mGravityMod);
|
|
||||||
force -= mRigid.linVelocity * mDrag;
|
force -= mRigid.linVelocity * mDrag;
|
||||||
torque -= mRigid.angMomentum * mDrag;
|
torque -= mRigid.angMomentum * mDrag;
|
||||||
|
|
||||||
mRigid.force = force;
|
mRigid.force = force;
|
||||||
mRigid.torque = torque;
|
mRigid.torque = torque;
|
||||||
|
|
||||||
|
// If we're still atRest, make sure we're not accumulating anything
|
||||||
|
if (mRigid.atRest)
|
||||||
|
mRigid.setAtRest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1369,17 +1398,53 @@ bool RigidShape::resolveDisplacement(Rigid& ns,CollisionState *state, F32 dt)
|
||||||
|
|
||||||
void RigidShape::updateWorkingCollisionSet(const U32 mask)
|
void RigidShape::updateWorkingCollisionSet(const U32 mask)
|
||||||
{
|
{
|
||||||
|
PROFILE_SCOPE( Vehicle_UpdateWorkingCollisionSet );
|
||||||
|
|
||||||
|
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
||||||
|
// that we will never accelerate more than 20 m/s for gravity, plus 30 m/s for
|
||||||
|
// jetting, and an equivalent 10 m/s for vehicle accel. We also assume that our
|
||||||
|
// working list is updated on a Tick basis, which means we only expand our box by
|
||||||
|
// the possible movement in that tick, plus some extra for caching purposes
|
||||||
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
|
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
|
||||||
F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
|
F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
|
||||||
F32 l = (len * 1.1) + 0.1; // fudge factor
|
F32 l = (len * 1.1) + 0.1; // fudge factor
|
||||||
convexBox.minExtents -= Point3F(l, l, l);
|
convexBox.minExtents -= Point3F(l, l, l);
|
||||||
convexBox.maxExtents += Point3F(l, l, l);
|
convexBox.maxExtents += Point3F(l, l, l);
|
||||||
|
|
||||||
disableCollision();
|
// Check to see if it is actually necessary to construct the new working list,
|
||||||
mConvex.updateWorkingList(convexBox, mask);
|
// or if we can use the cached version from the last query. We use the x
|
||||||
enableCollision();
|
// component of the min member of the mWorkingQueryBox, which is lame, but
|
||||||
}
|
// it works ok.
|
||||||
|
bool updateSet = false;
|
||||||
|
|
||||||
|
// Check containment
|
||||||
|
if ((sWorkingQueryBoxStaleThreshold == -1 || mWorkingQueryBoxCountDown > 0) && mWorkingQueryBox.minExtents.x != -1e9f)
|
||||||
|
{
|
||||||
|
if (mWorkingQueryBox.isContained(convexBox) == false)
|
||||||
|
// Needed region is outside the cached region. Update it.
|
||||||
|
updateSet = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Must update
|
||||||
|
updateSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually perform the query, if necessary
|
||||||
|
if (updateSet == true)
|
||||||
|
{
|
||||||
|
mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
|
||||||
|
|
||||||
|
const Point3F lPoint( sWorkingQueryBoxSizeMultiplier * l );
|
||||||
|
mWorkingQueryBox = convexBox;
|
||||||
|
mWorkingQueryBox.minExtents -= lPoint;
|
||||||
|
mWorkingQueryBox.maxExtents += lPoint;
|
||||||
|
|
||||||
|
disableCollision();
|
||||||
|
mConvex.updateWorkingList(mWorkingQueryBox, mask);
|
||||||
|
enableCollision();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/** Check collisions with trigger and items
|
/** Check collisions with trigger and items
|
||||||
|
|
@ -1573,6 +1638,25 @@ void RigidShape::unpackUpdate(NetConnection *con, BitStream *stream)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void RigidShape::consoleInit()
|
||||||
|
{
|
||||||
|
Con::addVariable("$rigidPhysics::workingQueryBoxStaleThreshold", TypeS32, &sWorkingQueryBoxStaleThreshold,
|
||||||
|
"@brief The maximum number of ticks that go by before the mWorkingQueryBox is considered stale and needs updating.\n\n"
|
||||||
|
"Other factors can cause the collision working query box to become invalidated, such as the rigid body moving far "
|
||||||
|
"enough outside of this cached box. The smaller this number, the more times the working list of triangles that are "
|
||||||
|
"considered for collision is refreshed. This has the greatest impact with colliding with high triangle count meshes.\n\n"
|
||||||
|
"@note Set to -1 to disable any time-based forced check.\n\n"
|
||||||
|
"@ingroup GameObjects\n");
|
||||||
|
|
||||||
|
Con::addVariable("$rigidPhysics::workingQueryBoxSizeMultiplier", TypeF32, &sWorkingQueryBoxSizeMultiplier,
|
||||||
|
"@brief How much larger the mWorkingQueryBox should be made when updating the working collision list.\n\n"
|
||||||
|
"The larger this number the less often the working list will be updated due to motion, but any non-static shape that "
|
||||||
|
"moves into the query box will not be noticed.\n\n"
|
||||||
|
"@ingroup GameObjects\n");
|
||||||
|
}
|
||||||
|
|
||||||
void RigidShape::initPersistFields()
|
void RigidShape::initPersistFields()
|
||||||
{
|
{
|
||||||
Parent::initPersistFields();
|
Parent::initPersistFields();
|
||||||
|
|
|
||||||
|
|
@ -31,12 +31,14 @@
|
||||||
#ifndef _BOXCONVEX_H_
|
#ifndef _BOXCONVEX_H_
|
||||||
#include "collision/boxConvex.h"
|
#include "collision/boxConvex.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
|
||||||
|
#include "T3D/physics/physicsBody.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class ParticleEmitter;
|
class ParticleEmitter;
|
||||||
class ParticleEmitterData;
|
class ParticleEmitterData;
|
||||||
class ClippedPolyList;
|
class ClippedPolyList;
|
||||||
|
|
||||||
|
|
||||||
class RigidShapeData : public ShapeBaseData
|
class RigidShapeData : public ShapeBaseData
|
||||||
{
|
{
|
||||||
typedef ShapeBaseData Parent;
|
typedef ShapeBaseData Parent;
|
||||||
|
|
@ -112,6 +114,8 @@ class RigidShapeData : public ShapeBaseData
|
||||||
F32 splashFreqMod;
|
F32 splashFreqMod;
|
||||||
F32 splashVelEpsilon;
|
F32 splashVelEpsilon;
|
||||||
|
|
||||||
|
bool enablePhysicsRep;
|
||||||
|
|
||||||
|
|
||||||
F32 dragForce;
|
F32 dragForce;
|
||||||
F32 vertFactor;
|
F32 vertFactor;
|
||||||
|
|
@ -132,6 +136,9 @@ class RigidShapeData : public ShapeBaseData
|
||||||
|
|
||||||
DECLARE_CONOBJECT(RigidShapeData);
|
DECLARE_CONOBJECT(RigidShapeData);
|
||||||
|
|
||||||
|
DECLARE_CALLBACK(void, onEnterLiquid, (RigidShape* obj, F32 coverage, const char* type));
|
||||||
|
DECLARE_CALLBACK(void, onLeaveLiquid, (RigidShape* obj, const char* type));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -177,6 +184,8 @@ class RigidShape: public ShapeBase
|
||||||
Point3F cameraRotVec;
|
Point3F cameraRotVec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PhysicsBody* mPhysicsRep;
|
||||||
|
|
||||||
StateDelta mDelta;
|
StateDelta mDelta;
|
||||||
S32 mPredictionCount; ///< Number of ticks to predict
|
S32 mPredictionCount; ///< Number of ticks to predict
|
||||||
bool inLiquid;
|
bool inLiquid;
|
||||||
|
|
@ -196,6 +205,9 @@ class RigidShape: public ShapeBase
|
||||||
|
|
||||||
GFXStateBlockRef mSolidSB;
|
GFXStateBlockRef mSolidSB;
|
||||||
|
|
||||||
|
Box3F mWorkingQueryBox;
|
||||||
|
S32 mWorkingQueryBoxCountDown;
|
||||||
|
|
||||||
//
|
//
|
||||||
bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
||||||
void updatePos(F32 dt);
|
void updatePos(F32 dt);
|
||||||
|
|
@ -203,7 +215,6 @@ class RigidShape: public ShapeBase
|
||||||
bool resolveCollision(Rigid& ns,CollisionList& cList);
|
bool resolveCollision(Rigid& ns,CollisionList& cList);
|
||||||
bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
|
bool resolveContacts(Rigid& ns,CollisionList& cList,F32 dt);
|
||||||
bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
|
bool resolveDisplacement(Rigid& ns,CollisionState *state,F32 dt);
|
||||||
bool findContacts(Rigid& ns,CollisionList& cList);
|
|
||||||
void checkTriggers();
|
void checkTriggers();
|
||||||
static void findCallback(SceneObject* obj,void * key);
|
static void findCallback(SceneObject* obj,void * key);
|
||||||
|
|
||||||
|
|
@ -227,7 +238,7 @@ class RigidShape: public ShapeBase
|
||||||
|
|
||||||
void _renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
void _renderMassAndContacts( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
|
||||||
|
|
||||||
void updateForces(F32);
|
void updateForces(F32 dt);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Test code...
|
// Test code...
|
||||||
|
|
@ -238,11 +249,13 @@ public:
|
||||||
RigidShape();
|
RigidShape();
|
||||||
~RigidShape();
|
~RigidShape();
|
||||||
|
|
||||||
|
static void consoleInit();
|
||||||
static void initPersistFields();
|
static void initPersistFields();
|
||||||
void processTick(const Move *move);
|
void processTick(const Move *move);
|
||||||
bool onAdd();
|
bool onAdd();
|
||||||
void onRemove();
|
void onRemove();
|
||||||
|
void _createPhysics();
|
||||||
|
|
||||||
/// Interpolates between move ticks @see processTick
|
/// Interpolates between move ticks @see processTick
|
||||||
/// @param dt Change in time between the last call and this call to the function
|
/// @param dt Change in time between the last call and this call to the function
|
||||||
void interpolateTick(F32 dt);
|
void interpolateTick(F32 dt);
|
||||||
|
|
@ -291,8 +304,6 @@ public:
|
||||||
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
void unpackUpdate(NetConnection *conn, BitStream *stream);
|
||||||
|
|
||||||
DECLARE_CONOBJECT(RigidShape);
|
DECLARE_CONOBJECT(RigidShape);
|
||||||
DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objId, F32 waterCoverage, const char* liquidType ));
|
|
||||||
DECLARE_CALLBACK( void, onLeaveLiquid, ( const char* objId, const char* liquidType ));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1000,7 +1000,7 @@ ShapeBase::ShapeBase()
|
||||||
mLiquidHeight( 0.0f ),
|
mLiquidHeight( 0.0f ),
|
||||||
mWaterCoverage( 0.0f ),
|
mWaterCoverage( 0.0f ),
|
||||||
mAppliedForce( Point3F::Zero ),
|
mAppliedForce( Point3F::Zero ),
|
||||||
mGravityMod( 1.0f ),
|
mNetGravity( 1.0f ),
|
||||||
mDamageFlash( 0.0f ),
|
mDamageFlash( 0.0f ),
|
||||||
mWhiteOut( 0.0f ),
|
mWhiteOut( 0.0f ),
|
||||||
mFlipFadeVal( false ),
|
mFlipFadeVal( false ),
|
||||||
|
|
@ -1768,7 +1768,7 @@ void ShapeBase::updateContainer()
|
||||||
// Set default values.
|
// Set default values.
|
||||||
mDrag = mDataBlock->drag;
|
mDrag = mDataBlock->drag;
|
||||||
mBuoyancy = 0.0f;
|
mBuoyancy = 0.0f;
|
||||||
mGravityMod = 1.0;
|
mNetGravity = gGravity;
|
||||||
mAppliedForce.set(0,0,0);
|
mAppliedForce.set(0,0,0);
|
||||||
|
|
||||||
ContainerQueryInfo info;
|
ContainerQueryInfo info;
|
||||||
|
|
@ -1797,7 +1797,7 @@ void ShapeBase::updateContainer()
|
||||||
}
|
}
|
||||||
|
|
||||||
mAppliedForce = info.appliedForce;
|
mAppliedForce = info.appliedForce;
|
||||||
mGravityMod = info.gravityScale;
|
mNetGravity = (1.0-mBuoyancy)*info.gravityScale* gGravity;
|
||||||
|
|
||||||
//Con::printf( "WaterCoverage: %f", mWaterCoverage );
|
//Con::printf( "WaterCoverage: %f", mWaterCoverage );
|
||||||
//Con::printf( "Drag: %f", mDrag );
|
//Con::printf( "Drag: %f", mDrag );
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ class SFXProfile;
|
||||||
|
|
||||||
typedef void* Light;
|
typedef void* Light;
|
||||||
|
|
||||||
|
const F32 gGravity = -20;
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -914,7 +915,7 @@ protected:
|
||||||
F32 mWaterCoverage; ///< Percent of this object covered by water
|
F32 mWaterCoverage; ///< Percent of this object covered by water
|
||||||
|
|
||||||
Point3F mAppliedForce;
|
Point3F mAppliedForce;
|
||||||
F32 mGravityMod;
|
F32 mNetGravity;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
F32 mDamageFlash;
|
F32 mDamageFlash;
|
||||||
|
|
|
||||||
|
|
@ -50,8 +50,6 @@ const static U32 sCollisionMoveMask = ( TerrainObjectType | WaterObjectType
|
||||||
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
|
static U32 sServerCollisionMask = sCollisionMoveMask; // ItemObjectType
|
||||||
static U32 sClientCollisionMask = sCollisionMoveMask;
|
static U32 sClientCollisionMask = sCollisionMoveMask;
|
||||||
|
|
||||||
static F32 sFlyingVehicleGravity = -20.0f;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
const char* FlyingVehicle::sJetSequence[FlyingVehicle::JetAnimCount] =
|
const char* FlyingVehicle::sJetSequence[FlyingVehicle::JetAnimCount] =
|
||||||
{
|
{
|
||||||
|
|
@ -485,6 +483,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE( FlyingVehicle_UpdateForces );
|
PROFILE_SCOPE( FlyingVehicle_UpdateForces );
|
||||||
|
|
||||||
|
if (mDisableMove) return;
|
||||||
MatrixF currPosMat;
|
MatrixF currPosMat;
|
||||||
mRigid.getTransform(&currPosMat);
|
mRigid.getTransform(&currPosMat);
|
||||||
mRigid.atRest = false;
|
mRigid.atRest = false;
|
||||||
|
|
@ -498,7 +497,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
|
||||||
currPosMat.getColumn(2,&zv);
|
currPosMat.getColumn(2,&zv);
|
||||||
F32 speed = mRigid.linVelocity.len();
|
F32 speed = mRigid.linVelocity.len();
|
||||||
|
|
||||||
Point3F force = Point3F(0, 0, sFlyingVehicleGravity * mRigid.mass * mGravityMod);
|
Point3F force = Point3F(0, 0, mRigid.mass * mNetGravity);
|
||||||
Point3F torque = Point3F(0, 0, 0);
|
Point3F torque = Point3F(0, 0, 0);
|
||||||
|
|
||||||
// Drag at any speed
|
// Drag at any speed
|
||||||
|
|
@ -520,7 +519,7 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hovering Jet
|
// Hovering Jet
|
||||||
F32 vf = -sFlyingVehicleGravity * mRigid.mass * mGravityMod;
|
F32 vf = mRigid.mass * -mNetGravity;
|
||||||
F32 h = getHeight();
|
F32 h = getHeight();
|
||||||
if (h <= 1) {
|
if (h <= 1) {
|
||||||
if (h > 0) {
|
if (h > 0) {
|
||||||
|
|
@ -567,8 +566,6 @@ void FlyingVehicle::updateForces(F32 /*dt*/)
|
||||||
// Add in force from physical zones...
|
// Add in force from physical zones...
|
||||||
force += mAppliedForce;
|
force += mAppliedForce;
|
||||||
|
|
||||||
// Container buoyancy & drag
|
|
||||||
force -= Point3F(0, 0, 1) * (mBuoyancy * sFlyingVehicleGravity * mRigid.mass * mGravityMod);
|
|
||||||
force -= mRigid.linVelocity * mDrag;
|
force -= mRigid.linVelocity * mDrag;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,6 @@ ConsoleDocClass( HoverVehicle,
|
||||||
);
|
);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const F32 sHoverVehicleGravity = -20;
|
|
||||||
|
|
||||||
const U32 sCollisionMoveMask = (TerrainObjectType | PlayerObjectType |
|
const U32 sCollisionMoveMask = (TerrainObjectType | PlayerObjectType |
|
||||||
StaticShapeObjectType | VehicleObjectType |
|
StaticShapeObjectType | VehicleObjectType |
|
||||||
|
|
@ -674,7 +673,7 @@ void HoverVehicle::updateForces(F32 /*dt*/)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE( HoverVehicle_UpdateForces );
|
PROFILE_SCOPE( HoverVehicle_UpdateForces );
|
||||||
|
|
||||||
Point3F gravForce(0, 0, sHoverVehicleGravity * mRigid.mass * mGravityMod);
|
Point3F gravForce(0, 0, mRigid.mass * mNetGravity);
|
||||||
|
|
||||||
MatrixF currTransform;
|
MatrixF currTransform;
|
||||||
mRigid.getTransform(&currTransform);
|
mRigid.getTransform(&currTransform);
|
||||||
|
|
@ -872,8 +871,6 @@ void HoverVehicle::updateForces(F32 /*dt*/)
|
||||||
// Add in physical zone force
|
// Add in physical zone force
|
||||||
force += mAppliedForce;
|
force += mAppliedForce;
|
||||||
|
|
||||||
// Container buoyancy & drag
|
|
||||||
force += Point3F(0, 0,-mBuoyancy * sHoverVehicleGravity * mRigid.mass * mGravityMod);
|
|
||||||
force -= mRigid.linVelocity * mDrag;
|
force -= mRigid.linVelocity * mDrag;
|
||||||
torque -= mRigid.angMomentum * mDrag;
|
torque -= mRigid.angMomentum * mDrag;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,6 @@ static F32 sWorkingQueryBoxSizeMultiplier = 2.0f; // How much larger should the
|
||||||
// Client prediction
|
// Client prediction
|
||||||
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
const S32 sMaxWarpTicks = 3; // Max warp duration in ticks
|
||||||
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
|
const S32 sMaxPredictionTicks = 30; // Number of ticks to predict
|
||||||
const F32 sVehicleGravity = -20;
|
|
||||||
|
|
||||||
// Physics and collision constants
|
// Physics and collision constants
|
||||||
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
static F32 sRestTol = 0.5; // % of gravity energy to be at rest
|
||||||
|
|
@ -124,17 +123,6 @@ ConsoleDocClass( VehicleData,
|
||||||
"@ingroup Vehicles\n"
|
"@ingroup Vehicles\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
IMPLEMENT_CALLBACK( VehicleData, onEnterLiquid, void, ( Vehicle* obj, F32 coverage, const char* type ), ( obj, coverage, type ),
|
|
||||||
"Called when the vehicle enters liquid.\n"
|
|
||||||
"@param obj the Vehicle object\n"
|
|
||||||
"@param coverage percentage of the vehicle's bounding box covered by the liquid\n"
|
|
||||||
"@param type type of liquid the vehicle has entered\n" );
|
|
||||||
|
|
||||||
IMPLEMENT_CALLBACK( VehicleData, onLeaveLiquid, void, ( Vehicle* obj, const char* type ), ( obj, type ),
|
|
||||||
"Called when the vehicle leaves liquid.\n"
|
|
||||||
"@param obj the Vehicle object\n"
|
|
||||||
"@param type type of liquid the vehicle has left\n" );
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
VehicleData::VehicleData()
|
VehicleData::VehicleData()
|
||||||
|
|
@ -678,9 +666,7 @@ Vehicle::Vehicle()
|
||||||
|
|
||||||
mCameraOffset.set(0,0,0);
|
mCameraOffset.set(0,0,0);
|
||||||
|
|
||||||
dMemset( mDustEmitterList, 0, sizeof( mDustEmitterList ) );
|
|
||||||
dMemset( mDamageEmitterList, 0, sizeof( mDamageEmitterList ) );
|
dMemset( mDamageEmitterList, 0, sizeof( mDamageEmitterList ) );
|
||||||
dMemset( mSplashEmitterList, 0, sizeof( mSplashEmitterList ) );
|
|
||||||
|
|
||||||
mDisableMove = false;
|
mDisableMove = false;
|
||||||
restCount = 0;
|
restCount = 0;
|
||||||
|
|
@ -701,30 +687,6 @@ U32 Vehicle::getCollisionMask()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point3F Vehicle::getVelocity() const
|
|
||||||
{
|
|
||||||
return mRigid.linVelocity;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::_createPhysics()
|
|
||||||
{
|
|
||||||
SAFE_DELETE(mPhysicsRep);
|
|
||||||
|
|
||||||
if (!PHYSICSMGR || !mDataBlock->enablePhysicsRep)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TSShape *shape = mShapeInstance->getShape();
|
|
||||||
PhysicsCollision *colShape = NULL;
|
|
||||||
colShape = shape->buildColShape(false, getScale());
|
|
||||||
|
|
||||||
if (colShape)
|
|
||||||
{
|
|
||||||
PhysicsWorld *world = PHYSICSMGR->getWorld(isServerObject() ? "server" : "client");
|
|
||||||
mPhysicsRep = PHYSICSMGR->createBody();
|
|
||||||
mPhysicsRep->init(colShape, 0, PhysicsBody::BF_KINEMATIC, this, world);
|
|
||||||
mPhysicsRep->setTransform(getTransform());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
bool Vehicle::onAdd()
|
bool Vehicle::onAdd()
|
||||||
|
|
@ -747,21 +709,6 @@ bool Vehicle::onAdd()
|
||||||
// Create Emitters on the client
|
// Create Emitters on the client
|
||||||
if( isClientObject() )
|
if( isClientObject() )
|
||||||
{
|
{
|
||||||
if( mDataBlock->dustEmitter )
|
|
||||||
{
|
|
||||||
for( S32 i=0; i<VehicleData::VC_NUM_DUST_EMITTERS; i++ )
|
|
||||||
{
|
|
||||||
mDustEmitterList[i] = new ParticleEmitter;
|
|
||||||
mDustEmitterList[i]->onNewDataBlock( mDataBlock->dustEmitter, false );
|
|
||||||
if( !mDustEmitterList[i]->registerObject() )
|
|
||||||
{
|
|
||||||
Con::warnf( ConsoleLogEntry::General, "Could not register dust emitter for class: %s", mDataBlock->getName() );
|
|
||||||
delete mDustEmitterList[i];
|
|
||||||
mDustEmitterList[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
U32 j;
|
U32 j;
|
||||||
for( j=0; j<VehicleData::VC_NUM_DAMAGE_EMITTERS; j++ )
|
for( j=0; j<VehicleData::VC_NUM_DAMAGE_EMITTERS; j++ )
|
||||||
{
|
{
|
||||||
|
|
@ -778,22 +725,6 @@ bool Vehicle::onAdd()
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( j=0; j<VehicleData::VC_NUM_SPLASH_EMITTERS; j++ )
|
|
||||||
{
|
|
||||||
if( mDataBlock->splashEmitterList[j] )
|
|
||||||
{
|
|
||||||
mSplashEmitterList[j] = new ParticleEmitter;
|
|
||||||
mSplashEmitterList[j]->onNewDataBlock( mDataBlock->splashEmitterList[j], false );
|
|
||||||
if( !mSplashEmitterList[j]->registerObject() )
|
|
||||||
{
|
|
||||||
Con::warnf( ConsoleLogEntry::General, "Could not register splash emitter for class: %s", mDataBlock->getName() );
|
|
||||||
delete mSplashEmitterList[j];
|
|
||||||
mSplashEmitterList[j] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new convex.
|
// Create a new convex.
|
||||||
|
|
@ -839,7 +770,7 @@ void Vehicle::processTick(const Move* move)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE( Vehicle_ProcessTick );
|
PROFILE_SCOPE( Vehicle_ProcessTick );
|
||||||
|
|
||||||
Parent::processTick(move);
|
ShapeBase::processTick(move);
|
||||||
if ( isMounted() )
|
if ( isMounted() )
|
||||||
return;
|
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)
|
void Vehicle::advanceTime(F32 dt)
|
||||||
{
|
{
|
||||||
PROFILE_SCOPE( Vehicle_AdvanceTime );
|
PROFILE_SCOPE( Vehicle_AdvanceTime );
|
||||||
|
|
@ -1080,22 +991,6 @@ void Vehicle::getCameraTransform(F32* pos, MatrixF* mat)
|
||||||
mat->mul( gCamFXMgr.getTrans() );
|
mat->mul( gCamFXMgr.getTrans() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Vehicle::getVelocity(const Point3F& r, Point3F* v)
|
|
||||||
{
|
|
||||||
mRigid.getVelocity(r, v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::applyImpulse(const Point3F &pos, const Point3F &impulse)
|
|
||||||
{
|
|
||||||
Point3F r;
|
|
||||||
mRigid.getOriginVector(pos,&r);
|
|
||||||
mRigid.applyImpulse(r, impulse);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
void Vehicle::updateMove(const Move* move)
|
void Vehicle::updateMove(const Move* move)
|
||||||
|
|
@ -1161,51 +1056,6 @@ void Vehicle::updateMove(const Move* move)
|
||||||
mJetting = false;
|
mJetting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Vehicle::setPosition(const Point3F& pos,const QuatF& rot)
|
|
||||||
{
|
|
||||||
MatrixF mat;
|
|
||||||
rot.setMatrix(&mat);
|
|
||||||
mat.setColumn(3,pos);
|
|
||||||
Parent::setTransform(mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::setRenderPosition(const Point3F& pos, const QuatF& rot)
|
|
||||||
{
|
|
||||||
MatrixF mat;
|
|
||||||
rot.setMatrix(&mat);
|
|
||||||
mat.setColumn(3,pos);
|
|
||||||
Parent::setRenderTransform(mat);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::setTransform(const MatrixF& newMat)
|
|
||||||
{
|
|
||||||
mRigid.setTransform(newMat);
|
|
||||||
Parent::setTransform(newMat);
|
|
||||||
mRigid.atRest = false;
|
|
||||||
mContacts.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Vehicle::disableCollision()
|
|
||||||
{
|
|
||||||
Parent::disableCollision();
|
|
||||||
for (SceneObject* ptr = getMountList(); ptr; ptr = ptr->getMountLink())
|
|
||||||
ptr->disableCollision();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::enableCollision()
|
|
||||||
{
|
|
||||||
Parent::enableCollision();
|
|
||||||
for (SceneObject* ptr = getMountList(); ptr; ptr = ptr->getMountLink())
|
|
||||||
ptr->enableCollision();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
/** Update the physics
|
/** Update the physics
|
||||||
*/
|
*/
|
||||||
|
|
@ -1234,7 +1084,7 @@ void Vehicle::updatePos(F32 dt)
|
||||||
if (mCollisionList.getCount())
|
if (mCollisionList.getCount())
|
||||||
{
|
{
|
||||||
F32 k = mRigid.getKineticEnergy();
|
F32 k = mRigid.getKineticEnergy();
|
||||||
F32 G = sVehicleGravity * dt;
|
F32 G = mNetGravity * dt;
|
||||||
F32 Kg = 0.5 * mRigid.mass * G * G;
|
F32 Kg = 0.5 * mRigid.mass * G * G;
|
||||||
if (k < sRestTol * Kg && ++restCount > sRestCount)
|
if (k < sRestTol * Kg && ++restCount > sRestCount)
|
||||||
mRigid.setAtRest();
|
mRigid.setAtRest();
|
||||||
|
|
@ -1325,101 +1175,6 @@ void Vehicle::updateForces(F32 /*dt*/)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
/** Update collision information
|
|
||||||
Update the convex state and check for collisions. If the object is in
|
|
||||||
collision, impact and contact forces are generated.
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool Vehicle::updateCollision(F32 dt)
|
|
||||||
{
|
|
||||||
PROFILE_SCOPE( Vehicle_UpdateCollision );
|
|
||||||
|
|
||||||
// Update collision information
|
|
||||||
MatrixF mat,cmat;
|
|
||||||
mConvex.transform = &mat;
|
|
||||||
mRigid.getTransform(&mat);
|
|
||||||
cmat = mConvex.getTransform();
|
|
||||||
|
|
||||||
mCollisionList.clear();
|
|
||||||
CollisionState *state = mConvex.findClosestState(cmat, getScale(), mDataBlock->collisionTol);
|
|
||||||
if (state && state->mDist <= mDataBlock->collisionTol)
|
|
||||||
{
|
|
||||||
//resolveDisplacement(ns,state,dt);
|
|
||||||
mConvex.getCollisionInfo(cmat, getScale(), &mCollisionList, mDataBlock->collisionTol);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve collisions
|
|
||||||
bool collided = resolveCollision(mRigid,mCollisionList);
|
|
||||||
resolveContacts(mRigid,mCollisionList,dt);
|
|
||||||
return collided;
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void Vehicle::updateWorkingCollisionSet(const U32 mask)
|
|
||||||
{
|
|
||||||
PROFILE_SCOPE( Vehicle_UpdateWorkingCollisionSet );
|
|
||||||
|
|
||||||
// First, we need to adjust our velocity for possible acceleration. It is assumed
|
|
||||||
// that we will never accelerate more than 20 m/s for gravity, plus 30 m/s for
|
|
||||||
// jetting, and an equivalent 10 m/s for vehicle accel. We also assume that our
|
|
||||||
// working list is updated on a Tick basis, which means we only expand our box by
|
|
||||||
// the possible movement in that tick, plus some extra for caching purposes
|
|
||||||
Box3F convexBox = mConvex.getBoundingBox(getTransform(), getScale());
|
|
||||||
F32 len = (mRigid.linVelocity.len() + 50) * TickSec;
|
|
||||||
F32 l = (len * 1.1) + 0.1; // fudge factor
|
|
||||||
convexBox.minExtents -= Point3F(l, l, l);
|
|
||||||
convexBox.maxExtents += Point3F(l, l, l);
|
|
||||||
|
|
||||||
// Check to see if it is actually necessary to construct the new working list,
|
|
||||||
// or if we can use the cached version from the last query. We use the x
|
|
||||||
// component of the min member of the mWorkingQueryBox, which is lame, but
|
|
||||||
// it works ok.
|
|
||||||
bool updateSet = false;
|
|
||||||
|
|
||||||
// Check containment
|
|
||||||
if ((sWorkingQueryBoxStaleThreshold == -1 || mWorkingQueryBoxCountDown > 0) && mWorkingQueryBox.minExtents.x != -1e9f)
|
|
||||||
{
|
|
||||||
if (mWorkingQueryBox.isContained(convexBox) == false)
|
|
||||||
// Needed region is outside the cached region. Update it.
|
|
||||||
updateSet = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Must update
|
|
||||||
updateSet = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actually perform the query, if necessary
|
|
||||||
if (updateSet == true)
|
|
||||||
{
|
|
||||||
mWorkingQueryBoxCountDown = sWorkingQueryBoxStaleThreshold;
|
|
||||||
|
|
||||||
const Point3F lPoint( sWorkingQueryBoxSizeMultiplier * l );
|
|
||||||
mWorkingQueryBox = convexBox;
|
|
||||||
mWorkingQueryBox.minExtents -= lPoint;
|
|
||||||
mWorkingQueryBox.maxExtents += lPoint;
|
|
||||||
|
|
||||||
disableCollision();
|
|
||||||
mConvex.updateWorkingList(mWorkingQueryBox, mask);
|
|
||||||
enableCollision();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
/** Check collisions with trigger and items
|
|
||||||
Perform a container search using the current bounding box
|
|
||||||
of the main body, wheels are not included. This method should
|
|
||||||
only be called on the server.
|
|
||||||
*/
|
|
||||||
void Vehicle::checkTriggers()
|
|
||||||
{
|
|
||||||
Box3F bbox = mConvex.getBoundingBox(getTransform(), getScale());
|
|
||||||
gServerContainer.findObjects(bbox,sTriggerMask,findCallback,this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The callback used in by the checkTriggers() method.
|
/** The callback used in by the checkTriggers() method.
|
||||||
The checkTriggers method uses a container search which will
|
The checkTriggers method uses a container search which will
|
||||||
invoke this callback on each obj that matches.
|
invoke this callback on each obj that matches.
|
||||||
|
|
@ -1743,32 +1498,6 @@ void Vehicle::updateFroth( F32 dt )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Returns true if vehicle is intersecting a water surface (roughly)
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
bool Vehicle::collidingWithWater( Point3F &waterHeight )
|
|
||||||
{
|
|
||||||
Point3F curPos = getPosition();
|
|
||||||
|
|
||||||
F32 height = mFabs( mObjBox.maxExtents.z - mObjBox.minExtents.z );
|
|
||||||
|
|
||||||
RayInfo rInfo;
|
|
||||||
if( gClientContainer.castRay( curPos + Point3F(0.0, 0.0, height), curPos, WaterObjectType, &rInfo) )
|
|
||||||
{
|
|
||||||
waterHeight = rInfo.point;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::setEnergyLevel(F32 energy)
|
|
||||||
{
|
|
||||||
Parent::setEnergyLevel(energy);
|
|
||||||
setMaskBits(EnergyMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vehicle::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
|
void Vehicle::prepBatchRender( SceneRenderState *state, S32 mountedImageIndex )
|
||||||
{
|
{
|
||||||
Parent::prepBatchRender( state, mountedImageIndex );
|
Parent::prepBatchRender( state, mountedImageIndex );
|
||||||
|
|
|
||||||
|
|
@ -131,9 +131,6 @@ struct VehicleData : public RigidShapeData
|
||||||
virtual void unpackData(BitStream* stream);
|
virtual void unpackData(BitStream* stream);
|
||||||
|
|
||||||
DECLARE_CONOBJECT(VehicleData);
|
DECLARE_CONOBJECT(VehicleData);
|
||||||
|
|
||||||
DECLARE_CALLBACK( void, onEnterLiquid, ( Vehicle* obj, F32 coverage, const char* type ) );
|
|
||||||
DECLARE_CALLBACK( void, onLeaveLiquid, ( Vehicle* obj, const char* type ) );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -145,74 +142,24 @@ class Vehicle : public RigidShape
|
||||||
typedef RigidShape Parent;
|
typedef RigidShape Parent;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum CollisionFaceFlags {
|
|
||||||
BodyCollision = 0x1,
|
|
||||||
WheelCollision = 0x2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct StateDelta {
|
|
||||||
Move move; ///< Last move from server
|
|
||||||
F32 dt; ///< Last interpolation time
|
|
||||||
// Interpolation data
|
|
||||||
Point3F pos;
|
|
||||||
Point3F posVec;
|
|
||||||
QuatF rot[2];
|
|
||||||
// Warp data
|
|
||||||
S32 warpTicks; ///< Number of ticks to warp
|
|
||||||
S32 warpCount; ///< Current pos in warp
|
|
||||||
Point3F warpOffset;
|
|
||||||
QuatF warpRot[2];
|
|
||||||
//
|
|
||||||
Point3F cameraOffset;
|
|
||||||
Point3F cameraVec;
|
|
||||||
Point3F cameraRot;
|
|
||||||
Point3F cameraRotVec;
|
|
||||||
};
|
|
||||||
|
|
||||||
PhysicsBody *mPhysicsRep;
|
|
||||||
|
|
||||||
StateDelta mDelta;
|
|
||||||
S32 mPredictionCount; ///< Number of ticks to predict
|
|
||||||
VehicleData* mDataBlock;
|
VehicleData* mDataBlock;
|
||||||
bool inLiquid;
|
|
||||||
SFXSource* mWakeSound;
|
SFXSource* mWakeSound;
|
||||||
|
|
||||||
Point3F mCameraOffset; ///< 3rd person camera
|
|
||||||
|
|
||||||
// Control
|
// Control
|
||||||
Point2F mSteering;
|
Point2F mSteering;
|
||||||
F32 mThrottle;
|
F32 mThrottle;
|
||||||
bool mJetting;
|
bool mJetting;
|
||||||
|
|
||||||
// Rigid Body
|
|
||||||
bool mDisableMove;
|
|
||||||
|
|
||||||
GFXStateBlockRef mSolidSB;
|
GFXStateBlockRef mSolidSB;
|
||||||
|
|
||||||
Box3F mWorkingQueryBox;
|
|
||||||
S32 mWorkingQueryBoxCountDown;
|
|
||||||
|
|
||||||
CollisionList mCollisionList;
|
|
||||||
CollisionList mContacts;
|
|
||||||
ShapeBaseConvex mConvex;
|
|
||||||
S32 restCount;
|
|
||||||
|
|
||||||
SimObjectPtr<ParticleEmitter> mDustEmitterList[VehicleData::VC_NUM_DUST_EMITTERS];
|
|
||||||
SimObjectPtr<ParticleEmitter> mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS];
|
SimObjectPtr<ParticleEmitter> mDamageEmitterList[VehicleData::VC_NUM_DAMAGE_EMITTERS];
|
||||||
SimObjectPtr<ParticleEmitter> mSplashEmitterList[VehicleData::VC_NUM_SPLASH_EMITTERS];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
|
||||||
void updatePos(F32 dt);
|
void updatePos(F32 dt);
|
||||||
bool updateCollision(F32 dt);
|
|
||||||
bool findContacts(Rigid& ns,CollisionList& cList);
|
|
||||||
void checkTriggers();
|
|
||||||
static void findCallback(SceneObject* obj,void * key);
|
static void findCallback(SceneObject* obj,void * key);
|
||||||
|
|
||||||
void setPosition(const Point3F& pos,const QuatF& rot);
|
|
||||||
void setRenderPosition(const Point3F& pos,const QuatF& rot);
|
|
||||||
void setTransform(const MatrixF& mat);
|
|
||||||
|
|
||||||
// virtual bool collideBody(const MatrixF& mat,Collision* info) = 0;
|
// virtual bool collideBody(const MatrixF& mat,Collision* info) = 0;
|
||||||
virtual void updateMove(const Move* move);
|
virtual void updateMove(const Move* move);
|
||||||
virtual void updateForces(F32 dt);
|
virtual void updateForces(F32 dt);
|
||||||
|
|
@ -225,11 +172,9 @@ class Vehicle : public RigidShape
|
||||||
void updateLiftoffDust( F32 dt );
|
void updateLiftoffDust( F32 dt );
|
||||||
void updateDamageSmoke( F32 dt );
|
void updateDamageSmoke( F32 dt );
|
||||||
|
|
||||||
void updateWorkingCollisionSet(const U32 mask);
|
|
||||||
virtual U32 getCollisionMask();
|
virtual U32 getCollisionMask();
|
||||||
|
|
||||||
void updateFroth( F32 dt );
|
void updateFroth( F32 dt );
|
||||||
bool collidingWithWater( Point3F &waterHeight );
|
|
||||||
|
|
||||||
/// ObjectRenderInst delegate hooked up in prepBatchRender
|
/// ObjectRenderInst delegate hooked up in prepBatchRender
|
||||||
/// if GameBase::gShowBoundingBox is true.
|
/// if GameBase::gShowBoundingBox is true.
|
||||||
|
|
@ -252,40 +197,15 @@ public:
|
||||||
bool onAdd();
|
bool onAdd();
|
||||||
void onRemove();
|
void onRemove();
|
||||||
|
|
||||||
void _createPhysics();
|
|
||||||
|
|
||||||
/// Interpolates between move ticks @see processTick
|
/// Interpolates between move ticks @see processTick
|
||||||
/// @param dt Change in time between the last call and this call to the function
|
/// @param dt Change in time between the last call and this call to the function
|
||||||
void interpolateTick(F32 dt);
|
|
||||||
void advanceTime(F32 dt);
|
void advanceTime(F32 dt);
|
||||||
|
|
||||||
/// Disables collisions for this vehicle and all mounted objects
|
|
||||||
void disableCollision();
|
|
||||||
|
|
||||||
/// Enables collisions for this vehicle and all mounted objects
|
|
||||||
void enableCollision();
|
|
||||||
|
|
||||||
/// Returns the velocity of the vehicle
|
|
||||||
Point3F getVelocity() const;
|
|
||||||
|
|
||||||
void setEnergyLevel(F32 energy);
|
|
||||||
|
|
||||||
void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex );
|
void prepBatchRender( SceneRenderState *state, S32 mountedImageIndex );
|
||||||
|
|
||||||
///@name Rigid body methods
|
///@name Rigid body methods
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
/// This method will get the velocity of the object, taking into account
|
|
||||||
/// angular velocity.
|
|
||||||
/// @param r Point on the object you want the velocity of, relative to Center of Mass
|
|
||||||
/// @param vel Velocity (out)
|
|
||||||
void getVelocity(const Point3F& r, Point3F* vel);
|
|
||||||
|
|
||||||
/// Applies an impulse force
|
|
||||||
/// @param r Point on the object to apply impulse to, r is relative to Center of Mass
|
|
||||||
/// @param impulse Impulse vector to apply.
|
|
||||||
void applyImpulse(const Point3F &r, const Point3F &impulse);
|
|
||||||
|
|
||||||
void getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot);
|
void getCameraParameters(F32 *min, F32* max, Point3F* offset, MatrixF* rot);
|
||||||
void getCameraTransform(F32* pos, MatrixF* mat);
|
void getCameraTransform(F32* pos, MatrixF* mat);
|
||||||
///@}
|
///@}
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,6 @@ static U32 sClientCollisionMask =
|
||||||
StaticShapeObjectType | VehicleObjectType |
|
StaticShapeObjectType | VehicleObjectType |
|
||||||
VehicleBlockerObjectType;
|
VehicleBlockerObjectType;
|
||||||
|
|
||||||
// Gravity constant
|
|
||||||
static F32 sWheeledVehicleGravity = -20;
|
|
||||||
|
|
||||||
// Misc. sound constants
|
// Misc. sound constants
|
||||||
static F32 sMinSquealVolume = 0.05f;
|
static F32 sMinSquealVolume = 0.05f;
|
||||||
static F32 sIdleEngineVolume = 0.2f;
|
static F32 sIdleEngineVolume = 0.2f;
|
||||||
|
|
@ -857,6 +854,7 @@ void WheeledVehicle::updateForces(F32 dt)
|
||||||
|
|
||||||
extendWheels();
|
extendWheels();
|
||||||
|
|
||||||
|
if (mDisableMove) return;
|
||||||
F32 aMomentum = mMass / mDataBlock->wheelCount;
|
F32 aMomentum = mMass / mDataBlock->wheelCount;
|
||||||
|
|
||||||
// Get the current matrix and extact vectors
|
// Get the current matrix and extact vectors
|
||||||
|
|
@ -902,8 +900,7 @@ void WheeledVehicle::updateForces(F32 dt)
|
||||||
// Integrate forces, we'll do this ourselves here instead of
|
// Integrate forces, we'll do this ourselves here instead of
|
||||||
// relying on the rigid class which does it during movement.
|
// relying on the rigid class which does it during movement.
|
||||||
Wheel* wend = &mWheel[mDataBlock->wheelCount];
|
Wheel* wend = &mWheel[mDataBlock->wheelCount];
|
||||||
mRigid.force.set(0, 0, 0);
|
mRigid.clearForces();
|
||||||
mRigid.torque.set(0, 0, 0);
|
|
||||||
|
|
||||||
// Calculate vertical load for friction. Divide up the spring
|
// Calculate vertical load for friction. Divide up the spring
|
||||||
// forces across all the wheels that are in contact with
|
// forces across all the wheels that are in contact with
|
||||||
|
|
@ -1095,7 +1092,7 @@ void WheeledVehicle::updateForces(F32 dt)
|
||||||
mRigid.force += mAppliedForce;
|
mRigid.force += mAppliedForce;
|
||||||
|
|
||||||
// Container drag & buoyancy
|
// Container drag & buoyancy
|
||||||
mRigid.force += Point3F(0, 0, -mBuoyancy * sWheeledVehicleGravity * mRigid.mass);
|
mRigid.force += Point3F(0, 0, mRigid.mass * mNetGravity);
|
||||||
mRigid.force -= mRigid.linVelocity * mDrag;
|
mRigid.force -= mRigid.linVelocity * mDrag;
|
||||||
mRigid.torque -= mRigid.angMomentum * mDrag;
|
mRigid.torque -= mRigid.angMomentum * mDrag;
|
||||||
|
|
||||||
|
|
@ -1104,17 +1101,13 @@ void WheeledVehicle::updateForces(F32 dt)
|
||||||
if (mRigid.atRest && (mRigid.force.len() || mRigid.torque.len()))
|
if (mRigid.atRest && (mRigid.force.len() || mRigid.torque.len()))
|
||||||
mRigid.atRest = false;
|
mRigid.atRest = false;
|
||||||
|
|
||||||
// Gravity
|
|
||||||
mRigid.force += Point3F(0, 0, sWheeledVehicleGravity * mRigid.mass);
|
|
||||||
|
|
||||||
// Integrate and update velocity
|
// Integrate and update velocity
|
||||||
mRigid.linMomentum += mRigid.force * dt;
|
mRigid.linMomentum += mRigid.force * dt;
|
||||||
mRigid.angMomentum += mRigid.torque * dt;
|
mRigid.angMomentum += mRigid.torque * dt;
|
||||||
mRigid.updateVelocity();
|
mRigid.updateVelocity();
|
||||||
|
|
||||||
// Since we've already done all the work, just need to clear this out.
|
// Since we've already done all the work, just need to clear this out.
|
||||||
mRigid.force.set(0, 0, 0);
|
mRigid.clearForces();
|
||||||
mRigid.torque.set(0, 0, 0);
|
|
||||||
|
|
||||||
// If we're still atRest, make sure we're not accumulating anything
|
// If we're still atRest, make sure we're not accumulating anything
|
||||||
if (mRigid.atRest)
|
if (mRigid.atRest)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue