[T3D1.0 BUG] Player (ground) Impact
by Davide Archetti · in Torque 3D Professional · 10/07/2009 (6:55 am) · 3 replies
Well, I was trying to see the shake camera effect when the player impact on the ground, but this doesn't work, no matter how you set the values of groundImpactMinSpeed.
I've discovered that that function _handleCollision, that take care of the ground impact, is called inside the updatePos function, just after the _move function is called (note: I'm using standard torque collision not the physic player).
But, _handleCollision use the class variable mVelocity to compute the impact speed, but the same variable is changed inside the _move function just after a collision is detected, so when it exit the _move function its value has been decresed to the after collision speed, so the _handleCollision never see the collision happens.
I have fixed this problem, by returning from the _move function the speed just before the collision and pass this speed to the _handleCollision function, so, the new updatePos function is
the _move function
And the new _handleCollision
I've discovered that that function _handleCollision, that take care of the ground impact, is called inside the updatePos function, just after the _move function is called (note: I'm using standard torque collision not the physic player).
But, _handleCollision use the class variable mVelocity to compute the impact speed, but the same variable is changed inside the _move function just after a collision is detected, so when it exit the _move function its value has been decresed to the after collision speed, so the _handleCollision never see the collision happens.
I have fixed this problem, by returning from the _move function the speed just before the collision and pass this speed to the _handleCollision function, so, the new updatePos function is
bool Player::updatePos(const F32 travelTime)
{
PROFILE_SCOPE(Player_UpdatePos);
getTransform().getColumn(3,&delta.posVec);
// When mounted to another object, only Z rotation used.
if (isMounted()) {
mVelocity = mMount.object->getVelocity();
setPosition(Point3F(0.0f, 0.0f, 0.0f), mRot);
setMaskBits(MoveMask);
return true;
}
Point3F newPos;
Point3F colVel = mVelocity; //This is the velocity returned from _move just before the collision happen
Collision col;
dMemset( &col, 0, sizeof( col ) );
// DEBUG:
//Point3F savedVelocity = mVelocity;
// This avoids unnecessary work, but also avoids problems with
// the physicsPlayer jitters while stationary.
if ( mVelocity.isZero() )
newPos = delta.posVec;
else
{
if ( mPhysicsPlayer )
{
newPos = mPhysicsPlayer->move( mVelocity * travelTime, &col );
mVelocity = ( newPos - delta.posVec ) / travelTime;
}
else
newPos = _move( travelTime, &col, colVel );
// DEBUG:
//if ( isClientObject() )
// Con::printf( "(client) vel: %g %g %g colObj:%x", mVelocity.x, mVelocity.y, mVelocity.z, col.object );
//else
// Con::printf( "(server) vel: %g %g %g colObj:%x", mVelocity.x, mVelocity.y, mVelocity.z, col.object );
}
_handleCollision( col, colVel );
// Set new position
// If on the client, calc delta for backstepping
if (isClientObject())
{
delta.pos = newPos;
delta.posVec = delta.posVec - delta.pos;
delta.dt = 1.0f;
}
...the _move function
Point3F Player::_move( const F32 travelTime, Collision *outCol, Point3F& colVel )
{
// Try and move to new pos
F32 totalMotion = 0.0f;
// TODO: not used?
//F32 initialSpeed = mVelocity.len();
Point3F start;
....
// Copy this collision out so
// we can use it to do impacts
// and query collision.
*outCol = *collision;
colVel = mVelocity;
F32 bd = -mDot( mVelocity, collision->normal );
....And the new _handleCollision
void Player::_handleCollision( const Collision &collision, const Point3F& colVel )
{
//F32 bd = -mDot( mVelocity, collision.normal );
F32 bd = -mDot( colVel, collision.normal);
// shake camera on ground impact
if( bd > mDataBlock->groundImpactMinSpeed && isControlObject() )
{
F32 ampScale = (bd - mDataBlock->groundImpactMinSpeed) / mDataBlock->minImpactSpeed;
CameraShake *groundImpactShake = new CameraShake;
groundImpactShake->setDuration( mDataBlock->groundImpactShakeDuration );
groundImpactShake->setFrequency( mDataBlock->groundImpactShakeFreq );
VectorF shakeAmp = mDataBlock->groundImpactShakeAmp * ampScale;
groundImpactShake->setAmplitude( shakeAmp );
groundImpactShake->setFalloff( mDataBlock->groundImpactShakeFalloff );
groundImpactShake->init();
gCamFXMgr.addFX( groundImpactShake );
}
if ( bd > mDataBlock->minImpactSpeed && !mMountPending )
{
if ( !isGhost() )
onImpact( collision.object, collision.normal * bd );
if (mDamageState == Enabled && mState != RecoverState)
{
// Scale how long we're down for
F32 value = (bd - mDataBlock->minImpactSpeed);
F32 range = (mDataBlock->minImpactSpeed * 0.9f);
U32 recover = mDataBlock->recoverDelay;
if (value < range)
recover = 1 + S32(mFloor( F32(recover) * value / range) );
//Con::printf("Used %d recover ticks", recover);
//Con::printf(" minImpact = %g, this one = %g", mDataBlock->minImpactSpeed, bd);
setState(RecoverState, recover);
}
}
if ( isServerObject() && bd > (mDataBlock->minImpactSpeed / 3.0f) )
{
setMaskBits(ImpactMask);
}
// Track collisions
if ( !isGhost() &&
collision.object &&
collision.object != mContactInfo.contactObject )
queueCollision( collision.object, /*mVelocity*/ colVel - collision.object->getVelocity() );
}
Full Sail QA&U Lab Intern