virtual void BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed ) { VPROF_BUDGET( "C_ServerRagdollAttached::SetupBones", VPROF_BUDGETGROUP_CLIENT_ANIMATION ); if ( !hdr ) return; float frac = RemapVal( gpGlobals->curtime, m_parentTime, m_parentTime+ATTACH_INTERP_TIME, 0, 1 ); frac = clamp( frac, 0.f, 1.f ); // interpolate offset over some time Vector offset = m_vecOffset * (1-frac); C_BaseAnimating *parent = assert_cast< C_BaseAnimating* >( GetMoveParent() ); Vector worldOrigin; worldOrigin.Init(); if ( parent ) { Assert( parent != this ); parent->SetupBones( NULL, -1, BONE_USED_BY_ANYTHING, gpGlobals->curtime ); matrix3x4_t boneToWorld; parent->GetCachedBoneMatrix( m_boneIndexAttached, boneToWorld ); VectorTransform( m_attachmentPointBoneSpace, boneToWorld, worldOrigin ); } BaseClass::BuildTransformations( hdr, pos, q, cameraTransform, boneMask, boneComputed ); if ( parent ) { int index = m_boneIndex[m_ragdollAttachedObjectIndex]; const matrix3x4_t &matrix = GetBone( index ); Vector ragOrigin; VectorTransform( m_attachmentPointRagdollSpace, matrix, ragOrigin ); offset = worldOrigin - ragOrigin; // fixes culling SetAbsOrigin( worldOrigin ); m_vecOffset = offset; } for ( int i = 0; i < hdr->numbones(); i++ ) { if ( !( hdr->boneFlags( i ) & boneMask ) ) continue; Vector pos; matrix3x4_t &matrix = GetBoneForWrite( i ); MatrixGetColumn( matrix, 3, pos ); pos += offset; MatrixSetColumn( pos, 3, matrix ); } }
//----------------------------------------------------------------------------- // Purpose: We need to slam our position! //----------------------------------------------------------------------------- void C_NPC_Puppet::BuildTransformations( CStudioHdr *pStudioHdr, Vector *pos, Quaternion q[], const matrix3x4_t& cameraTransform, int boneMask, CBoneBitList &boneComputed ) { if ( m_hAnimationTarget && m_nTargetAttachment != -1 ) { C_BaseAnimating *pTarget = m_hAnimationTarget->GetBaseAnimating(); if ( pTarget ) { matrix3x4_t matTarget; pTarget->GetAttachment( m_nTargetAttachment, matTarget ); MatrixCopy( matTarget, GetBoneForWrite( 0 ) ); boneComputed.ClearAll(); // FIXME: Why is this calculated already? boneComputed.MarkBone( 0 ); } } // Call the baseclass BaseClass::BuildTransformations( pStudioHdr, pos, q, cameraTransform, boneMask, boneComputed ); }
void C_ServerRagdoll::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion q[], const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed ) { if ( !hdr ) return; matrix3x4_t bonematrix; bool boneSimulated[MAXSTUDIOBONES]; // no bones have been simulated memset( boneSimulated, 0, sizeof(boneSimulated) ); mstudiobone_t *pbones = hdr->pBone( 0 ); mstudioseqdesc_t *pSeqDesc = NULL; if ( m_nOverlaySequence >= 0 && m_nOverlaySequence < hdr->GetNumSeq() ) { pSeqDesc = &hdr->pSeqdesc( m_nOverlaySequence ); } int i; for ( i = 0; i < m_elementCount; i++ ) { int index = m_boneIndex[i]; if ( index >= 0 ) { if ( hdr->boneFlags(index) & boneMask ) { boneSimulated[index] = true; matrix3x4_t &matrix = GetBoneForWrite( index ); if ( m_flBlendWeightCurrent != 0.0f && pSeqDesc && // FIXME: this bone access is illegal pSeqDesc->weight( index ) != 0.0f ) { // Use the animated bone position instead boneSimulated[index] = false; } else { AngleMatrix( m_ragAngles[i], m_ragPos[i], matrix ); } } } } for ( i = 0; i < hdr->numbones(); i++ ) { if ( !( hdr->boneFlags( i ) & boneMask ) ) continue; // BUGBUG: Merge this code with the code in c_baseanimating somehow!!! // animate all non-simulated bones if ( boneSimulated[i] || CalcProceduralBone( hdr, i, m_BoneAccessor ) ) { continue; } else { QuaternionMatrix( q[i], pos[i], bonematrix ); if (pbones[i].parent == -1) { ConcatTransforms( cameraTransform, bonematrix, GetBoneForWrite( i ) ); } else { ConcatTransforms( GetBone( pbones[i].parent ), bonematrix, GetBoneForWrite( i ) ); } } if ( pbones[i].parent == -1 ) { // Apply client-side effects to the transformation matrix // ApplyBoneMatrixTransform( GetBoneForWrite( i ) ); } } }
void C_GStringPlayerRagdoll::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quaternion *q, const matrix3x4_t &cameraTransform, int boneMask, CBoneBitList &boneComputed ) { if ( !hdr ) return; matrix3x4_t bonematrix; bool boneSimulated[MAXSTUDIOBONES]; // no bones have been simulated memset( boneSimulated, 0, sizeof(boneSimulated) ); mstudiobone_t *pbones = hdr->pBone( 0 ); if ( m_pRagdoll ) { // simulate bones and update flags int oldWritableBones = m_BoneAccessor.GetWritableBones(); int oldReadableBones = m_BoneAccessor.GetReadableBones(); m_BoneAccessor.SetWritableBones( BONE_USED_BY_ANYTHING ); m_BoneAccessor.SetReadableBones( BONE_USED_BY_ANYTHING ); #if defined( REPLAY_ENABLED ) // If we're playing back a demo, override the ragdoll bones with cached version if available - otherwise, simulate. if ( ( !engine->IsPlayingDemo() && !engine->IsPlayingTimeDemo() ) || !CReplayRagdollCache::Instance().IsInitialized() || !CReplayRagdollCache::Instance().GetFrame( this, engine->GetDemoPlaybackTick(), boneSimulated, &m_BoneAccessor ) ) #endif { m_pRagdoll->RagdollBone( this, pbones, hdr->numbones(), boneSimulated, m_BoneAccessor ); } m_BoneAccessor.SetWritableBones( oldWritableBones ); m_BoneAccessor.SetReadableBones( oldReadableBones ); } // For EF_BONEMERGE entities, copy the bone matrices for any bones that have matching names. bool boneMerge = IsEffectActive(EF_BONEMERGE); if ( boneMerge || m_pBoneMergeCache ) { if ( boneMerge ) { if ( !m_pBoneMergeCache ) { m_pBoneMergeCache = new CBoneMergeCache; m_pBoneMergeCache->Init( this ); } m_pBoneMergeCache->MergeMatchingBones( boneMask ); } else { delete m_pBoneMergeCache; m_pBoneMergeCache = NULL; } } for (int i = 0; i < hdr->numbones(); i++) { if ( i == m_iBoneHead ) { MatrixScaleBy( 0.01f, GetBoneForWrite( i ) ); } // Only update bones reference by the bone mask. if ( !( hdr->boneFlags( i ) & boneMask ) ) { continue; } if ( m_pBoneMergeCache && m_pBoneMergeCache->IsBoneMerged( i ) ) continue; // animate all non-simulated bones if ( boneSimulated[i] || CalcProceduralBone( hdr, i, m_BoneAccessor )) { continue; } // skip bones that the IK has already setup else if (boneComputed.IsBoneMarked( i )) { // dummy operation, just used to verify in debug that this should have happened GetBoneForWrite( i ); } else { QuaternionMatrix( q[i], pos[i], bonematrix ); Assert( fabs( pos[i].x ) < 100000 ); Assert( fabs( pos[i].y ) < 100000 ); Assert( fabs( pos[i].z ) < 100000 ); if ( (hdr->boneFlags( i ) & BONE_ALWAYS_PROCEDURAL) && (hdr->pBone( i )->proctype & STUDIO_PROC_JIGGLE) ) { // // Physics-based "jiggle" bone // Bone is assumed to be along the Z axis // Pitch around X, yaw around Y // // compute desired bone orientation matrix3x4_t goalMX; if (pbones[i].parent == -1) { ConcatTransforms( cameraTransform, bonematrix, goalMX ); } else { ConcatTransforms( GetBone( pbones[i].parent ), bonematrix, goalMX ); } // get jiggle properties from QC data mstudiojigglebone_t *jiggleInfo = (mstudiojigglebone_t *)pbones[i].pProcedure( ); if (!m_pJiggleBones) { m_pJiggleBones = new CJiggleBones; } // do jiggle physics m_pJiggleBones->BuildJiggleTransformations( i, gpGlobals->realtime, jiggleInfo, goalMX, GetBoneForWrite( i ) ); } else if (hdr->boneParent(i) == -1) { ConcatTransforms( cameraTransform, bonematrix, GetBoneForWrite( i ) ); } else { ConcatTransforms( GetBone( hdr->boneParent(i) ), bonematrix, GetBoneForWrite( i ) ); } } } }