void DrawBones( matrix3x4_t const* pBones, int nNumBones, ragdoll_t const* pRagdoll, int nRed, int nGreen, int nBlue, C_BaseAnimating* pBaseAnimating ) { Assert( pBones ); Assert( pRagdoll ); Assert( pBaseAnimating ); Vector from, to; for ( int i = 0; i < nNumBones; ++i ) { // debugoverlay->AddCoordFrameOverlay( pBones[ i ], 3.0f ); int const iRagdollParentIndex = pRagdoll->list[ i ].parentIndex; if ( iRagdollParentIndex < 0 ) continue; int iBoneIndex = pRagdoll->boneIndex[ i ]; int iParentIndex = pRagdoll->boneIndex[ iRagdollParentIndex ]; MatrixPosition( pBones[ iParentIndex ], from ); MatrixPosition( pBones[ iBoneIndex ], to ); debugoverlay->AddLineOverlay( from, to, nRed, nGreen, nBlue, true, 0.0f ); } }
void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld ) { Vector vecOrigin; MatrixPosition( attachmentToWorld, vecOrigin ); ::FormatViewModelAttachment( vecOrigin, false ); PositionMatrix( vecOrigin, attachmentToWorld ); }
void C_BaseViewModel::FormatViewModelAttachment( int nAttachment, matrix3x4_t &attachmentToWorld ) { C_BasePlayer *pPlayer = ToBasePlayer( GetOwner() ); Vector vecOrigin; MatrixPosition( attachmentToWorld, vecOrigin ); ::FormatViewModelAttachment( pPlayer, vecOrigin, false ); PositionMatrix( vecOrigin, attachmentToWorld ); }
bool CAnimating::GetAttachment( int iAttachment, Vector &absOrigin, Vector *forward, Vector *right, Vector *up ) { matrix3x4_t attachmentToWorld; bool bRet = GetAttachment( iAttachment, attachmentToWorld ); MatrixPosition( attachmentToWorld, absOrigin ); if (forward) { MatrixGetColumn( attachmentToWorld, 0, forward ); } if (right) { MatrixGetColumn( attachmentToWorld, 1, right ); } if (up) { MatrixGetColumn( attachmentToWorld, 2, up ); } return bRet; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ) { ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint]; if ( !pPoint->hEntity.Get() ) { if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing ) { pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset ); pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset ); } pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL ); return; } // Only update non-follow particles when we're initializing, // unless we're parented to something, in which case we should always update if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) ) return; if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN ) return; Vector vecOrigin, vecForward, vecRight, vecUp; float flOffset = 0.0f; bool bUsingHeadOrigin = false; #ifdef TF_CLIENT_DLL CBaseEntity *pWearable = (CBaseEntity*) pPoint->hEntity.Get(); if ( pWearable && dynamic_cast<IHasAttributes*>( pWearable ) && !pWearable->IsPlayer() ) { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); if ( pAnimating ) { int bUseHeadOrigin = 0; CALL_ATTRIB_HOOK_INT_ON_OTHER( pPoint->hEntity.Get(), bUseHeadOrigin, particle_effect_use_head_origin ); if ( bUseHeadOrigin > 0 ) { int iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "bip_head" ); if ( iBone < 0 ) { iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "prp_helmet" ); if ( iBone < 0 ) { iBone = Studio_BoneIndexByName( pAnimating->GetModelPtr(), "prp_hat" ); } } if ( iBone >= 0 ) { bUsingHeadOrigin = true; const matrix3x4_t headBone = pAnimating->GetBone( iBone ); MatrixVectors( headBone, &vecForward, &vecRight, &vecUp ); MatrixPosition( headBone, vecOrigin ); CALL_ATTRIB_HOOK_FLOAT_ON_OTHER( pPoint->hEntity.Get(), flOffset, particle_effect_vertical_offset ); } } } } #endif if ( !bUsingHeadOrigin ) { switch ( pPoint->iAttachType ) { case PATTACH_POINT: case PATTACH_POINT_FOLLOW: { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); Assert( pAnimating ); if ( pAnimating ) { matrix3x4_t attachmentToWorld; if ( !pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) { // try C_BaseAnimating if attach point is not on the weapon if ( !pAnimating->C_BaseAnimating::GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) { Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() ); attachmentToWorld = pAnimating->RenderableToWorldTransform(); } } VMatrix vMat(attachmentToWorld); MatrixTranslate( vMat, pPoint->vecOriginOffset ); MatrixVectors( vMat.As3x4(), &vecForward, &vecRight, &vecUp ); MatrixPosition( vMat.As3x4(), vecOrigin ); if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) { FormatViewModelAttachment( vecOrigin, true ); } } } break; case PATTACH_ABSORIGIN: case PATTACH_ABSORIGIN_FOLLOW: default: { vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp ); } break; case PATTACH_ROOTBONE_FOLLOW: { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); Assert( pAnimating ); if ( pAnimating ) { matrix3x4_t rootBone; if ( pAnimating->GetRootBone( rootBone ) ) { MatrixVectors( rootBone, &vecForward, &vecRight, &vecUp ); MatrixPosition( rootBone, vecOrigin ); } } } break; } } Vector vecForcedOriginOffset( 0, 0, flOffset ); pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp ); pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin + vecForcedOriginOffset ); pEffect->pParticleEffect->SetSortOrigin( vecOrigin + vecForcedOriginOffset); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ) { ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint]; if ( !pPoint->hEntity.Get() ) { if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing ) { pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset ); pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset ); } pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL ); return; } // Only update non-follow particles when we're initializing, // unless we're parented to something, in which case we should always update if ( !bInitializing && !pPoint->hEntity->GetMoveParent() && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) ) return; if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN ) return; Vector vecOrigin, vecForward, vecRight, vecUp; switch ( pPoint->iAttachType ) { case PATTACH_POINT: case PATTACH_POINT_FOLLOW: { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); Assert( pAnimating ); if ( pAnimating ) { matrix3x4_t attachmentToWorld; pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ); MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp ); MatrixPosition( attachmentToWorld, vecOrigin ); if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) { FormatViewModelAttachment( vecOrigin, true ); } } } break; case PATTACH_ABSORIGIN: case PATTACH_ABSORIGIN_FOLLOW: default: { vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp ); } break; } pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp ); pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin ); pEffect->pParticleEffect->SetSortOrigin( vecOrigin ); }
inline void MatrixAngles(const matrix3x4 &matrix, Angle &angles, Vector &vec) { MatrixAngles(matrix, angles); MatrixPosition(matrix, vec); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int iPoint, bool bInitializing ) { ParticleControlPoint_t *pPoint = &pEffect->pControlPoints[iPoint]; if ( pEffect->pParticleEffect->m_pDef->IsScreenSpaceEffect() && iPoint == 0 ) { pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vec3_origin ); return; } if ( !pPoint->hEntity.Get() ) { if ( pPoint->iAttachType == PATTACH_WORLDORIGIN && bInitializing ) { pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, Vector(1,0,0), Vector(0,1,0), Vector(0,0,1) ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, pPoint->vecOriginOffset ); pEffect->pParticleEffect->SetSortOrigin( pPoint->vecOriginOffset ); } pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, NULL ); return; } // Only update non-follow particles when we're initializing, if ( !bInitializing && (pPoint->iAttachType == PATTACH_ABSORIGIN || pPoint->iAttachType == PATTACH_POINT ) ) return; if ( pPoint->iAttachType == PATTACH_CUSTOMORIGIN ) return; Vector vecOrigin, vecForward, vecRight, vecUp; switch ( pPoint->iAttachType ) { case PATTACH_POINT: case PATTACH_POINT_FOLLOW: { C_BaseAnimating *pAnimating = pPoint->hEntity->GetBaseAnimating(); bool bValid = false; Assert( pAnimating ); if ( pAnimating ) { matrix3x4_t attachmentToWorld; if ( pAnimating->IsViewModel() ) { C_BasePlayer *pPlayer = ToBasePlayer( ((C_BaseViewModel *)pAnimating)->GetOwner() ); ACTIVE_SPLITSCREEN_PLAYER_GUARD( C_BasePlayer::GetSplitScreenSlotForPlayer( pPlayer ) ); if ( pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) { bValid = true; MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp ); MatrixPosition( attachmentToWorld, vecOrigin ); if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) { FormatViewModelAttachment( pPlayer, vecOrigin, true ); } } } else { // HACK_GETLOCALPLAYER_GUARD( "CParticleProperty::UpdateControlPoint" ); if ( pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) ) { bValid = true; MatrixVectors( attachmentToWorld, &vecForward, &vecRight, &vecUp ); #ifdef _DEBUG float flTests[3] = {vecForward.Dot( vecRight ), vecRight.Dot( vecUp ), vecUp.Dot( vecForward )}; static float s_flMaxTest = 0.001f; Assert( fabs( flTests[0] ) + fabs( flTests[1] ) + fabs( flTests[2] ) < s_flMaxTest ); #endif MatrixPosition( attachmentToWorld, vecOrigin ); if ( pEffect->pParticleEffect->m_pDef->IsViewModelEffect() ) { HACK_GETLOCALPLAYER_GUARD( "CParticleProperty::UpdateControlPoint" ); FormatViewModelAttachment( NULL, vecOrigin, true ); } } } } if ( !bValid ) { static bool bWarned = false; if ( !bWarned ) { bWarned = true; DevWarning( "Attempted to attach particle effect %s to an unknown attachment on entity %s\n", pEffect->pParticleEffect->m_pDef->GetName(), pAnimating->GetClassname() ); } } if ( !bValid ) { AssertOnce( 0 ); return; } } break; case PATTACH_ABSORIGIN: case PATTACH_ABSORIGIN_FOLLOW: default: { vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; pPoint->hEntity->GetVectors( &vecForward, &vecRight, &vecUp ); } break; case PATTACH_EYES_FOLLOW: { C_BaseEntity *pEnt = pPoint->hEntity; if ( !pEnt->IsPlayer() ) return; C_BasePlayer *pPlayer = assert_cast< C_BasePlayer* >( pEnt ); bool bValid = false; Assert( pPlayer ); if ( pPlayer ) { bValid = true; vecOrigin = pPlayer->EyePosition() + pPoint->vecOriginOffset; pPlayer->EyeVectors( &vecForward, &vecRight, &vecUp ); } if ( !bValid ) { AssertOnce( 0 ); return; } } break; case PATTACH_CUSTOMORIGIN_FOLLOW: { matrix3x4_t mat; MatrixMultiply( pPoint->hEntity->RenderableToWorldTransform(), pPoint->matOffset, mat ); MatrixVectors( mat, &vecForward, &vecRight, &vecUp ); vecOrigin = pPoint->hEntity->GetAbsOrigin() + pPoint->vecOriginOffset; } break; } pEffect->pParticleEffect->SetControlPointOrientation( pPoint->iControlPoint, vecForward, vecRight, vecUp ); pEffect->pParticleEffect->SetControlPointEntity( pPoint->iControlPoint, pPoint->hEntity ); pEffect->pParticleEffect->SetControlPoint( pPoint->iControlPoint, vecOrigin ); pEffect->pParticleEffect->SetSortOrigin( vecOrigin ); }