Updated again server setupbones to match more the client's
This commit is contained in:
parent
457fc82dc7
commit
70d7c82ff9
6 changed files with 274 additions and 66 deletions
|
@ -1308,8 +1308,8 @@ void CInput::CreateMove ( int sequence_number, float input_sample_frametime, boo
|
|||
continue;
|
||||
}
|
||||
|
||||
cmd->simulationdata[pEntity->index].m_flInterpolatedSimulationTime = pEntity->m_flInterpolatedSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].m_flSimulationTime = pEntity->m_flInterpolatedSimulationTime;
|
||||
cmd->simulationdata[pEntity->index].m_flAnimTime = pEntity->m_flSimulationTime;
|
||||
}
|
||||
|
||||
#ifdef CSTRIKE_DLL
|
||||
|
|
|
@ -1590,6 +1590,58 @@ QAngle CBaseAnimating::GetStepAngles( void ) const
|
|||
return GetLocalAngles();
|
||||
}
|
||||
|
||||
class CTraceFilterSkipNPCsAndPlayers : public CTraceFilterSimple
|
||||
{
|
||||
public:
|
||||
CTraceFilterSkipNPCsAndPlayers( const IHandleEntity *passentity, int collisionGroup )
|
||||
: CTraceFilterSimple( passentity, collisionGroup )
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask )
|
||||
{
|
||||
if ( CTraceFilterSimple::ShouldHitEntity(pServerEntity, contentsMask) )
|
||||
{
|
||||
CBaseEntity *pEntity = EntityFromEntityHandle( pServerEntity );
|
||||
if ( !pEntity )
|
||||
return true;
|
||||
|
||||
if ( pEntity->IsNPC() || pEntity->IsPlayer() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void CBaseAnimating::UpdateIKLocks( float currentTime )
|
||||
{
|
||||
if (!m_pIk)
|
||||
return;
|
||||
|
||||
int targetCount = m_pIk->m_target.Count();
|
||||
if ( targetCount == 0 )
|
||||
return;
|
||||
|
||||
for (int i = 0; i < targetCount; i++)
|
||||
{
|
||||
CIKTarget *pTarget = &m_pIk->m_target[i];
|
||||
|
||||
if (!pTarget->IsActive())
|
||||
continue;
|
||||
|
||||
if (pTarget->GetOwner() != -1)
|
||||
{
|
||||
CBaseEntity *pOwner = UTIL_EntityByIndex( pTarget->GetOwner() );
|
||||
if (pOwner != NULL)
|
||||
{
|
||||
pTarget->UpdateOwner( pOwner->entindex(), pOwner->GetAbsOrigin(), pOwner->GetAbsAngles() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Find IK collisions with world
|
||||
// Input :
|
||||
|
@ -1598,52 +1650,81 @@ QAngle CBaseAnimating::GetStepAngles( void ) const
|
|||
|
||||
void CBaseAnimating::CalculateIKLocks( float currentTime )
|
||||
{
|
||||
if ( m_pIk )
|
||||
if (!m_pIk)
|
||||
return;
|
||||
|
||||
int targetCount = m_pIk->m_target.Count();
|
||||
if ( targetCount == 0 )
|
||||
return;
|
||||
|
||||
// In TF, we might be attaching a player's view to a walking model that's using IK. If we are, it can
|
||||
// get in here during the view setup code, and it's not normally supposed to be able to access the spatial
|
||||
// partition that early in the rendering loop. So we allow access right here for that special case.
|
||||
SpatialPartitionListMask_t curSuppressed = partition->GetSuppressedLists();
|
||||
partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
|
||||
|
||||
Ray_t ray;
|
||||
CTraceFilterSkipNPCsAndPlayers traceFilter( this, GetCollisionGroup() );
|
||||
|
||||
// FIXME: trace based on gravity or trace based on angles?
|
||||
Vector up;
|
||||
AngleVectors( GetAbsAngles(), NULL, NULL, &up );
|
||||
|
||||
// FIXME: check number of slots?
|
||||
float minHeight = FLT_MAX;
|
||||
float maxHeight = -FLT_MAX;
|
||||
|
||||
for (int i = 0; i < targetCount; i++)
|
||||
{
|
||||
Ray_t ray;
|
||||
CTraceFilterSkipNPCs traceFilter( this, GetCollisionGroup() );
|
||||
Vector up;
|
||||
GetVectors( NULL, NULL, &up );
|
||||
// FIXME: check number of slots?
|
||||
for (int i = 0; i < m_pIk->m_target.Count(); i++)
|
||||
trace_t trace;
|
||||
CIKTarget *pTarget = &m_pIk->m_target[i];
|
||||
|
||||
if (!pTarget->IsActive())
|
||||
continue;
|
||||
|
||||
switch( pTarget->type)
|
||||
{
|
||||
trace_t trace;
|
||||
CIKTarget *pTarget = &m_pIk->m_target[i];
|
||||
|
||||
if (!pTarget->IsActive())
|
||||
continue;
|
||||
|
||||
switch( pTarget->type )
|
||||
case IK_GROUND:
|
||||
{
|
||||
case IK_GROUND:
|
||||
Vector estGround;
|
||||
Vector p1, p2;
|
||||
|
||||
// adjust ground to original ground position
|
||||
estGround = (pTarget->est.pos - GetAbsOrigin());
|
||||
estGround = estGround - (estGround * up) * up;
|
||||
estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up;
|
||||
|
||||
VectorMA( estGround, pTarget->est.height, up, p1 );
|
||||
VectorMA( estGround, -pTarget->est.height, up, p2 );
|
||||
|
||||
float r = MAX( pTarget->est.radius, 1);
|
||||
|
||||
// don't IK to other characters
|
||||
ray.Init( p1, p2, Vector(-r,-r,0), Vector(r,r,r*2) );
|
||||
enginetrace->TraceRay( ray, PhysicsSolidMaskForEntity(), &traceFilter, &trace );
|
||||
|
||||
if ( trace.m_pEnt != NULL && trace.m_pEnt->GetMoveType() == MOVETYPE_PUSH )
|
||||
{
|
||||
Vector estGround;
|
||||
estGround = (pTarget->est.pos - GetAbsOrigin());
|
||||
estGround = estGround - (estGround * up) * up;
|
||||
estGround = GetAbsOrigin() + estGround + pTarget->est.floor * up;
|
||||
pTarget->SetOwner( trace.m_pEnt->entindex(), trace.m_pEnt->GetAbsOrigin(), trace.m_pEnt->GetAbsAngles() );
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->ClearOwner( );
|
||||
}
|
||||
|
||||
Vector p1, p2;
|
||||
VectorMA( estGround, pTarget->est.height, up, p1 );
|
||||
VectorMA( estGround, -pTarget->est.height, up, p2 );
|
||||
if (trace.startsolid)
|
||||
{
|
||||
// trace from back towards hip
|
||||
Vector tmp = estGround - pTarget->trace.closest;
|
||||
tmp.NormalizeInPlace();
|
||||
ray.Init( estGround - tmp * pTarget->est.height, estGround, Vector(-r,-r,0), Vector(r,r,1) );
|
||||
|
||||
float r = MAX(pTarget->est.radius,1);
|
||||
// debugoverlay->AddLineOverlay( ray.m_Start, ray.m_Start + ray.m_Delta, 255, 0, 0, 0, 0 );
|
||||
|
||||
// don't IK to other characters
|
||||
ray.Init( p1, p2, Vector(-r,-r,0), Vector(r,r,1) );
|
||||
enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace );
|
||||
|
||||
/*
|
||||
debugoverlay->AddBoxOverlay( p1, Vector(-r,-r,0), Vector(r,r,1), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 1.0f );
|
||||
debugoverlay->AddBoxOverlay( trace.endpos, Vector(-r,-r,0), Vector(r,r,1), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 1.0f );
|
||||
debugoverlay->AddLineOverlay( p1, trace.endpos, 255, 0, 0, 0, 1.0f );
|
||||
*/
|
||||
|
||||
if (trace.startsolid)
|
||||
if (!trace.startsolid)
|
||||
{
|
||||
ray.Init( pTarget->trace.hip, pTarget->est.pos, Vector(-r,-r,0), Vector(r,r,1) );
|
||||
|
||||
enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace );
|
||||
|
||||
p1 = trace.endpos;
|
||||
VectorMA( p1, - pTarget->est.height, up, p2 );
|
||||
ray.Init( p1, p2, Vector(-r,-r,0), Vector(r,r,1) );
|
||||
|
@ -1651,30 +1732,154 @@ void CBaseAnimating::CalculateIKLocks( float currentTime )
|
|||
enginetrace->TraceRay( ray, MASK_SOLID, &traceFilter, &trace );
|
||||
}
|
||||
|
||||
if (!trace.startsolid)
|
||||
{
|
||||
if (trace.DidHitWorld())
|
||||
{
|
||||
pTarget->SetPosWithNormalOffset( trace.endpos, trace.plane.normal );
|
||||
pTarget->SetNormal( trace.plane.normal );
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->SetPos( trace.endpos );
|
||||
pTarget->SetAngles( GetAbsAngles() );
|
||||
}
|
||||
// debugoverlay->AddLineOverlay( ray.m_Start, ray.m_Start + ray.m_Delta, 0, 255, 0, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
if (!trace.startsolid)
|
||||
{
|
||||
if (trace.DidHitWorld())
|
||||
{
|
||||
// clamp normal to 33 degrees
|
||||
const float limit = 0.832;
|
||||
float dot = DotProduct(trace.plane.normal, up);
|
||||
if (dot < limit)
|
||||
{
|
||||
Assert( dot >= 0 );
|
||||
// subtract out up component
|
||||
Vector diff = trace.plane.normal - up * dot;
|
||||
// scale remainder such that it and the up vector are a unit vector
|
||||
float d = sqrt( (1 - limit * limit) / DotProduct( diff, diff ) );
|
||||
trace.plane.normal = up * limit + d * diff;
|
||||
}
|
||||
// FIXME: this is wrong with respect to contact position and actual ankle offset
|
||||
pTarget->SetPosWithNormalOffset( trace.endpos, trace.plane.normal );
|
||||
pTarget->SetNormal( trace.plane.normal );
|
||||
pTarget->SetOnWorld( true );
|
||||
|
||||
// only do this on forward tracking or commited IK ground rules
|
||||
if (pTarget->est.release < 0.1)
|
||||
{
|
||||
// keep track of ground height
|
||||
float offset = DotProduct( pTarget->est.pos, up );
|
||||
if (minHeight > offset )
|
||||
minHeight = offset;
|
||||
|
||||
if (maxHeight < offset )
|
||||
maxHeight = offset;
|
||||
}
|
||||
// FIXME: if we don't drop legs, running down hills looks horrible
|
||||
/*
|
||||
if (DotProduct( pTarget->est.pos, up ) < DotProduct( estGround, up ))
|
||||
{
|
||||
pTarget->est.pos = estGround;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (trace.DidHitNonWorldEntity())
|
||||
{
|
||||
pTarget->SetPos( trace.endpos );
|
||||
pTarget->SetAngles( GetAbsAngles() );
|
||||
|
||||
// only do this on forward tracking or commited IK ground rules
|
||||
if (pTarget->est.release < 0.1)
|
||||
{
|
||||
float offset = DotProduct( pTarget->est.pos, up );
|
||||
if (minHeight > offset )
|
||||
minHeight = offset;
|
||||
|
||||
if (maxHeight < offset )
|
||||
maxHeight = offset;
|
||||
}
|
||||
// FIXME: if we don't drop legs, running down hills looks horrible
|
||||
/*
|
||||
if (DotProduct( pTarget->est.pos, up ) < DotProduct( estGround, up ))
|
||||
{
|
||||
pTarget->est.pos = estGround;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->IKFailed( );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IK_ATTACHMENT:
|
||||
else
|
||||
{
|
||||
// anything on the server?
|
||||
if (!trace.DidHitWorld())
|
||||
{
|
||||
pTarget->IKFailed( );
|
||||
}
|
||||
else
|
||||
{
|
||||
pTarget->SetPos( trace.endpos );
|
||||
pTarget->SetAngles( GetAbsAngles() );
|
||||
pTarget->SetOnWorld( true );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/*
|
||||
debugoverlay->AddTextOverlay( p1, i, 0, "%d %.1f %.1f %.1f ", i,
|
||||
pTarget->latched.deltaPos.x, pTarget->latched.deltaPos.y, pTarget->latched.deltaPos.z );
|
||||
debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -r, -r, -1 ), Vector( r, r, 1), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
|
||||
*/
|
||||
// debugoverlay->AddBoxOverlay( pTarget->latched.pos, Vector( -2, -2, 2 ), Vector( 2, 2, 6), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
|
||||
}
|
||||
break;
|
||||
|
||||
case IK_ATTACHMENT:
|
||||
{
|
||||
CBaseEntity *pEntity = NULL;
|
||||
float flDist = pTarget->est.radius;
|
||||
|
||||
// FIXME: make entity finding sticky!
|
||||
// FIXME: what should the radius check be?
|
||||
for ( CEntitySphereQuery sphere( pTarget->est.pos, 64 ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
|
||||
{
|
||||
CBaseAnimating *pAnim = pEntity->GetBaseAnimating( );
|
||||
if (!pAnim)
|
||||
continue;
|
||||
|
||||
int iAttachment = pAnim->LookupAttachment( pTarget->offset.pAttachmentName );
|
||||
if (iAttachment <= 0)
|
||||
continue;
|
||||
|
||||
Vector origin;
|
||||
QAngle angles;
|
||||
pAnim->GetAttachment( iAttachment, origin, angles );
|
||||
|
||||
// debugoverlay->AddBoxOverlay( origin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 255, 0, 0, 0, 0 );
|
||||
|
||||
float d = (pTarget->est.pos - origin).Length();
|
||||
|
||||
if ( d >= flDist)
|
||||
continue;
|
||||
|
||||
flDist = d;
|
||||
pTarget->SetPos( origin );
|
||||
pTarget->SetAngles( angles );
|
||||
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 255, 0, 0, 0 );
|
||||
}
|
||||
|
||||
if (flDist >= pTarget->est.radius)
|
||||
{
|
||||
// debugoverlay->AddBoxOverlay( pTarget->est.pos, Vector( -pTarget->est.radius, -pTarget->est.radius, -pTarget->est.radius ), Vector( pTarget->est.radius, pTarget->est.radius, pTarget->est.radius), QAngle( 0, 0, 0 ), 0, 0, 255, 0, 0 );
|
||||
// no solution, disable ik rule
|
||||
pTarget->IKFailed( );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( HL2_DLL )
|
||||
if (minHeight < FLT_MAX)
|
||||
{
|
||||
input->AddIKGroundContactInfo( entindex(), minHeight, maxHeight );
|
||||
}
|
||||
#endif
|
||||
|
||||
partition->SuppressLists( curSuppressed, true );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1827,6 +2032,8 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
|||
m_pIk->Init( pStudioHdr, GetAbsAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
|
||||
UpdateIKLocks( gpGlobals->curtime );
|
||||
|
||||
m_pIk->UpdateTargets( pos, q, pBoneToWorld, boneComputed );
|
||||
CalculateIKLocks( gpGlobals->curtime );
|
||||
m_pIk->SolveDependencies( pos, q, pBoneToWorld, boneComputed );
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
|
||||
virtual void GetBoneTransform( int iBone, matrix3x4_t &pBoneToWorld );
|
||||
virtual void SetupBones( matrix3x4_t *pBoneToWorld, int boneMask );
|
||||
virtual void UpdateIKLocks( float currentTime );
|
||||
virtual void CalculateIKLocks( float currentTime );
|
||||
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity );
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
ConVar sv_unlag( "sv_unlag", "1", FCVAR_DEVELOPMENTONLY, "Enables player lag compensation" );
|
||||
ConVar sv_maxunlag( "sv_maxunlag", "1.0", FCVAR_DEVELOPMENTONLY, "Maximum lag compensation in seconds", true, 0.0f, true, 1.0f );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "1", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" );
|
||||
ConVar sv_lagflushbonecache( "sv_lagflushbonecache", "0", FCVAR_DEVELOPMENTONLY, "Flushes entity bone cache on lag compensation" );
|
||||
ConVar sv_unlag_fixstuck( "sv_unlag_fixstuck", "0", FCVAR_DEVELOPMENTONLY, "Disallow backtracking a player for lag compensation if it will cause them to become stuck" );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -398,8 +398,8 @@ void CLagCompensationManager::BacktrackPlayer( CBasePlayer *pPlayer, CUserCmd *c
|
|||
VPROF_BUDGET( "BacktrackPlayer", "CLagCompensationManager" );
|
||||
int pl_index = pPlayer->entindex() - 1;
|
||||
|
||||
float flTargetSimulationTime = cmd->simulationdata[pl_index + 1].m_flInterpolatedSimulationTime;
|
||||
float flTargetSimulatedAnimationTime = cmd->simulationdata[pl_index + 1].m_flSimulationTime;
|
||||
float flTargetSimulationTime = cmd->simulationdata[pl_index + 1].m_flSimulationTime;
|
||||
float flTargetSimulatedAnimationTime = cmd->simulationdata[pl_index + 1].m_flAnimTime;
|
||||
|
||||
// get track history of this player
|
||||
CUtlFixedLinkedList< LagRecord > *trackSim = &m_PlayerTrack[ pl_index ];
|
||||
|
|
|
@ -194,21 +194,21 @@ void WriteUsercmd( bf_write *buf, const CUserCmd *to, const CUserCmd *from )
|
|||
// Write finally simulation data with entity index
|
||||
for (unsigned int i = 0; i <= highestEntityIndex; i++)
|
||||
{
|
||||
if (from->simulationdata[i].m_flInterpolatedSimulationTime
|
||||
!= to->simulationdata[i].m_flInterpolatedSimulationTime)
|
||||
if (from->simulationdata[i].m_flSimulationTime
|
||||
!= to->simulationdata[i].m_flSimulationTime)
|
||||
{
|
||||
buf->WriteOneBit(1);
|
||||
buf->WriteBitFloat(to->simulationdata[i].m_flInterpolatedSimulationTime);
|
||||
buf->WriteBitFloat(to->simulationdata[i].m_flSimulationTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf->WriteOneBit(0);
|
||||
}
|
||||
|
||||
if (from->simulationdata[i].m_flSimulationTime != to->simulationdata[i].m_flSimulationTime)
|
||||
if (from->simulationdata[i].m_flAnimTime != to->simulationdata[i].m_flAnimTime)
|
||||
{
|
||||
buf->WriteOneBit(1);
|
||||
buf->WriteBitFloat(to->simulationdata[i].m_flSimulationTime);
|
||||
buf->WriteBitFloat(to->simulationdata[i].m_flAnimTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -351,12 +351,12 @@ void ReadUsercmd( bf_read *buf, CUserCmd *move, CUserCmd *from )
|
|||
{
|
||||
if (buf->ReadOneBit())
|
||||
{
|
||||
move->simulationdata[i].m_flInterpolatedSimulationTime = buf->ReadBitFloat();
|
||||
move->simulationdata[i].m_flSimulationTime = buf->ReadBitFloat();
|
||||
}
|
||||
|
||||
if (buf->ReadOneBit())
|
||||
{
|
||||
move->simulationdata[i].m_flSimulationTime = buf->ReadBitFloat();
|
||||
move->simulationdata[i].m_flAnimTime = buf->ReadBitFloat();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ struct SimulationData
|
|||
// TODO_ENHANCED:
|
||||
// For now we send the last received update for animations.
|
||||
// anim time is unreliable on low fps.
|
||||
float m_flInterpolatedSimulationTime;
|
||||
float m_flSimulationTime;
|
||||
float m_flSimulationTime;
|
||||
float m_flAnimTime;
|
||||
};
|
||||
|
||||
class CEntityGroundContact
|
||||
|
|
Loading…
Reference in a new issue