void CStudioModelRenderer::StudioCalcRotations(float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f) { int i; int frame; mstudiobone_t *pbone; float s; float adj[MAXSTUDIOCONTROLLERS]; float dadt; if (f > pseqdesc->numframes - 1) f = 0; else if (f < -0.01) f = -0.01; frame = (int)f; dadt = StudioEstimateInterpolant(); s = (f - frame); pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); StudioCalcBoneAdj(dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen); for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++) { StudioCalcBoneQuaterion(frame, s, pbone, panim, adj, q[i]); StudioCalcBonePosition(frame, s, pbone, panim, adj, pos[i]); } if (pseqdesc->motiontype & STUDIO_X) pos[pseqdesc->motionbone][0] = 0.0; if (pseqdesc->motiontype & STUDIO_Y) pos[pseqdesc->motionbone][1] = 0.0; if (pseqdesc->motiontype & STUDIO_Z) pos[pseqdesc->motionbone][2] = 0.0; s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate; if (pseqdesc->motiontype & STUDIO_LX) pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0]; if (pseqdesc->motiontype & STUDIO_LY) pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1]; if (pseqdesc->motiontype & STUDIO_LZ) pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2]; }
/* ==================== StudioCalcRotations ==================== */ void CStudioModelRenderer::StudioCalcRotations ( float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f ) { int i; int frame; mstudiobone_t *pbone; float s; float adj[MAXSTUDIOCONTROLLERS]; float dadt; if (f > pseqdesc->numframes - 1) { f = 0; // bah, fix this bug with changing sequences too fast } // BUG ( somewhere else ) but this code should validate this data. // This could cause a crash if the frame # is negative, so we'll go ahead // and clamp it here else if ( f < -0.01 ) { f = -0.01; } frame = (int)f; // Con_DPrintf("%d %.4f %.4f %.4f %.4f %d\n", m_pCurrentEntity->curstate.sequence, m_clTime, m_pCurrentEntity->animtime, m_pCurrentEntity->frame, f, frame ); // Con_DPrintf( "%f %f %f\n", m_pCurrentEntity->angles[ROLL], m_pCurrentEntity->angles[PITCH], m_pCurrentEntity->angles[YAW] ); // Con_DPrintf("frame %d %d\n", frame1, frame2 ); dadt = StudioEstimateInterpolant( ); s = (f - frame); // add in programtic controllers pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); StudioCalcBoneAdj( dadt, adj, m_pCurrentEntity->curstate.controller, m_pCurrentEntity->latched.prevcontroller, m_pCurrentEntity->mouth.mouthopen ); for (i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++) { StudioCalcBoneQuaterion( frame, s, pbone, panim, adj, q[i] ); StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); // if (0 && i == 0) // Con_DPrintf("%d %d %d %d\n", m_pCurrentEntity->curstate.sequence, frame, j, k ); } if (pseqdesc->motiontype & STUDIO_X) { pos[pseqdesc->motionbone][0] = 0.0; } if (pseqdesc->motiontype & STUDIO_Y) { pos[pseqdesc->motionbone][1] = 0.0; } if (pseqdesc->motiontype & STUDIO_Z) { pos[pseqdesc->motionbone][2] = 0.0; } s = 0 * ((1.0 - (f - (int)(f))) / (pseqdesc->numframes)) * m_pCurrentEntity->curstate.framerate; if (pseqdesc->motiontype & STUDIO_LX) { pos[pseqdesc->motionbone][0] += s * pseqdesc->linearmovement[0]; } if (pseqdesc->motiontype & STUDIO_LY) { pos[pseqdesc->motionbone][1] += s * pseqdesc->linearmovement[1]; } if (pseqdesc->motiontype & STUDIO_LZ) { pos[pseqdesc->motionbone][2] += s * pseqdesc->linearmovement[2]; } }
/* <16247> ../cstrike/dlls/animation.cpp:1115 */ void SV_StudioSetupBones(model_t *pModel, float frame, int sequence, const vec_t *angles, const vec_t *origin, const byte *pcontroller, const byte *pblending, int iBone, const edict_t *pEdict) { int i, j; float_precision f; float subframe; float adj[MAXSTUDIOCONTROLLERS]; mstudiobone_t *pbones; mstudioseqdesc_t *pseqdesc; mstudioanim_t *panim; float bonematrix[3][4]; int chain[MAXSTUDIOBONES]; int chainlength; vec3_t temp_angles; static float pos[MAXSTUDIOBONES][3], pos2[MAXSTUDIOBONES][3]; static float q[MAXSTUDIOBONES][4], q2[MAXSTUDIOBONES][4]; g_pstudiohdr = (studiohdr_t *)IEngineStudio.Mod_Extradata(pModel); // Bound sequence number if (sequence < 0 || sequence >= g_pstudiohdr->numseq) sequence = 0; pbones = (mstudiobone_t *)((byte *)g_pstudiohdr + g_pstudiohdr->boneindex); pseqdesc = (mstudioseqdesc_t *)((byte *)g_pstudiohdr + g_pstudiohdr->seqindex) + sequence; panim = StudioGetAnim(pModel, pseqdesc); if (iBone < -1 || iBone >= g_pstudiohdr->numbones) iBone = 0; if (iBone == -1) { chainlength = g_pstudiohdr->numbones; for (i = 0; i < chainlength; i++) chain[(chainlength - i) - 1] = i; } else { chainlength = 0; for (i = iBone; i != -1; i = pbones[i].parent) chain[chainlength++] = i; } f = StudioEstimateFrame(frame, pseqdesc); subframe = (int)f; f -= subframe; StudioCalcBoneAdj(0, adj, pcontroller, pcontroller, 0); StudioCalcRotations(pbones, chain, chainlength, adj, pos, q, pseqdesc, panim, subframe, f); if (pseqdesc->numblends != 9) { if (pseqdesc->numblends > 1) { float b = (float_precision)pblending[0] / 255.0f; pseqdesc = (mstudioseqdesc_t *)((byte *)g_pstudiohdr + g_pstudiohdr->seqindex) + sequence; panim = StudioGetAnim(pModel, pseqdesc); panim += g_pstudiohdr->numbones; StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, subframe, f); StudioSlerpBones(q, pos, q2, pos2, b); } } // This game knows how to do nine way blending else { static float pos3[MAXSTUDIOBONES][3], pos4[MAXSTUDIOBONES][3]; static float q3[MAXSTUDIOBONES][4], q4[MAXSTUDIOBONES][4]; float_precision s, t; s = GetPlayerYaw(pEdict); t = GetPlayerPitch(pEdict); // Blending is 0-127 == Left to Middle, 128 to 255 == Middle to right if (s <= 127.0f) { // Scale 0-127 blending up to 0-255 s = (s * 2.0f); if (t <= 127.0f) { t = (t * 2.0f); StudioCalcRotations(pbones, chain, chainlength, adj, pos, q, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 1); StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 3); StudioCalcRotations(pbones, chain, chainlength, adj, pos3, q3, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 4); StudioCalcRotations(pbones, chain, chainlength, adj, pos4, q4, pseqdesc, panim, subframe, f); } else { t = 2.0f * (t - 127.0f); panim = LookupAnimation(pModel, pseqdesc, 3); StudioCalcRotations(pbones, chain, chainlength, adj, pos, q, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 4); StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 6); StudioCalcRotations(pbones, chain, chainlength, adj, pos3, q3, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 7); StudioCalcRotations(pbones, chain, chainlength, adj, pos4, q4, pseqdesc, panim, subframe, f); } } else { // Scale 127-255 blending up to 0-255 s = 2.0f * (s - 127.0f); if (t <= 127.0f) { t = (t * 2.0f); panim = LookupAnimation(pModel, pseqdesc, 1); StudioCalcRotations(pbones, chain, chainlength, adj, pos, q, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 2); StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 4); StudioCalcRotations(pbones, chain, chainlength, adj, pos3, q3, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 5); StudioCalcRotations(pbones, chain, chainlength, adj, pos4, q4, pseqdesc, panim, subframe, f); } else { t = 2.0f * (t - 127.0f); panim = LookupAnimation(pModel, pseqdesc, 4); StudioCalcRotations(pbones, chain, chainlength, adj, pos, q, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 5); StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 7); StudioCalcRotations(pbones, chain, chainlength, adj, pos3, q3, pseqdesc, panim, subframe, f); panim = LookupAnimation(pModel, pseqdesc, 8); StudioCalcRotations(pbones, chain, chainlength, adj, pos4, q4, pseqdesc, panim, subframe, f); } } // Normalize interpolant s /= 255.0f; t /= 255.0f; // Spherically interpolate the bones StudioSlerpBones(q, pos, q2, pos2, s); StudioSlerpBones(q3, pos3, q4, pos4, s); StudioSlerpBones(q, pos, q3, pos3, t); } if (pseqdesc->numblends == 9 && sequence < ANIM_FIRST_DEATH_SEQUENCE && sequence != ANIM_SWIM_1 && sequence != ANIM_SWIM_2) { int copy = 1; int gaitsequence = GetPlayerGaitsequence(pEdict); // calc gait animation if (gaitsequence < 0 || gaitsequence >= g_pstudiohdr->numseq) gaitsequence = 0; pseqdesc = (mstudioseqdesc_t *)((byte *)g_pstudiohdr + g_pstudiohdr->seqindex) + gaitsequence; panim = StudioGetAnim(pModel, pseqdesc); StudioCalcRotations(pbones, chain, chainlength, adj, pos2, q2, pseqdesc, panim, 0, 0); for (i = 0; i < g_pstudiohdr->numbones; i++) { if (!Q_strcmp(pbones[i].name, "Bip01 Spine")) { copy = 0; } else if (!Q_strcmp(pbones[pbones[i].parent].name, "Bip01 Pelvis")) { copy = 1; } if (copy) { Q_memcpy(pos[i], pos2[i], sizeof(pos[i])); Q_memcpy(q[i], q2[i], sizeof(q[i])); } } } VectorCopy(angles, temp_angles); if (pEdict != NULL) { temp_angles[1] = UTIL_GetPlayerGaitYaw(ENTINDEX(pEdict)); if (temp_angles[1] < 0) temp_angles[1] += 360.0f; } AngleMatrix(temp_angles, (*g_pRotationMatrix)); (*g_pRotationMatrix)[0][3] = origin[0]; (*g_pRotationMatrix)[1][3] = origin[1]; (*g_pRotationMatrix)[2][3] = origin[2]; for (i = chainlength - 1; i >= 0; i--) { j = chain[i]; QuaternionMatrix(q[j], bonematrix); bonematrix[0][3] = pos[j][0]; bonematrix[1][3] = pos[j][1]; bonematrix[2][3] = pos[j][2]; if (pbones[j].parent == -1) ConcatTransforms((*g_pRotationMatrix), bonematrix, (*g_pBoneTransform)[j]); else ConcatTransforms((*g_pBoneTransform)[pbones[j].parent], bonematrix, (*g_pBoneTransform)[j]); } }