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; }
//----------------------------------------------------------------------------- // 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 ); }
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 ); } }
//----------------------------------------------------------------------------- // 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; }
void RagdollApplyAnimationAsVelocity( ragdoll_t &ragdoll, matrix3x4_t pBoneToWorld[] ) { for ( int i = 0; i < ragdoll.listCount; i++ ) { matrix3x4_t inverse; MatrixInvert( pBoneToWorld[i], inverse ); Quaternion q; Vector pos; MatrixAngles( inverse, q, pos ); Vector velocity; AngularImpulse angVel; float flSpin; Vector localVelocity; AngularImpulse localAngVelocity; QuaternionAxisAngle( q, localAngVelocity, flSpin ); localAngVelocity *= flSpin; localVelocity = pos; // move those bone-local coords back to world space using the ragdoll transform ragdoll.list[i].pObject->LocalToWorldVector( velocity, localVelocity ); ragdoll.list[i].pObject->LocalToWorldVector( angVel, localAngVelocity ); ragdoll.list[i].pObject->AddVelocity( &velocity, &angVel ); } }
//----------------------------------------------------------------------------------- void Matrix4x4::MatrixInvertOrthogonal(Matrix4x4* matrix) { Vector3 translation = MatrixGetOffset(matrix); MatrixTranspose(matrix); MatrixSetColumn(matrix, 3, Vector4(0.0f, 0.0f, 0.0f, 1.0f)); Matrix4x4 translationMatrix; MatrixMakeTranslation(&translationMatrix, translation); MatrixInvert(&translationMatrix); MatrixMultiply(matrix, &translationMatrix, matrix); }
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 ); } } } }
/* * Given an Xform structure and forward and inverse transformations, * propagate the information in the Xform structure to the * transformations. * In this case, the information "in" the Xform structure is * actually stored in the forward transformation; the Xform * points to NULL. */ void XformPropagate(TransRef tr, RSMatrix *trans,RSMatrix* itrans) { Xform *xform = (Xform*)tr; /* * The Xform methods change the forward trans * directly, so it's already all set. * Build the inverse... */ MatrixInvert(trans, itrans); }
//----------------------------------------------------------------------------- // 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 CStudioPhysics::Load( MDLHandle_t mdlHandle ) { m_MDLHandle = mdlHandle; LoadPhysicsProperties(); vcollide_t *pVCollide = GetVCollide( ); if ( !pVCollide ) { m_pList = NULL; m_listCount = 0; return; } m_pList = new CPhysmesh[pVCollide->solidCount]; m_listCount = pVCollide->solidCount; int i; for ( i = 0; i < pVCollide->solidCount; i++ ) { m_pList[i].Clear(); m_pList[i].m_vertCount = physcollision->CreateDebugMesh( pVCollide->solids[i], &m_pList[i].m_pVerts ); m_pList[i].m_pCollisionModel = physcollision->CreateQueryModel( pVCollide->solids[i] ); } ParseKeydata(); CStudioHdr studioHdr( g_pMDLCache->GetStudioHdr( mdlHandle ), g_pMDLCache ); for ( i = 0; i < pVCollide->solidCount; i++ ) { CPhysmesh *pmesh = m_pList + i; int boneIndex = FindBoneIndex( &studioHdr, pmesh->m_boneName ); if ( boneIndex < 0 ) continue; if ( pmesh->m_constraint.parentIndex >= 0 ) { CPhysmesh *pparent = m_pList + pmesh->m_constraint.parentIndex; int parentIndex = FindBoneIndex( &studioHdr, pparent->m_boneName ); Studio_CalcBoneToBoneTransform( &studioHdr, boneIndex, parentIndex, pmesh->m_matrix ); } else { MatrixInvert( studioHdr.pBone(boneIndex)->poseToBone, pmesh->m_matrix ); } } // doesn't have a root bone? Make it the first bone if ( !m_edit.rootName[0] ) { strcpy( m_edit.rootName, m_pList[0].m_boneName ); } }
//----------------------------------------------------------------------------- // 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 ); }
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 ); }
void polyfitr(int npoly, int nfreq, float ddata[], float wtt[], float dataout[]) { int i, j, k, kk, m1, m2; double re, dd, freq; long double aarr[NPOLY * NPOLY], bbrr[NPOLY * NPOLY]; static float mcalc[NSPEC * NPOLY]; for (i = 0; i < nfreq; i++) { kk = i * npoly; freq = (double) (i - d1.fc * d1.nfreq) / ((double) (d1.fc * nfreq)); for (j = 0; j < npoly; j++) { mcalc[kk] = pow(freq, (double) j); kk++; } } for (i = 0; i < npoly; i++) { re = 0.0; m1 = i; for (k = 0; k < nfreq; k++) { dd = log10(ddata[k]); if (wtt[k] > 0) re += mcalc[m1] * dd * wtt[k]; m1 += npoly; } bbrr[i] = re; for (j = 0; j <= i; j++) { re = 0.0; m1 = i; m2 = j; for (k = 0; k < nfreq; k++) { if (wtt[k] > 0) re += mcalc[m1] * mcalc[m2] * wtt[k]; m1 += npoly; m2 += npoly; } k = j + (i * (i + 1)) / 2; aarr[k] = re; } } MatrixInvert(npoly, aarr, bbrr); // for (j = 0; j < npoly; j++) printf("poly %d %f\n",j,(double)bbrr[j]); for (i = 0; i < nfreq; i++) { re = 0.0; freq = (double) (i - d1.fc * d1.nfreq) / ((double) (d1.fc * nfreq)); for (j = 0; j < npoly; j++) { re += bbrr[j] * pow(freq, (double) j); } dd = pow(10.0, re); dataout[i] = dd; } }
//----------------------------------------------------------------------------- // 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 ); }
void CBeam::SetAbsEndPos( const Vector &pos ) { if (!GetMoveParent()) { SetEndPos( pos ); return; } Vector vecLocalPos; matrix3x4_t worldToBeam; MatrixInvert( EntityToWorldTransform(), worldToBeam ); VectorTransform( pos, worldToBeam, vecLocalPos ); SetEndPos( vecLocalPos ); }
void TransformUtil::transformPointWithParent(DBTransform &transform, DBTransform &parent) { transformToMatrix(parent, _helpMatrix); _helpMatrix = MatrixInvert(_helpMatrix); Number x = transform.x; Number y = transform.y; transform.x = _helpMatrix.a * x + _helpMatrix.c * y + _helpMatrix.tx; transform.y = _helpMatrix.b * x + _helpMatrix.d * y + _helpMatrix.ty; transform.skewX = formatRadian(transform.skewX - parent.skewX); transform.skewY = formatRadian(transform.skewY - parent.skewY); }
Mapping * LinearMappingCreate( Vector *center, Vector *vaxis, Vector *uaxis) { Mapping *res; RSMatrix m; Vector n; res = (Mapping *)Malloc(sizeof(Mapping)); res->flags = OBJSPACE; res->method= LinearMapping; if (center) res->center = *center; else res->center.x = res->center.y = res->center.z = 0.; if (uaxis && vaxis) { VecCross(uaxis, vaxis, &n); /* this is wrong, since uaxis and vaxis * give U and V in world space, and we * need the inverse. */ ArbitraryMatrix( uaxis->x, uaxis->y, uaxis->z, vaxis->x, vaxis->y, vaxis->z, n.x, n.y, n.z, res->center.x, res->center.y, res->center.z, &m); MatrixInvert(&m, &res->m); res->uaxis = *uaxis; res->vaxis = *vaxis; VecNormalize(&res->uaxis); VecNormalize(&res->vaxis); } else { VecScale(-1., res->center, &n); TranslationMatrix(n.x, n.y, n.z, &res->m); res->uaxis.x = res->vaxis.y = 1.; res->uaxis.y = res->uaxis.z = res->vaxis.x = res->vaxis.z = 0.; } return res; }
int FindContext(double M[2][2]) /* array to search for */ { register int i; /* loop variable for search */ for (i=0; i < nextcontext; i++) if (M[0][0] == contexts[i].normal[0][0] && M[1][0] == contexts[i].normal[1][0] && M[0][1] == contexts[i].normal[0][1] && M[1][1] == contexts[i].normal[1][1]) break; if (i >= nextcontext) { if (i >= MAXCONTEXTS) Abort("Context: out of them"); LONGCOPY(contexts[i].normal, M, sizeof(contexts[i].normal)); MatrixInvert(M, contexts[i].inverse); nextcontext++; } return(i); }
//----------------------------------------------------------------------------- // 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 ); }
//----------------------------------------------------------------------------- // Sets up the camera //----------------------------------------------------------------------------- void CRenderManager::SetupCameraRenderState( ) { CCameraProperty *pCamera = g_pWorldManager->GetLocalPlayer()->m_pCameraProperty; matrix3x4_t cameraToWorld; AngleMatrix( pCamera->m_Angles, pCamera->m_Origin, cameraToWorld ); matrix3x4_t matRotate; matrix3x4_t matRotateZ; MatrixBuildRotationAboutAxis( Vector(0,0,1), -90, matRotateZ ); MatrixMultiply( cameraToWorld, matRotateZ, matRotate ); matrix3x4_t matRotateX; MatrixBuildRotationAboutAxis( Vector(1,0,0), 90, matRotateX ); MatrixMultiply( matRotate, matRotateX, matRotate ); matrix3x4_t view; MatrixInvert( matRotate, view ); CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->LoadMatrix( view ); }
//----------------------------------------------------------------------------- // Purpose: Recompute my rendering box //----------------------------------------------------------------------------- void C_QUA_Strider::ClientThink() { int i; Vector vecMins, vecMaxs; Vector vecAbsMins, vecAbsMaxs; matrix3x4_t worldToStrider, hitboxToStrider; Vector vecBoxMins, vecBoxMaxs; Vector vecBoxAbsMins, vecBoxAbsMaxs; mstudiohitboxset_t *set; CBoneCache *pCache = NULL; // The reason why this is here, as opposed to in SetObjectCollisionBox, // is because of IK. The code below recomputes bones so as to get at the hitboxes, // which causes IK to trigger, which causes raycasts against the other entities to occur, // which is illegal to do while in the Relink phase. studiohdr_t *pStudioHdr = GetModel()?modelinfo->GetStudiomodel( GetModel() ):NULL; if (!pStudioHdr) goto doneWithComputation; set = pStudioHdr->pHitboxSet( m_nHitboxSet ); if ( !set || !set->numhitboxes ) goto doneWithComputation; CStudioHdr *hdr = GetModelPtr(); pCache = GetBoneCache( hdr ); matrix3x4_t *hitboxbones[MAXSTUDIOBONES]; pCache->ReadCachedBonePointers( hitboxbones, pStudioHdr->numbones ); // // Compute a box in world space that surrounds this entity m_vecRenderMins.Init( FLT_MAX, FLT_MAX, FLT_MAX ); m_vecRenderMaxs.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); // MatrixInvert( EntityToWorldTransform(), worldToStrider ); // for ( i = 0; i < set->numhitboxes; i++ ) { mstudiobbox_t *pbox = set->pHitbox(i); ConcatTransforms( worldToStrider, *hitboxbones[pbox->bone], hitboxToStrider ); TransformAABB( hitboxToStrider, pbox->bbmin, pbox->bbmax, vecBoxMins, vecBoxMaxs ); VectorMin( m_vecRenderMins, vecBoxMins, m_vecRenderMins ); VectorMax( m_vecRenderMaxs, vecBoxMaxs, m_vecRenderMaxs ); } // // Deberiamos poner aqui lo de la vista?? // // // UNDONE: Disabled this until we can get closer to a final map and tune //#if 0 // // Cut ropes. // if ( gpGlobals->curtime >= m_flNextRopeCutTime ) // { // // Blow the bbox out a little. // Vector vExtendedMins = vecMins - Vector( 50, 50, 50 ); // Vector vExtendedMaxs = vecMaxs + Vector( 50, 50, 50 ); // // C_RopeKeyframe *ropes[512]; // int nRopes = C_RopeKeyframe::GetRopesIntersectingAABB( ropes, ARRAYSIZE( ropes ), GetAbsOrigin() + vExtendedMins, GetAbsOrigin() + vExtendedMaxs ); // for ( int i=0; i < nRopes; i++ ) // { // C_RopeKeyframe *pRope = ropes[i]; // // if ( pRope->GetEndEntity() ) // { // Vector vPos; // if ( pRope->GetEndPointPos( 1, vPos ) ) // { // // Detach the endpoint. // pRope->SetEndEntity( NULL ); // // // Make some spark effect here.. // g_pEffects->Sparks( vPos ); // } // } // } // // m_flNextRopeCutTime = gpGlobals->curtime + 0.5; // } //#endif doneWithComputation: // True argument because the origin may have stayed the same, but the size is expected to always change g_pClientShadowMgr->AddToDirtyShadowList( this, true ); }
//----------------------------------------------------------------------------- // 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 IFaceposerModels::CFacePoserModel::CreateNewBitmap( char const *pchBitmapFilename, int sequence, int nSnapShotSize, bool bZoomInOnFace, CExpression *pExpression, mxbitmapdata_t *bitmap ) { MatSysWindow *pWnd = g_pMatSysWindow; if ( !pWnd ) return; StudioModel *model = m_pModel; if ( !model ) return; CStudioHdr *hdr = model->GetStudioHdr(); if ( !hdr ) return; if ( sequence < 0 || sequence >= hdr->GetNumSeq() ) return; mstudioseqdesc_t &seqdesc = hdr->pSeqdesc( sequence ); Con_ColorPrintf( FILE_COLOR, "Creating bitmap %s for sequence '%s'\n", pchBitmapFilename, seqdesc.pszLabel() ); model->ClearOverlaysSequences(); int iLayer = model->GetNewAnimationLayer(); model->SetOverlaySequence( iLayer, sequence, 1.0 ); model->SetOverlayRate( iLayer, FindPoseCycle( model, sequence ), 0.0 ); for (int i = 0; i < hdr->GetNumPoseParameters(); i++) { model->SetPoseParameter( i, 0.0 ); } float flexValues[ GLOBAL_STUDIO_FLEX_CONTROL_COUNT ] = { 0 }; if ( pExpression ) { float *settings = pExpression->GetSettings(); float *weights = pExpression->GetWeights(); // Save existing settings from model for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i ) { int j = hdr->pFlexcontroller( i )->localToGlobal; if ( j == -1 ) continue; flexValues[ i ] = model->GetFlexController( i ); // Set Value from passed in settings model->SetFlexController( i, settings[ j ] * weights[ j ] ); } } model->ClearLookTargets( ); QAngle oldrot, oldLight; Vector oldtrans; VectorCopy( model->m_angles, oldrot ); VectorCopy( model->m_origin, oldtrans ); VectorCopy( g_viewerSettings.lightrot, oldLight ); model->m_angles.Init(); model->m_origin.Init(); g_viewerSettings.lightrot.Init(); g_viewerSettings.lightrot.y = -180; bool bSaveGround = g_viewerSettings.showGround; g_viewerSettings.showGround = false; if ( bZoomInOnFace ) { Vector size; VectorSubtract( hdr->hull_max(), hdr->hull_min(), size ); float eyeheight = hdr->hull_min().z + 0.9 * size.z; // float width = ( size.x + size.y ) / 2.0f; model->m_origin.x = size.z * .6f; if ( hdr->GetNumAttachments() > 0 ) { for (int i = 0; i < hdr->GetNumAttachments(); i++) { const mstudioattachment_t &attachment = hdr->pAttachment( i ); int iBone = hdr->GetAttachmentBone( i ); if ( Q_stricmp( attachment.pszName(), "eyes" ) ) continue; mstudiobone_t *bone = hdr->pBone( iBone ); if ( !bone ) continue; matrix3x4_t boneToPose; MatrixInvert( bone->poseToBone, boneToPose ); matrix3x4_t attachmentPoseToLocal; ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal ); Vector localSpaceEyePosition; VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition ); // Not sure why this must be negative? eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z; break; } } KeyValues *seqKeyValues = new KeyValues(""); if ( seqKeyValues->LoadFromBuffer( model->GetFileName( ), model->GetKeyValueText( sequence ) ) ) { // Do we have a build point section? KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer"); if ( pkvAllFaceposer ) { float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f ); if ( flEyeheight != -9999.0f ) { eyeheight = flEyeheight; } } } model->m_origin.z += eyeheight; } else { Vector mins, maxs; model->ExtractBbox(mins, maxs); Vector size; VectorSubtract( maxs, mins, size ); float maxdim = size.x; if ( size.y > maxdim ) maxdim = size.y; if ( size.z > maxdim ) maxdim = size.z; float midpoint = mins.z + 0.5 * size.z; model->m_origin.x = 3 * maxdim; model->m_origin.z += midpoint; } pWnd->SuppressResize( true ); RECT rcClient; HWND wnd = (HWND)pWnd->getHandle(); WINDOWPLACEMENT wp; GetWindowPlacement( wnd, &wp ); GetClientRect( wnd, &rcClient ); MoveWindow( wnd, 0, 0, nSnapShotSize + 16, nSnapShotSize + 16, TRUE ); // Snapshots are taken of the back buffer; // we need to render to the back buffer but not move it to the front pWnd->SuppressBufferSwap( true ); pWnd->redraw(); pWnd->SuppressBufferSwap( false ); // make it square, assumes w > h char fullpath[ 512 ]; Q_snprintf( fullpath, sizeof( fullpath ), "%s%s", GetGameDirectory(), pchBitmapFilename ); pWnd->TakeSnapshotRect( fullpath, 0, 0, nSnapShotSize, nSnapShotSize ); // Move back to original position SetWindowPlacement( wnd, &wp ); pWnd->SuppressResize( false ); VectorCopy( oldrot, model->m_angles ); VectorCopy( oldtrans, model->m_origin ); VectorCopy( oldLight, g_viewerSettings.lightrot ); g_viewerSettings.showGround = bSaveGround; if ( pExpression ) { // Save existing settings from model for ( LocalFlexController_t i = LocalFlexController_t(0); i < hdr->numflexcontrollers(); ++i ) { int j = hdr->pFlexcontroller( i )->localToGlobal; if ( j == -1 ) continue; model->SetFlexController( i, flexValues[ i ] ); } } model->ClearOverlaysSequences(); if ( bitmap->valid ) { DeleteObject( bitmap->image ); bitmap->image = 0; bitmap->valid = false; } LoadBitmapFromFile( pchBitmapFilename, *bitmap ); }
void ControlPanel::CenterOnFace( void ) { if ( !models->GetActiveStudioModel() ) return; StudioModel *mdl = models->GetActiveStudioModel(); if ( !mdl ) return; CStudioHdr *hdr = mdl->GetStudioHdr(); if ( !hdr ) return; setSpeed( 1.0f ); int oldSeq = models->GetActiveStudioModel()->GetSequence(); int seq = models->GetActiveStudioModel()->LookupSequence( "idle_suble" ); if ( seq == -1 ) seq = 0; if ( seq != oldSeq ) { Con_Printf( "Centering changed model sequence # to %d\n", seq ); } setSequence( seq ); initPoseParameters( ); mdl->m_angles.Init(); mdl->m_origin.Init(); Vector size; VectorSubtract( hdr->hull_max(), hdr->hull_min(), size ); float eyeheight = hdr->hull_min().z + 0.9 * size.z; if ( hdr->GetNumAttachments() > 0 ) { for (int i = 0; i < hdr->GetNumAttachments(); i++) { const mstudioattachment_t &attachment = hdr->pAttachment( i ); int iBone = hdr->GetAttachmentBone( i ); if ( Q_stricmp( attachment.pszName(), "eyes" ) ) continue; mstudiobone_t *bone = hdr->pBone( iBone ); if ( !bone ) continue; matrix3x4_t boneToPose; MatrixInvert( bone->poseToBone, boneToPose ); matrix3x4_t attachmentPoseToLocal; ConcatTransforms( boneToPose, attachment.local, attachmentPoseToLocal ); Vector localSpaceEyePosition; VectorITransform( vec3_origin, attachmentPoseToLocal, localSpaceEyePosition ); // Not sure why this must be negative? eyeheight = -localSpaceEyePosition.z + hdr->hull_min().z; break; } } KeyValues *seqKeyValues = new KeyValues(""); if ( seqKeyValues->LoadFromBuffer( mdl->GetFileName( ), mdl->GetKeyValueText( seq ) ) ) { // Do we have a build point section? KeyValues *pkvAllFaceposer = seqKeyValues->FindKey("faceposer"); if ( pkvAllFaceposer ) { float flEyeheight = pkvAllFaceposer->GetFloat( "eye_height", -9999.0f ); if ( flEyeheight != -9999.0f ) { eyeheight = flEyeheight; } } } seqKeyValues->deleteThis(); mdl->m_origin.x = size.z * .65f; mdl->m_origin.z += eyeheight; CUtlVector< StudioModel * > modellist; modellist.AddToTail( models->GetActiveStudioModel() ); int i; if ( models->CountVisibleModels() > 0 ) { modellist.RemoveAll(); for ( i = 0; i < models->Count(); i++ ) { if ( models->IsModelShownIn3DView( i ) ) { modellist.AddToTail( models->GetStudioModel( i ) ); } } } int modelcount = modellist.Count(); int countover2 = modelcount / 2; int ydelta = GetModelGap(); int yoffset = -countover2 * ydelta; for ( i = 0 ; i < modelcount; i++ ) { if ( models->GetStudioHeader( i ) == hdr ) { mdl->m_origin.y = -yoffset; } yoffset += ydelta; } g_pMatSysWindow->redraw(); }
bool _ComputeRagdollBones( const ragdoll_t *pRagdoll, matrix3x4_t &parentTransform, matrix3x4_t *pBones, Vector *pPositions, QAngle *pAngles ) { matrix3x4_t inverted, output; #ifdef _DEBUG CBitVec<MAXSTUDIOBONES> vBonesComputed; vBonesComputed.ClearAll(); #endif for ( int i = 0; i < pRagdoll->listCount; ++i ) { const ragdollelement_t& element = pRagdoll->list[ i ]; // during restore if a model has changed since the file was saved, this could be NULL if ( !element.pObject ) return false; int const boneIndex = pRagdoll->boneIndex[ i ]; if ( boneIndex < 0 ) { AssertMsg( 0, "Replay: No mapping for ragdoll bone\n" ); return false; } // Get global transform and put it into the bone cache element.pObject->GetPositionMatrix( &pBones[ boneIndex ] ); // Ensure a fixed translation from the parent (no stretching) if ( element.parentIndex >= 0 && !pRagdoll->allowStretch ) { int parentIndex = pRagdoll->boneIndex[ element.parentIndex ]; #ifdef _DEBUG // Make sure we computed the parent already Assert( vBonesComputed.IsBitSet(parentIndex) ); #endif // overwrite the position from physics to force rigid attachment // NOTE: On the client we actually override this with the proper parent bone in each LOD Vector out; VectorTransform( element.originParentSpace, pBones[ parentIndex ], out ); MatrixSetColumn( out, 3, pBones[ boneIndex ] ); MatrixInvert( pBones[ parentIndex ], inverted ); } else if ( element.parentIndex == - 1 ) { // Decompose into parent space MatrixInvert( parentTransform, inverted ); } #ifdef _DEBUG vBonesComputed.Set( boneIndex, true ); #endif // Compute local transform and put into 'output' ConcatTransforms( inverted, pBones[ boneIndex ], output ); // Cache as Euler/position MatrixAngles( output, pAngles[ i ], pPositions[ i ] ); } return true; }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CBaseViewModel::SpawnControlPanels() { #if defined( VGUI_CONTROL_PANELS ) char buf[64]; // Destroy existing panels DestroyControlPanels(); CBaseCombatWeapon *weapon = m_hWeapon.Get(); if ( weapon == NULL ) { return; } MDLCACHE_CRITICAL_SECTION(); // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; /* if ( IsBuiltOnAttachment() ) { pEntityToSpawnOn = dynamic_cast<CBaseAnimating*>((CBaseEntity*)m_hBuiltOnEntity.Get()); if ( pEntityToSpawnOn ) { char sBuildPointLL[64]; char sBuildPointUR[64]; Q_snprintf( sBuildPointLL, sizeof( sBuildPointLL ), "bp%d_controlpanel%%d_ll", m_iBuiltOnPoint ); Q_snprintf( sBuildPointUR, sizeof( sBuildPointUR ), "bp%d_controlpanel%%d_ur", m_iBuiltOnPoint ); pAttachmentNameLL = sBuildPointLL; pAttachmentNameUR = sBuildPointUR; } else { pEntityToSpawnOn = this; } } */ Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; weapon->GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; weapon->GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( false ); pScreen->MakeVisibleOnlyToTeammates( false ); #ifdef INVASION_DLL pScreen->SetOverlayMaterial( SCREEN_OVERLAY_MATERIAL ); #endif pScreen->SetAttachedToViewModel( true ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } #endif }
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 ) { CStudioHdr *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 ); // Exaggerate the bone's ability to pull the mass of the ragdoll around constraint.constraint.bodyMassScale[1] = 50.0f; 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 ); PhysDisableEntityCollisions( pAttached, m_ragdoll.list[0].pObject ); m_pAttachConstraint = physenv->CreateRagdollConstraint( pRefObject, pAttached, m_ragdoll.pGroup, constraint ); SetParent( pFollow ); SetOwnerEntity( pFollow ); RagdollActivate( m_ragdoll, modelinfo->GetVCollide( GetModelIndex() ), GetModelIndex() ); // add a bunch of dampening to the ragdoll for ( int i = 0; i < m_ragdoll.listCount; i++ ) { float damping, rotdamping; m_ragdoll.list[i].pObject->GetDamping( &damping, &rotdamping ); damping *= ATTACHED_DAMPING_SCALE; rotdamping *= ATTACHED_DAMPING_SCALE; m_ragdoll.list[i].pObject->SetDamping( &damping, &rotdamping ); } m_boneIndexAttached = boneIndexRoot; m_ragdollAttachedObjectIndex = ragdollAttachedIndex; m_attachmentPointBoneSpace = boneLocalOrigin; Vector vTemp; MatrixGetColumn( constraint.constraintToReference, 3, vTemp ); m_attachmentPointRagdollSpace = vTemp; }
//----------------------------------------------------------------------------- // This is called by the base object when it's time to spawn the control panels //----------------------------------------------------------------------------- void CPlantedC4::SpawnControlPanels() { char buf[64]; // FIXME: Deal with dynamically resizing control panels? // If we're attached to an entity, spawn control panels on it instead of use CBaseAnimating *pEntityToSpawnOn = this; char *pOrgLL = "controlpanel%d_ll"; char *pOrgUR = "controlpanel%d_ur"; char *pAttachmentNameLL = pOrgLL; char *pAttachmentNameUR = pOrgUR; Assert( pEntityToSpawnOn ); // Lookup the attachment point... int nPanel; for ( nPanel = 0; true; ++nPanel ) { Q_snprintf( buf, sizeof( buf ), pAttachmentNameLL, nPanel ); int nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) { // Try and use my panels then pEntityToSpawnOn = this; Q_snprintf( buf, sizeof( buf ), pOrgLL, nPanel ); nLLAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nLLAttachmentIndex <= 0) return; } Q_snprintf( buf, sizeof( buf ), pAttachmentNameUR, nPanel ); int nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) { // Try and use my panels then Q_snprintf( buf, sizeof( buf ), pOrgUR, nPanel ); nURAttachmentIndex = pEntityToSpawnOn->LookupAttachment(buf); if (nURAttachmentIndex <= 0) return; } const char *pScreenName; GetControlPanelInfo( nPanel, pScreenName ); if (!pScreenName) continue; const char *pScreenClassname; GetControlPanelClassName( nPanel, pScreenClassname ); if ( !pScreenClassname ) continue; // Compute the screen size from the attachment points... matrix3x4_t panelToWorld; pEntityToSpawnOn->GetAttachment( nLLAttachmentIndex, panelToWorld ); matrix3x4_t worldToPanel; MatrixInvert( panelToWorld, worldToPanel ); // Now get the lower right position + transform into panel space Vector lr, lrlocal; pEntityToSpawnOn->GetAttachment( nURAttachmentIndex, panelToWorld ); MatrixGetColumn( panelToWorld, 3, lr ); VectorTransform( lr, worldToPanel, lrlocal ); float flWidth = lrlocal.x; float flHeight = lrlocal.y; CVGuiScreen *pScreen = CreateVGuiScreen( pScreenClassname, pScreenName, pEntityToSpawnOn, this, nLLAttachmentIndex ); pScreen->ChangeTeam( GetTeamNumber() ); pScreen->SetActualSize( flWidth, flHeight ); pScreen->SetActive( true ); pScreen->MakeVisibleOnlyToTeammates( false ); int nScreen = m_hScreens.AddToTail( ); m_hScreens[nScreen].Set( pScreen ); } }