void CRagdollProp::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) { matrix3x4_t startMatrixInv; matrix3x4_t startMatrix; m_ragdoll.list[0].pObject->GetPositionMatrix( startMatrix ); MatrixInvert( startMatrix, startMatrixInv ); // object 0 MUST be the one to get teleported! VPhysicsSwapObject( m_ragdoll.list[0].pObject ); BaseClass::Teleport( newPosition, newAngles, newVelocity ); // Calculate the relative transform of the teleport matrix3x4_t xform; ConcatTransforms( EntityToWorldTransform(), startMatrixInv, xform ); UpdateNetworkDataFromVPhysics( m_ragdoll.list[0].pObject, 0 ); for ( int i = 1; i < m_ragdoll.listCount; i++ ) { matrix3x4_t matrix, newMatrix; m_ragdoll.list[i].pObject->GetPositionMatrix( matrix ); ConcatTransforms( xform, matrix, newMatrix ); m_ragdoll.list[i].pObject->SetPositionMatrix( newMatrix, true ); UpdateNetworkDataFromVPhysics( m_ragdoll.list[i].pObject, i ); } }
void C_BaseViewModel::ApplyBoneMatrixTransform( matrix3x4_t& transform ) { if ( ShouldFlipViewModel() ) { matrix3x4_t viewMatrix, viewMatrixInverse; // We could get MATERIAL_VIEW here, but this is called sometimes before the renderer // has set that matrix. Luckily, this is called AFTER the CViewSetup has been initialized. const CViewSetup *pSetup = view->GetPlayerViewSetup(); AngleMatrix( pSetup->angles, pSetup->origin, viewMatrixInverse ); MatrixInvert( viewMatrixInverse, viewMatrix ); // Transform into view space. matrix3x4_t temp, temp2; ConcatTransforms( viewMatrix, transform, temp ); // Flip it along X. // (This is the slower way to do it, and it equates to negating the top row). //matrix3x4_t mScale; //SetIdentityMatrix( mScale ); //mScale[0][0] = 1; //mScale[1][1] = -1; //mScale[2][2] = 1; //ConcatTransforms( mScale, temp, temp2 ); temp[1][0] = -temp[1][0]; temp[1][1] = -temp[1][1]; temp[1][2] = -temp[1][2]; temp[1][3] = -temp[1][3]; // Transform back out of view space. ConcatTransforms( viewMatrixInverse, temp, transform ); } }
void CRagdollPropAttached::InitRagdollAttached( IPhysicsObject *pAttached, const Vector &forceVector, int forceBone, matrix3x4_t *pPrevBones, matrix3x4_t *pBoneToWorld, float dt, int collisionGroup, CBaseAnimating *pFollow, int boneIndexRoot, const Vector &boneLocalOrigin, int parentBoneAttach, const Vector &worldAttachOrigin ) { int ragdollAttachedIndex = 0; if ( parentBoneAttach > 0 ) { studiohdr_t *pStudioHdr = GetModelPtr(); mstudiobone_t *pBone = pStudioHdr->pBone( parentBoneAttach ); ragdollAttachedIndex = pBone->physicsbone; } InitRagdoll( forceVector, forceBone, vec3_origin, pPrevBones, pBoneToWorld, dt, collisionGroup, false ); IPhysicsObject *pRefObject = m_ragdoll.list[ragdollAttachedIndex].pObject; Vector attachmentPointRagdollSpace; pRefObject->WorldToLocal( attachmentPointRagdollSpace, worldAttachOrigin ); constraint_ragdollparams_t constraint; constraint.Defaults(); matrix3x4_t tmp, worldToAttached, worldToReference, constraintToWorld; Vector offsetWS; pAttached->LocalToWorld( offsetWS, boneLocalOrigin ); AngleMatrix( QAngle(0, pFollow->GetAbsAngles().y, 0 ), offsetWS, constraintToWorld ); constraint.axes[0].SetAxisFriction( -2, 2, 20 ); constraint.axes[1].SetAxisFriction( 0, 0, 0 ); constraint.axes[2].SetAxisFriction( -15, 15, 20 ); pAttached->GetPositionMatrix( tmp ); MatrixInvert( tmp, worldToAttached ); pRefObject->GetPositionMatrix( tmp ); MatrixInvert( tmp, worldToReference ); ConcatTransforms( worldToReference, constraintToWorld, constraint.constraintToReference ); ConcatTransforms( worldToAttached, constraintToWorld, constraint.constraintToAttached ); // for now, just slam this to be the passed in value MatrixSetColumn( attachmentPointRagdollSpace, 3, constraint.constraintToReference ); DisableCollisions( pAttached ); m_pAttachConstraint = physenv->CreateRagdollConstraint( pRefObject, pAttached, m_ragdoll.pGroup, constraint ); FollowEntity( pFollow ); SetOwnerEntity( pFollow ); RagdollActivate( m_ragdoll ); Relink(); m_boneIndexAttached = boneIndexRoot; m_ragdollAttachedObjectIndex = ragdollAttachedIndex; m_attachmentPointBoneSpace = boneLocalOrigin; Vector vTemp; MatrixGetColumn( constraint.constraintToReference, 3, vTemp ); m_attachmentPointRagdollSpace = vTemp; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPropServerVehicleManhack::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV ) { Assert( nRole == VEHICLE_ROLE_DRIVER ); CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); Assert( pPlayer );//*/ //commented out because this really should be setting the manhack angle, not the vehicle angle *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. //*pAbsOrigin = pPlayer->EyePosition(); CNPC_Manhack *pManhack=NULL; if (GetManhack()) pManhack=GetManhack()->GetManhack(); if (pManhack != NULL) { Vector m_vecManhackEye = GetManhack()->GetManhackEyePosition(); //pManhack->GetManhackView(); QAngle m_angManhackEye = pManhack->GetAbsAngles(); matrix3x4_t vehicleEyePosToWorld; AngleMatrix( m_angManhackEye, vehicleEyePosToWorld ); // Dampen the eye positional change as we drive around. //*pAbsAngles = pPlayer->EyeAngles(); CPropVehicleManhack *pDriveable = assert_cast<CPropVehicleManhack*>(GetDrivableVehicle()); if (pDriveable) pDriveable->DampenEyePosition( m_vecManhackEye, m_angManhackEye ); // Compute the relative rotation between the unperturbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); AngleMatrix( m_angManhackEye, m_vecManhackEye, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perturbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); } else DevMsg("fail\n"); }
void CAPC2FourWheelServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles ) { //FixMe, wtf? #ifndef DEBUG Assert( nRole == VEHICLE_DRIVER ); #endif CBaseCombatCharacter *pPlayer = GetPassenger( VEHICLE_ROLE_DRIVER ); Assert( pPlayer ); float flPitchFactor=1.0; *pAbsAngles = pPlayer->EyeAngles(); matrix3x4_t vehicleEyePosToWorld; Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; GetAPC()->GetAttachment( "cannon_muzzle", vehicleEyeOrigin, vehicleEyeAngles ); Vector up,forward; GetAPC()->GetVectors(NULL,&forward,&up); vehicleEyeOrigin+=(forward*37)+(up*35); AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); //#ifdef HL2_DLL // // View dampening. // if ( r_VehicleViewDampen.GetInt() ) // { // GetAPC()->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); // } //#endif // Compute the relative rotation between the unperterbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); // Now perterb the attachment point vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perterbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); }
//----------------------------------------------------------------------------- // Apply movement //----------------------------------------------------------------------------- void CLogicMeasureMovement::MeasureThink( ) { // FIXME: This is a hack to make measuring !player simpler. The player isn't // created at Activate time, so m_hMeasureTarget may be NULL because of that. if ( !m_hMeasureTarget.Get() && !Q_strnicmp( STRING(m_strMeasureTarget), "!player", 8 ) ) { SetMeasureTarget( STRING(m_strMeasureTarget) ); } // Make sure all entities are valid if ( m_hMeasureTarget.Get() && m_hMeasureReference.Get() && m_hTarget.Get() && m_hTargetReference.Get() ) { matrix3x4_t matRefToMeasure, matWorldToMeasure; switch( m_nMeasureType ) { case MEASURE_POSITION: MatrixInvert( m_hMeasureTarget->EntityToWorldTransform(), matWorldToMeasure ); break; case MEASURE_EYE_POSITION: AngleIMatrix( m_hMeasureTarget->EyeAngles(), m_hMeasureTarget->EyePosition(), matWorldToMeasure ); break; // FIXME: Could add attachment point measurement here easily } ConcatTransforms( matWorldToMeasure, m_hMeasureReference->EntityToWorldTransform(), matRefToMeasure ); // Apply the scale factor if ( ( m_flScale != 0.0f ) && ( m_flScale != 1.0f ) ) { Vector vecTranslation; MatrixGetColumn( matRefToMeasure, 3, vecTranslation ); vecTranslation /= m_flScale; MatrixSetColumn( vecTranslation, 3, matRefToMeasure ); } // Now apply the new matrix to the new reference point matrix3x4_t matMeasureToRef, matNewTargetToWorld; MatrixInvert( matRefToMeasure, matMeasureToRef ); ConcatTransforms( m_hTargetReference->EntityToWorldTransform(), matMeasureToRef, matNewTargetToWorld ); Vector vecNewOrigin; QAngle vecNewAngles; MatrixAngles( matNewTargetToWorld, vecNewAngles, vecNewOrigin ); m_hTarget->SetAbsOrigin( vecNewOrigin ); m_hTarget->SetAbsAngles( vecNewAngles ); } SetNextThink( gpGlobals->curtime + TICK_INTERVAL ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CChoreoGenericServerVehicle::GetVehicleViewPosition( int nRole, Vector *pAbsOrigin, QAngle *pAbsAngles, float *pFOV /*= NULL*/ ) { // FIXME: This needs to be reconciled with the other versions of this function! Assert( nRole == VEHICLE_ROLE_DRIVER ); CBasePlayer *pPlayer = ToBasePlayer( GetDrivableVehicle()->GetDriver() ); Assert( pPlayer ); // Use the player's eyes instead of the attachment point if ( GetVehicle()->m_bForcePlayerEyePoint ) { // Call to BaseClass because CBasePlayer::EyePosition calls this function. *pAbsOrigin = pPlayer->CBaseCombatCharacter::EyePosition(); *pAbsAngles = pPlayer->CBaseCombatCharacter::EyeAngles(); return; } *pAbsAngles = pPlayer->EyeAngles(); // yuck. this is an in/out parameter. float flPitchFactor = 1.0; matrix3x4_t vehicleEyePosToWorld; Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; GetVehicle()->GetAttachment( "vehicle_driver_eyes", vehicleEyeOrigin, vehicleEyeAngles ); AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); // Compute the relative rotation between the unperterbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); // Now perterb the attachment point vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perterbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); }
//----------------------------------------------------------------------------- // Computes PoseToWorld from BoneToWorld //----------------------------------------------------------------------------- void ComputePoseToWorld( matrix3x4_t *pPoseToWorld, studiohdr_t *pStudioHdr, int boneMask, const Vector& vecViewOrigin, const matrix3x4_t *pBoneToWorld ) { if ( pStudioHdr->flags & STUDIOHDR_FLAGS_STATIC_PROP ) { // by definition, these always have an identity poseToBone transform MatrixCopy( pBoneToWorld[ 0 ], pPoseToWorld[ 0 ] ); return; } if ( !pStudioHdr->pLinearBones() ) { // convert bone to world transformations into pose to world transformations for (int i = 0; i < pStudioHdr->numbones; i++) { mstudiobone_t *pCurBone = pStudioHdr->pBone( i ); if ( !(pCurBone->flags & boneMask) ) continue; ConcatTransforms( pBoneToWorld[ i ], pCurBone->poseToBone, pPoseToWorld[ i ] ); } } else { mstudiolinearbone_t *pLinearBones = pStudioHdr->pLinearBones(); // convert bone to world transformations into pose to world transformations for (int i = 0; i < pStudioHdr->numbones; i++) { if ( !(pLinearBones->flags(i) & boneMask) ) continue; ConcatTransforms( pBoneToWorld[ i ], pLinearBones->poseToBone(i), pPoseToWorld[ i ] ); } } #if 0 // These don't seem to be used in any existing QC file, re-enable in a future project? // Pretransform if( !( pCurBone->flags & ( BONE_SCREEN_ALIGN_SPHERE | BONE_SCREEN_ALIGN_CYLINDER ))) { ConcatTransforms( pBoneToWorld[ i ], pCurBone->poseToBone, pPoseToWorld[ i ] ); } else { // If this bone is screen aligned, then generate a PoseToWorld matrix that billboards the bone ScreenAlignBone( &pPoseToWorld[i], pCurBone, vecViewOrigin, pBoneToWorld[i] ); } #endif }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CASW_Prediction::SetupMove( C_BasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) { // Call the default SetupMove code. BaseClass::SetupMove( player, ucmd, pHelper, move ); CASW_Player *pASWPlayer = static_cast<CASW_Player*>( player ); if ( !asw_allow_detach.GetBool() ) { if ( pASWPlayer && pASWPlayer->GetMarine() ) { // this forces horizontal movement move->m_vecAngles.x = 0; move->m_vecViewAngles.x = 0; } } CBaseEntity *pMoveParent = player->GetMoveParent(); if (!pMoveParent) { move->m_vecAbsViewAngles = move->m_vecViewAngles; } else { matrix3x4_t viewToParent, viewToWorld; AngleMatrix( move->m_vecViewAngles, viewToParent ); ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld ); MatrixAngles( viewToWorld, move->m_vecAbsViewAngles ); } CASW_MoveData *pASWMove = static_cast<CASW_MoveData*>( move ); pASWMove->m_iForcedAction = ucmd->forced_action; // setup trace optimization g_pGameMovement->SetupMovementBounds( move ); }
//----------------------------------------------------------------------------- // Purpose: Prepares for running movement // Input : *player - // *ucmd - // *pHelper - // *move - // time - //----------------------------------------------------------------------------- void CPlayerMove::SetupMove( CBasePlayer *player, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) { VPROF( "CPlayerMove::SetupMove" ); // Allow sound, etc. to be created by movement code move->m_bFirstRunOfFunctions = true; // Prepare the usercmd fields move->m_nImpulseCommand = ucmd->impulse; move->m_vecViewAngles = ucmd->viewangles; CBaseEntity *pMoveParent = player->GetMoveParent(); if (!pMoveParent) { move->m_vecAbsViewAngles = move->m_vecViewAngles; } else { matrix3x4_t viewToParent, viewToWorld; AngleMatrix( move->m_vecViewAngles, viewToParent ); ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld ); MatrixAngles( viewToWorld, move->m_vecAbsViewAngles ); } move->m_nButtons = ucmd->buttons; // Ingore buttons for movement if at controls if ( player->GetFlags() & FL_ATCONTROLS ) { move->m_flForwardMove = 0; move->m_flSideMove = 0; move->m_flUpMove = 0; } else { move->m_flForwardMove = ucmd->forwardmove; move->m_flSideMove = ucmd->sidemove; move->m_flUpMove = ucmd->upmove; } // Prepare remaining fields move->m_flClientMaxSpeed = player->m_flMaxspeed; move->m_nOldButtons = player->m_Local.m_nOldButtons; move->m_vecAngles = player->pl.v_angle; move->m_vecVelocity = player->GetAbsVelocity(); move->m_nPlayerHandle = player; move->m_vecAbsOrigin = player->GetAbsOrigin(); // Copy constraint information if ( player->m_hConstraintEntity.Get() ) move->m_vecConstraintCenter = player->m_hConstraintEntity.Get()->GetAbsOrigin(); else move->m_vecConstraintCenter = player->m_vecConstraintCenter; move->m_flConstraintRadius = player->m_flConstraintRadius; move->m_flConstraintWidth = player->m_flConstraintWidth; move->m_flConstraintSpeedFactor = player->m_flConstraintSpeedFactor; }
//----------------------------------------------------------------------------- // Returns the unperterbed view position for a particular role //----------------------------------------------------------------------------- bool CBaseTFVehicle::GetRoleViewPosition( int nRole, Vector *pVehicleEyeOrigin, QAngle *pVehicleEyeAngles ) { // Generate the view position in world space. Vector vAbsOrigin; QAngle vAbsAngle; bool bUsingThirdPersonCamera = GetRoleAbsViewPosition( nRole, &vAbsOrigin, &vAbsAngle ); // Make a matrix for it. matrix3x4_t absMatrix; AngleMatrix( vAbsAngle, absMatrix ); MatrixSetColumn( vAbsOrigin, 3, absMatrix ); // Transform the matrix into local space. matrix3x4_t worldToEntity, local; MatrixInvert( EntityToWorldTransform(), worldToEntity ); ConcatTransforms( worldToEntity, absMatrix, local ); // Suck out the origin and angles. pVehicleEyeOrigin->Init( local[0][3], local[1][3], local[2][3] ); MatrixAngles( local, *pVehicleEyeAngles ); return bUsingThirdPersonCamera; }
//----------------------------------------------------------------------------- // Transform from DME to engine coordinates //----------------------------------------------------------------------------- void CDmeMDL::EngineToDmeMatrix( matrix3x4_t& engineToDme ) { VMatrix rotation, rotationZ; MatrixBuildRotationAboutAxis( rotation, Vector( 1, 0, 0 ), -90 ); MatrixBuildRotationAboutAxis( rotationZ, Vector( 0, 1, 0 ), -90 ); ConcatTransforms( rotationZ.As3x4(), rotation.As3x4(), engineToDme ); }
const matrix3x4_t & C_PortalGhostRenderable::RenderableToWorldTransform() { if( m_pGhostedRenderable == NULL ) return m_ReferencedReturns.matRenderableToWorldTransform; ConcatTransforms( m_matGhostTransform.As3x4(), m_pGhostedRenderable->RenderableToWorldTransform(), m_ReferencedReturns.matRenderableToWorldTransform ); return m_ReferencedReturns.matRenderableToWorldTransform; }
//----------------------------------------------------------------------------- // Purpose: Builds the animation transformation matrix for the entity if it's animating //----------------------------------------------------------------------------- void CMapAnimator::UpdateAnimation( float animTime ) { // only animate if the doc is animating and we're selected if ( !CMapDoc::GetActiveMapDoc()->IsAnimating() || !Parent->IsSelected() ) { // we're not animating m_bCurrentlyAnimating = false; return; } m_bCurrentlyAnimating = true; Vector newOrigin; Quaternion newAngles; GetAnimationAtTime( animTime, newOrigin, newAngles ); matrix4_t mat, tmpMat; Vector ourOrigin; GetOrigin( ourOrigin ); IdentityMatrix( mat ); // build us a matrix // T(newOrigin)R(angle)T(-ourOrigin) IdentityMatrix( m_CoordFrame ) ; // transform back to the origin for ( int i = 0; i < 3; i++ ) { m_CoordFrame[i][3] = -ourOrigin[i]; } // Apply interpolated Rotation QuaternionMatrix( newAngles, mat ); ConcatTransforms( mat, m_CoordFrame, tmpMat ); // transform back to our new position IdentityMatrix( mat ); for ( i = 0; i < 3; i++ ) { mat[i][3] = newOrigin[i]; } ConcatTransforms( mat, tmpMat, m_CoordFrame ); }
void CStickyBomb::Touch( CBaseEntity *pOther ) { // Don't stick if already stuck if ( GetMoveType() == MOVETYPE_FLYGRAVITY ) { trace_t tr = GetTouchTrace(); // stickies don't stick to each other or sky if ( FClassnameIs(pOther, "grenade_stickybomb") || (tr.surface.flags & SURF_SKY) ) { // bounce Vector vecNewVelocity; PhysicsClipVelocity( GetAbsVelocity(), tr.plane.normal, vecNewVelocity, 1.0 ); SetAbsVelocity( vecNewVelocity ); } else { SetAbsVelocity( vec3_origin ); SetMoveType( MOVETYPE_NONE ); if ( pOther->entindex() != 0 ) { // set up notification if the parent is deleted before we explode g_pNotify->AddEntity( this, pOther ); if ( (tr.surface.flags & SURF_HITBOX) && modelinfo->GetModelType( pOther->GetModel() ) == mod_studio ) { CBaseAnimating *pOtherAnim = dynamic_cast<CBaseAnimating *>(pOther); if ( pOtherAnim ) { matrix3x4_t bombWorldSpace; MatrixCopy( EntityToWorldTransform(), bombWorldSpace ); // get the bone info so we can follow the bone FollowEntity( pOther ); SetOwnerEntity( pOther ); m_boneIndexAttached = pOtherAnim->GetHitboxBone( tr.hitbox ); matrix3x4_t boneToWorld; pOtherAnim->GetBoneTransform( m_boneIndexAttached, boneToWorld ); // transform my current position/orientation into the hit bone's space // UNDONE: Eventually we need to intersect with the mesh here // REVISIT: maybe do something like the decal code to find a spot on // the mesh. matrix3x4_t worldToBone, localMatrix; MatrixInvert( boneToWorld, worldToBone ); ConcatTransforms( worldToBone, bombWorldSpace, localMatrix ); MatrixAngles( localMatrix, m_boneAngles.GetForModify(), m_bonePosition.GetForModify() ); return; } } SetParent( pOther ); } } } }
//----------------------------------------------------------------------------- // Shared code to compute the vehicle view position //----------------------------------------------------------------------------- void CFourWheelVehiclePhysics::GetVehicleViewPosition( const char *pViewAttachment, float flPitchFactor, Vector *pAbsOrigin, QAngle *pAbsAngles ) { matrix3x4_t vehicleEyePosToWorld; Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; GetAttachment( pViewAttachment, vehicleEyeOrigin, vehicleEyeAngles ); AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); #ifdef HL2_DLL // View dampening. if ( r_VehicleViewDampen.GetInt() ) { m_pOuterServerVehicle->GetFourWheelVehicle()->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); } #endif // Compute the relative rotation between the unperterbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); // Now perterb the attachment point vehicleEyeAngles.x = RemapAngleRange( PITCH_CURVE_ZERO * flPitchFactor, PITCH_CURVE_LINEAR, vehicleEyeAngles.x ); vehicleEyeAngles.z = RemapAngleRange( ROLL_CURVE_ZERO * flPitchFactor, ROLL_CURVE_LINEAR, vehicleEyeAngles.z ); AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perterbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); }
bool C_PortalGhostRenderable::GetAttachment( int number, matrix3x4_t &matrix ) { if( m_pGhostedRenderable == NULL ) return false; if( m_pGhostedRenderable->GetAttachment( number, matrix ) ) { ConcatTransforms( m_matGhostTransform.As3x4(), matrix, matrix ); return true; } return false; }
//----------------------------------------------------------------------------- // Purpose: Tell the vehicle physics system whenever we teleport, so it can fixup the wheels. //----------------------------------------------------------------------------- void CPropVehicle::Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ) { matrix3x4_t startMatrixInv; MatrixInvert( EntityToWorldTransform(), startMatrixInv ); BaseClass::Teleport( newPosition, newAngles, newVelocity ); // Calculate the relative transform of the teleport matrix3x4_t xform; ConcatTransforms( EntityToWorldTransform(), startMatrixInv, xform ); m_VehiclePhysics.Teleport( xform ); }
//----------------------------------------------------------------------------- // Teleport //----------------------------------------------------------------------------- void CFourWheelVehiclePhysics::Teleport( matrix3x4_t& relativeTransform ) { // We basically just have to make sure the wheels are in the right place // after teleportation occurs for ( int i = 0; i < m_wheelCount; i++ ) { matrix3x4_t matrix, newMatrix; m_pWheels[i]->GetPositionMatrix( &matrix ); ConcatTransforms( relativeTransform, matrix, newMatrix ); m_pWheels[i]->SetPositionMatrix( newMatrix, true ); } }
CASW_Laser_Mine* CASW_Laser_Mine::ASW_Laser_Mine_Create( const Vector &position, const QAngle &angles, const QAngle &angLaserAim, CBaseEntity *pOwner, CBaseEntity *pMoveParent, bool bFriendly, CBaseEntity *pCreatorWeapon ) { CASW_Laser_Mine *pMine = (CASW_Laser_Mine*)CreateEntityByName( "asw_laser_mine" ); pMine->SetLaserAngle( angLaserAim ); matrix3x4_t wallMatrix; AngleMatrix( angles, wallMatrix ); QAngle angRotateMine( 0, 90, 90 ); matrix3x4_t fRotateMatrix; AngleMatrix( angRotateMine, fRotateMatrix ); matrix3x4_t finalMatrix; QAngle angMine; ConcatTransforms( wallMatrix, fRotateMatrix, finalMatrix ); MatrixAngles( finalMatrix, angMine ); Vector vecSrc = pOwner->WorldSpaceCenter(); CASW_Marine *pMarine = dynamic_cast<CASW_Marine*>( pOwner ); if ( pMarine ) vecSrc = pMarine->GetOffhandThrowSource(); pMine->SetAbsAngles( -angMine ); pMine->Spawn(); pMine->SetOwnerEntity( pOwner ); UTIL_SetOrigin( pMine, vecSrc ); pMine->m_bFriendly = bFriendly; pMine->m_hCreatorWeapon.Set( pCreatorWeapon ); // adjust throw duration based on distance and some randomness float flDist = vecSrc.DistTo( position ); const float flBaseDist = 90.0f; float flDistFraction = ( flDist / flBaseDist ); flDistFraction = clamp<float>( flDistFraction, 0.5f, 2.0f ); flDistFraction += RandomFloat( 0.0f, 0.2f ); pMine->StartSpawnFlipping( vecSrc, position, angMine, 0.30f * flDistFraction ); if( pCreatorWeapon ) pMine->m_CreatorWeaponClass = pCreatorWeapon->Classify(); if ( pMoveParent ) { pMine->SetParent( pMoveParent ); gEntList.AddListenerEntity( pMine ); } return pMine; }
void CRagdollProp::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask ) { // no ragdoll, fall through to base class if ( !m_ragdoll.listCount ) { BaseClass::SetupBones( pBoneToWorld, boneMask ); return; } // Not really ideal, but it'll work for now UpdateModelWidthScale(); MDLCACHE_CRITICAL_SECTION(); CStudioHdr *pStudioHdr = GetModelPtr( ); bool sim[MAXSTUDIOBONES]; memset( sim, 0, pStudioHdr->numbones() ); int i; CBoneAccessor boneaccessor( pBoneToWorld ); for ( i = 0; i < m_ragdoll.listCount; i++ ) { // during restore this may be NULL if ( !m_ragdoll.list[i].pObject ) continue; if ( RagdollGetBoneMatrix( m_ragdoll, boneaccessor, i ) ) { sim[m_ragdoll.boneIndex[i]] = true; } } mstudiobone_t *pbones = pStudioHdr->pBone( 0 ); for ( i = 0; i < pStudioHdr->numbones(); i++ ) { if ( sim[i] ) continue; if ( !(pbones[i].flags & boneMask) ) continue; matrix3x4_t matBoneLocal; AngleMatrix( pbones[i].rot, pbones[i].pos, matBoneLocal ); ConcatTransforms( pBoneToWorld[pbones[i].parent], matBoneLocal, pBoneToWorld[i]); } }
bool C_WalkerStrider::GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld ) { // // // This is a TOTAL hack, but we don't have any nodes that work well at all for mounted guns. // // studiohdr_t *pStudioHdr = GetModelPtr( ); if ( !pStudioHdr || iAttachment < 1 || iAttachment > pStudioHdr->numattachments ) { return false; } Vector vLocalPos( 0, 0, 0 ); mstudioattachment_t *pAttachment = pStudioHdr->pAttachment( iAttachment-1 ); if ( stricmp( pAttachment->pszName(), "build_point_left_gun" ) == 0 ) { vLocalPos.y = sideDist; } else if ( stricmp( pAttachment->pszName(), "build_point_right_gun" ) == 0 ) { vLocalPos.y = -sideDist; } else if ( stricmp( pAttachment->pszName(), "ThirdPersonCameraOrigin" ) == 0 ) { } else { // Ok, it's not one of our magical attachments. Use the regular attachment setup stuff. return BaseClass::GetAttachment( iAttachment, attachmentToWorld ); } if ( m_bCrouched ) { vLocalPos.z += downDist; } // Now build the output matrix. matrix3x4_t localMatrix; SetIdentityMatrix( localMatrix ); PositionMatrix( vLocalPos, localMatrix ); ConcatTransforms( EntityToWorldTransform(), localMatrix, attachmentToWorld ); return true; }
SOPAngle *SOPAngle::RotateAroundAxis(SOPVector *vec, lua_Number degrees) { matrix3x4_t m_rgflCoordinateFrame; Vector rotationAxisLs; Quaternion q; matrix3x4_t xform; matrix3x4_t localToWorldMatrix; Vector axisvector = vec->ToVector(); QAngle rotatedAngles; QAngle angOurAngs = ToQAngle(); AngleMatrix( angOurAngs, m_rgflCoordinateFrame ); VectorIRotate( axisvector, m_rgflCoordinateFrame, rotationAxisLs ); AxisAngleQuaternion( rotationAxisLs, degrees, q ); QuaternionMatrix( q, vec3_origin, xform ); ConcatTransforms( m_rgflCoordinateFrame, xform, localToWorldMatrix ); MatrixAngles( localToWorldMatrix, rotatedAngles ); return new SOPAngle(rotatedAngles.x, rotatedAngles.y, rotatedAngles.z); }
//----------------------------------------------------------------------------- // Eye angles //----------------------------------------------------------------------------- const QAngle &CBasePlayer::EyeAngles( ) { // NOTE: Viewangles are measured *relative* to the parent's coordinate system CBaseEntity *pMoveParent = const_cast<CBasePlayer*>(this)->GetMoveParent(); if ( !pMoveParent ) { return pl.v_angle; } // FIXME: Cache off the angles? matrix3x4_t eyesToParent, eyesToWorld; AngleMatrix( pl.v_angle, eyesToParent ); ConcatTransforms( pMoveParent->EntityToWorldTransform(), eyesToParent, eyesToWorld ); static QAngle angEyeWorld; MatrixAngles( eyesToWorld, angEyeWorld ); return angEyeWorld; }
//----------------------------------------------------------------------------- // Generates the PoseToBone Matrix nessecary to align the given bone with the // world. //----------------------------------------------------------------------------- static void ScreenAlignBone( matrix3x4_t *pPoseToWorld, mstudiobone_t *pCurBone, const Vector& vecViewOrigin, const matrix3x4_t &boneToWorld ) { // Grab the world translation: Vector vT( boneToWorld[0][3], boneToWorld[1][3], boneToWorld[2][3] ); // Construct the coordinate frame: // Initialized to get rid of compiler Vector vX, vY, vZ; if( pCurBone->flags & BONE_SCREEN_ALIGN_SPHERE ) { vX = vecViewOrigin - vT; VectorNormalize(vX); vZ = Vector(0,0,1); vY = vZ.Cross(vX); VectorNormalize(vY); vZ = vX.Cross(vY); VectorNormalize(vZ); } else { Assert( pCurBone->flags & BONE_SCREEN_ALIGN_CYLINDER ); vX.Init( boneToWorld[0][0], boneToWorld[1][0], boneToWorld[2][0] ); vZ = vecViewOrigin - vT; VectorNormalize(vZ); vY = vZ.Cross(vX); VectorNormalize(vY); vZ = vX.Cross(vY); VectorNormalize(vZ); } matrix3x4_t matBoneBillboard( vX.x, vY.x, vZ.x, vT.x, vX.y, vY.y, vZ.y, vT.y, vX.z, vY.z, vZ.z, vT.z ); ConcatTransforms( matBoneBillboard, pCurBone->poseToBone, *pPoseToWorld ); }
//----------------------------------------------------------------------------- // Purpose: Vehicle dampening shared between server and client //----------------------------------------------------------------------------- void SharedVehicleViewSmoothing(CBasePlayer *pPlayer, Vector *pAbsOrigin, QAngle *pAbsAngles, bool bEnterAnimOn, bool bExitAnimOn, const Vector &vecEyeExitEndpoint, ViewSmoothingData_t *pData, float *pFOV ) { int eyeAttachmentIndex = pData->pVehicle->LookupAttachment( "vehicle_driver_eyes" ); matrix3x4_t vehicleEyePosToWorld; Vector vehicleEyeOrigin; QAngle vehicleEyeAngles; pData->pVehicle->GetAttachment( eyeAttachmentIndex, vehicleEyeOrigin, vehicleEyeAngles ); AngleMatrix( vehicleEyeAngles, vehicleEyePosToWorld ); // Dampen the eye positional change as we drive around. *pAbsAngles = pPlayer->EyeAngles(); if ( r_VehicleViewDampen.GetInt() && pData->bDampenEyePosition ) { CPropVehicleDriveable *pDriveable = assert_cast<CPropVehicleDriveable*>(pData->pVehicle); pDriveable->DampenEyePosition( vehicleEyeOrigin, vehicleEyeAngles ); } // Started running an entry or exit anim? bool bRunningAnim = ( bEnterAnimOn || bExitAnimOn ); if ( bRunningAnim && !pData->bWasRunningAnim ) { pData->bRunningEnterExit = true; pData->flEnterExitStartTime = gpGlobals->curtime; pData->flEnterExitDuration = pData->pVehicle->SequenceDuration( pData->pVehicle->GetSequence() ); #ifdef CLIENT_DLL pData->vecOriginSaved = PrevMainViewOrigin(); pData->vecAnglesSaved = PrevMainViewAngles(); #endif // Save our initial angular error, which we will blend out over the length of the animation. pData->vecAngleDiffSaved.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); pData->vecAngleDiffSaved.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); pData->vecAngleDiffSaved.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); pData->vecAngleDiffMin = pData->vecAngleDiffSaved; } pData->bWasRunningAnim = bRunningAnim; float frac = 0; float flFracFOV = 0; // If we're in an enter/exit animation, blend the player's eye angles to the attachment's if ( bRunningAnim || pData->bRunningEnterExit ) { *pAbsAngles = vehicleEyeAngles; // Forward integrate to determine the elapsed time in this entry/exit anim. frac = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / pData->flEnterExitDuration; frac = clamp( frac, 0.0f, 1.0f ); flFracFOV = ( gpGlobals->curtime - pData->flEnterExitStartTime ) / ( pData->flEnterExitDuration * 0.85f ); flFracFOV = clamp( flFracFOV, 0.0f, 1.0f ); //Msg("Frac: %f\n", frac ); if ( frac < 1.0 ) { // Blend to the desired vehicle eye origin //Vector vecToView = (vehicleEyeOrigin - PrevMainViewOrigin()); //vehicleEyeOrigin = PrevMainViewOrigin() + (vecToView * SimpleSpline(frac)); //debugoverlay->AddBoxOverlay( vehicleEyeOrigin, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 0,255,255, 64, 10 ); } else { pData->bRunningEnterExit = false; // Enter animation has finished, align view with the eye attachment point // so they can start mouselooking around. #if !defined ( HL2MP_DEV_DLL ) && !defined ( HL2MP_DEV_VEHICLE_FIX ) if ( !bExitAnimOn ) { Vector localEyeOrigin; QAngle localEyeAngles; pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles ); #ifdef CLIENT_DLL engine->SetViewAngles( localEyeAngles ); #endif } #else #ifdef CLIENT_DLL pPlayer = C_BasePlayer::GetLocalPlayer(); #endif if ( pPlayer ) { if ( !bExitAnimOn ) { Vector localEyeOrigin; QAngle localEyeAngles; pData->pVehicle->GetAttachmentLocal( eyeAttachmentIndex, localEyeOrigin, localEyeAngles ); #ifdef CLIENT_DLL engine->SetViewAngles( localEyeAngles ); #endif } } #endif } } // Compute the relative rotation between the unperturbed eye attachment + the eye angles matrix3x4_t cameraToWorld; AngleMatrix( *pAbsAngles, cameraToWorld ); matrix3x4_t worldToEyePos; MatrixInvert( vehicleEyePosToWorld, worldToEyePos ); matrix3x4_t vehicleCameraToEyePos; ConcatTransforms( worldToEyePos, cameraToWorld, vehicleCameraToEyePos ); // Damp out some of the vehicle motion (neck/head would do this) if ( pData->bClampEyeAngles ) { RemapViewAngles( pData, vehicleEyeAngles ); } AngleMatrix( vehicleEyeAngles, vehicleEyeOrigin, vehicleEyePosToWorld ); // Now treat the relative eye angles as being relative to this new, perturbed view position... matrix3x4_t newCameraToWorld; ConcatTransforms( vehicleEyePosToWorld, vehicleCameraToEyePos, newCameraToWorld ); // output new view abs angles MatrixAngles( newCameraToWorld, *pAbsAngles ); // UNDONE: *pOrigin would already be correct in single player if the HandleView() on the server ran after vphysics MatrixGetColumn( newCameraToWorld, 3, *pAbsOrigin ); float flDefaultFOV; #ifdef CLIENT_DLL flDefaultFOV = default_fov.GetFloat(); #else flDefaultFOV = pPlayer->GetDefaultFOV(); #endif // If we're playing an entry or exit animation... if ( bRunningAnim || pData->bRunningEnterExit ) { float flSplineFrac = clamp( SimpleSpline( frac ), 0.f, 1.f ); // Blend out the error between the player's initial eye angles and the animation's initial // eye angles over the duration of the animation. QAngle vecAngleDiffBlend = ( ( 1 - flSplineFrac ) * pData->vecAngleDiffSaved ); // If our current error is less than the error amount that we're blending // out, use that. This lets the angles converge as quickly as possible. QAngle vecAngleDiffCur; vecAngleDiffCur.x = AngleDiff( vehicleEyeAngles.x, pData->vecAnglesSaved.x ); vecAngleDiffCur.y = AngleDiff( vehicleEyeAngles.y, pData->vecAnglesSaved.y ); vecAngleDiffCur.z = AngleDiff( vehicleEyeAngles.z, pData->vecAnglesSaved.z ); // In either case, never increase the error, so track the minimum error and clamp to that. for (int i = 0; i < 3; i++) { if ( fabs(vecAngleDiffCur[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) { pData->vecAngleDiffMin[i] = vecAngleDiffCur[i]; } if ( fabs(vecAngleDiffBlend[i] ) < fabs( pData->vecAngleDiffMin[i] ) ) { pData->vecAngleDiffMin[i] = vecAngleDiffBlend[i]; } } // Add the error to the animation's eye angles. *pAbsAngles -= pData->vecAngleDiffMin; // Use this as the basis for the next error calculation. pData->vecAnglesSaved = *pAbsAngles; //if ( gpGlobals->frametime ) //{ // Msg("Angle : %.2f %.2f %.2f\n", target.x, target.y, target.z ); //} //Msg("Prev: %.2f %.2f %.2f\n", pData->vecAnglesSaved.x, pData->vecAnglesSaved.y, pData->vecAnglesSaved.z ); Vector vecAbsOrigin = *pAbsOrigin; // If we're exiting, our desired position is the server-sent exit position if ( bExitAnimOn ) { //debugoverlay->AddBoxOverlay( vecEyeExitEndpoint, -Vector(1,1,1), Vector(1,1,1), vec3_angle, 255,255,255, 64, 10 ); // Blend to the exit position *pAbsOrigin = Lerp( flSplineFrac, vecAbsOrigin, vecEyeExitEndpoint ); if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { *pFOV = Lerp( flFracFOV, pData->flFOV, flDefaultFOV ); } } } else { // Blend from our starting position to the desired origin *pAbsOrigin = Lerp( flSplineFrac, pData->vecOriginSaved, vecAbsOrigin ); if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { *pFOV = Lerp( flFracFOV, flDefaultFOV, pData->flFOV ); } } } } else if ( pFOV != NULL ) { if ( pData->flFOV > flDefaultFOV ) { // Not running an entry/exit anim. Just use the vehicle's FOV. *pFOV = pData->flFOV; } } }
// apply custom pitch to bone merge void CASW_Bone_Merge_Cache::MergeMatchingBones( int boneMask, CBoneBitList &boneComputed, bool bOverrideDirection, const Vector &vecDir ) { UpdateCache(); // If this is set, then all the other cache data is set. if ( !m_pOwnerHdr || m_MergedBones.Count() == 0 ) return; // Have the entity we're following setup its bones. m_pFollow->SetupBones( NULL, -1, m_nFollowBoneSetupMask, gpGlobals->curtime ); matrix3x4_t matPitchUp; AngleMatrix( QAngle( asw_weapon_pitch.GetFloat(), 0, 0 ), matPitchUp ); // Now copy the bone matrices. for ( int i=0; i < m_MergedBones.Count(); i++ ) { int iOwnerBone = m_MergedBones[i].m_iMyBone; int iParentBone = m_MergedBones[i].m_iParentBone; // Only update bones reference by the bone mask. if ( !( m_pOwnerHdr->boneFlags( iOwnerBone ) & boneMask ) ) continue; if ( bOverrideDirection && m_nRightHandBoneID == -1 ) // only want to change direction of the right hand bone, cache its index here { mstudiobone_t *pOwnerBones = m_pOwnerHdr->pBone( 0 ); for ( int k = 0; k < m_pOwnerHdr->numbones(); k++ ) { if ( !Q_stricmp( pOwnerBones[k].pszName(), "ValveBiped.Bip01_R_Hand" ) ) { m_nRightHandBoneID = k; break; } } } if ( bOverrideDirection && i == m_nRightHandBoneID ) { matrix3x4_t matParentBoneToWorld; m_pFollow->GetBoneTransform( iParentBone, matParentBoneToWorld ); MatrixSetColumn( vec3_origin, 3, matParentBoneToWorld ); // remove translation matrix3x4_t matParentBoneToWorldInv; MatrixInvert( matParentBoneToWorld, matParentBoneToWorldInv ); QAngle angAiming; VectorAngles( vecDir, Vector( 0, 0, -1 ), angAiming ); matrix3x4_t matAimDirection; AngleMatrix( angAiming, matAimDirection ); MatrixSetColumn( vec3_origin, 3, matAimDirection ); // remove translation matrix3x4_t matCorrection; ConcatTransforms( matParentBoneToWorldInv, matAimDirection, matCorrection ); ConcatTransforms( m_pFollow->GetBone( iParentBone ), matCorrection, m_pOwner->GetBoneForWrite( iOwnerBone ) ); } else { ConcatTransforms( m_pFollow->GetBone( iParentBone ), matPitchUp, m_pOwner->GetBoneForWrite( iOwnerBone ) ); } boneComputed.Set( i ); } }
void CMarineMove::SetupMarineMove( const CBasePlayer *player, CBaseEntity *marine, CUserCmd *ucmd, IMoveHelper *pHelper, CMoveData *move ) { VPROF( "CMarineMove::SetupMarineMove" ); // hm, we need it to be a specific swarm marine here, not a generic entity CASW_Marine *aswmarine = static_cast< CASW_Marine * >(marine); if (aswmarine == NULL) return; // Prepare the usercmd fields move->m_nImpulseCommand = ucmd->impulse; move->m_vecViewAngles = ucmd->viewangles; move->m_vecViewAngles.x = 0; // asw always walking horizontally CBaseEntity *pMoveParent = marine->GetMoveParent(); if (!pMoveParent) { move->m_vecAbsViewAngles = move->m_vecViewAngles; } else { matrix3x4_t viewToParent, viewToWorld; AngleMatrix( move->m_vecViewAngles, viewToParent ); ConcatTransforms( pMoveParent->EntityToWorldTransform(), viewToParent, viewToWorld ); MatrixAngles( viewToWorld, move->m_vecAbsViewAngles ); } move->m_nButtons = ucmd->buttons; // Ingore buttons for movement if at controls if ( marine->GetFlags() & FL_ATCONTROLS ) { move->m_flForwardMove = 0; move->m_flSideMove = 0; move->m_flUpMove = 0; } else { move->m_flForwardMove = ucmd->forwardmove; move->m_flSideMove = ucmd->sidemove; move->m_flUpMove = ucmd->upmove; } // Prepare remaining fields move->m_flClientMaxSpeed = aswmarine->MaxSpeed(); //player->MaxSpeed(); #ifdef CLIENT_DLL //Msg("maxspeed = %f\n", move->m_flClientMaxSpeed); #endif //move->m_nOldButtons = player->m_Local.m_nOldButtons; move->m_nOldButtons = aswmarine->m_nOldButtons; move->m_vecAngles = marine->GetAbsAngles(); //player->pl.v_angle; #ifdef GAME_DLL //Msg("S ucmd %d vel %f %f %f\n", ucmd->command_number, move->m_vecVelocity.x, move->m_vecVelocity.y, move->m_vecVelocity.z); #else //Msg("C ucmd %d vel %f %f %f\n", ucmd->command_number, move->m_vecVelocity.x, move->m_vecVelocity.y, move->m_vecVelocity.z); #endif move->m_vecVelocity = marine->GetAbsVelocity(); move->m_nPlayerHandle = marine;//player; #ifdef GAME_DLL move->SetAbsOrigin( marine->GetAbsOrigin() ); #else move->SetAbsOrigin( marine->GetNetworkOrigin() ); /* C_BaseEntity *pEnt = cl_entitylist->FirstBaseEntity(); while (pEnt) { if (FClassnameIs(pEnt, "class C_DynamicProp")) { Msg("Setting z to %f\n", pEnt->GetAbsOrigin().z + 10); move->m_vecAbsOrigin.z = pEnt->GetAbsOrigin().z + 10; marine->SetNetworkOrigin(pEnt->GetAbsOrigin() + Vector(0,0,10)); break; } pEnt = cl_entitylist->NextBaseEntity( pEnt ); } */ #endif //Msg("Move X velocity set to %f forward move = %f origin = %f\n", // move->m_vecVelocity.x, move->m_flForwardMove, move->m_vecAbsOrigin.x); // Copy constraint information /* if ( player->m_hConstraintEntity.Get() ) move->m_vecConstraintCenter = player->m_hConstraintEntity.Get()->GetAbsOrigin(); else move->m_vecConstraintCenter = player->m_vecConstraintCenter; move->m_flConstraintRadius = player->m_flConstraintRadius; move->m_flConstraintWidth = player->m_flConstraintWidth; move->m_flConstraintSpeedFactor = player->m_flConstraintSpeedFactor; */ }
/* ==================== StudioMergeBones ==================== */ void CStudioModelRenderer::StudioMergeBones ( model_t *m_pSubModel ) { int i, j; double f; int do_hunt = true; mstudiobone_t *pbones; mstudioseqdesc_t *pseqdesc; mstudioanim_t *panim; static float pos[MAXSTUDIOBONES][3]; float bonematrix[3][4]; static vec4_t q[MAXSTUDIOBONES]; if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) { m_pCurrentEntity->curstate.sequence = 0; } pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; f = StudioEstimateFrame( pseqdesc ); if (m_pCurrentEntity->latched.prevframe > f) { //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f ); } panim = StudioGetAnim( m_pSubModel, pseqdesc ); StudioCalcRotations( pos, q, pseqdesc, panim, f ); pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); for (i = 0; i < m_pStudioHeader->numbones; i++) { for (j = 0; j < m_nCachedBones; j++) { if (stricmp(pbones[i].name, m_nCachedBoneNames[j]) == 0) { MatrixCopy( m_rgCachedBoneTransform[j], (*m_pbonetransform)[i] ); MatrixCopy( m_rgCachedLightTransform[j], (*m_plighttransform)[i] ); break; } } if (j >= m_nCachedBones) { QuaternionMatrix( q[i], bonematrix ); bonematrix[0][3] = pos[i][0]; bonematrix[1][3] = pos[i][1]; bonematrix[2][3] = pos[i][2]; if (pbones[i].parent == -1) { if ( IEngineStudio.IsHardware() ) { ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); // MatrixCopy should be faster... //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] ); } else { ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); } // Apply client-side effects to the transformation matrix StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] ); } else { ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); } } } }
/* ==================== StudioSetupBones ==================== */ void CStudioModelRenderer::StudioSetupBones ( void ) { int i; double f; mstudiobone_t *pbones; mstudioseqdesc_t *pseqdesc; mstudioanim_t *panim; static float pos[MAXSTUDIOBONES][3]; static vec4_t q[MAXSTUDIOBONES]; float bonematrix[3][4]; static float pos2[MAXSTUDIOBONES][3]; static vec4_t q2[MAXSTUDIOBONES]; static float pos3[MAXSTUDIOBONES][3]; static vec4_t q3[MAXSTUDIOBONES]; static float pos4[MAXSTUDIOBONES][3]; static vec4_t q4[MAXSTUDIOBONES]; if (m_pCurrentEntity->curstate.sequence >= m_pStudioHeader->numseq) { m_pCurrentEntity->curstate.sequence = 0; } pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence; f = StudioEstimateFrame( pseqdesc ); if (m_pCurrentEntity->latched.prevframe > f) { //Con_DPrintf("%f %f\n", m_pCurrentEntity->prevframe, f ); } panim = StudioGetAnim( m_pRenderModel, pseqdesc ); StudioCalcRotations( pos, q, pseqdesc, panim, f ); if (pseqdesc->numblends > 1) { float s; float dadt; panim += m_pStudioHeader->numbones; StudioCalcRotations( pos2, q2, pseqdesc, panim, f ); dadt = StudioEstimateInterpolant(); s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; StudioSlerpBones( q, pos, q2, pos2, s ); if (pseqdesc->numblends == 4) { panim += m_pStudioHeader->numbones; StudioCalcRotations( pos3, q3, pseqdesc, panim, f ); panim += m_pStudioHeader->numbones; StudioCalcRotations( pos4, q4, pseqdesc, panim, f ); s = (m_pCurrentEntity->curstate.blending[0] * dadt + m_pCurrentEntity->latched.prevblending[0] * (1.0 - dadt)) / 255.0; StudioSlerpBones( q3, pos3, q4, pos4, s ); s = (m_pCurrentEntity->curstate.blending[1] * dadt + m_pCurrentEntity->latched.prevblending[1] * (1.0 - dadt)) / 255.0; StudioSlerpBones( q, pos, q3, pos3, s ); } } if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && ( m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime ) && ( m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq )) { // blend from last sequence static float pos1b[MAXSTUDIOBONES][3]; static vec4_t q1b[MAXSTUDIOBONES]; float s; pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; panim = StudioGetAnim( m_pRenderModel, pseqdesc ); // clip prevframe StudioCalcRotations( pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe ); if (pseqdesc->numblends > 1) { panim += m_pStudioHeader->numbones; StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe ); s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; StudioSlerpBones( q1b, pos1b, q2, pos2, s ); if (pseqdesc->numblends == 4) { panim += m_pStudioHeader->numbones; StudioCalcRotations( pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe ); panim += m_pStudioHeader->numbones; StudioCalcRotations( pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe ); s = (m_pCurrentEntity->latched.prevseqblending[0]) / 255.0; StudioSlerpBones( q3, pos3, q4, pos4, s ); s = (m_pCurrentEntity->latched.prevseqblending[1]) / 255.0; StudioSlerpBones( q1b, pos1b, q3, pos3, s ); } } s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; StudioSlerpBones( q, pos, q1b, pos1b, s ); } else { //Con_DPrintf("prevframe = %4.2f\n", f); m_pCurrentEntity->latched.prevframe = f; } pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); // calc gait animation if (m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0) { if (m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq) { m_pPlayerInfo->gaitsequence = 0; } pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence; panim = StudioGetAnim( m_pRenderModel, pseqdesc ); StudioCalcRotations( pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe ); for (i = 0; i < m_pStudioHeader->numbones; i++) { if (strcmp( pbones[i].name, "Bip01 Spine") == 0) break; memcpy( pos[i], pos2[i], sizeof( pos[i] )); memcpy( q[i], q2[i], sizeof( q[i] )); } } for (i = 0; i < m_pStudioHeader->numbones; i++) { QuaternionMatrix( q[i], bonematrix ); bonematrix[0][3] = pos[i][0]; bonematrix[1][3] = pos[i][1]; bonematrix[2][3] = pos[i][2]; if (pbones[i].parent == -1) { if ( IEngineStudio.IsHardware() ) { ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]); // MatrixCopy should be faster... //ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); MatrixCopy( (*m_pbonetransform)[i], (*m_plighttransform)[i] ); } else { ConcatTransforms ((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); ConcatTransforms ((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); } // Apply client-side effects to the transformation matrix StudioFxTransform( m_pCurrentEntity, (*m_pbonetransform)[i] ); } else { ConcatTransforms ((*m_pbonetransform)[pbones[i].parent], bonematrix, (*m_pbonetransform)[i]); ConcatTransforms ((*m_plighttransform)[pbones[i].parent], bonematrix, (*m_plighttransform)[i]); } } }