/* ==================== 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]); } } }
/* ==================== StudioSetupBones ==================== */ void CGameStudioModelRenderer::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]; // Use default bone setup for nonplayers if(!m_pCurrentEntity->player) { CStudioModelRenderer::StudioSetupBones(); return; } // Bound sequence number. 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; if(m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0) { f = m_pPlayerInfo->gaitframe; } else { f = StudioEstimateFrame(pseqdesc); } // This game knows how to do three way blending if(pseqdesc->numblends == 3) { float s; // Get left anim panim = StudioGetAnim(m_pRenderModel, pseqdesc); // Blending is 0-127 == Left to Middle, 128 to 255 == Middle to right if(m_pCurrentEntity->curstate.blending[0] <= 127) { StudioCalcRotations(pos, q, pseqdesc, panim, f); // Scale 0-127 blending up to 0-255 s = m_pCurrentEntity->curstate.blending[0]; s = (s * 2.0); } else { // Skip ahead to middle panim += m_pStudioHeader->numbones; StudioCalcRotations(pos, q, pseqdesc, panim, f); // Scale 127-255 blending up to 0-255 s = m_pCurrentEntity->curstate.blending[0]; s = 2.0 * (s - 127.0); } // Normalize interpolant s /= 255.0; // Go to middle or right panim += m_pStudioHeader->numbones; StudioCalcRotations(pos2, q2, pseqdesc, panim, f); // Spherically interpolate the bones StudioSlerpBones(q, pos, q2, pos2, s); } else { panim = StudioGetAnim(m_pRenderModel, pseqdesc); StudioCalcRotations(pos, q, pseqdesc, panim, f); } // Are we in the process of transitioning from one sequence to another. 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; // Blending value into last sequence unsigned char prevseqblending = m_pCurrentEntity->latched.prevseqblending[0]; // Point at previous sequenece pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; // Know how to do three way blends if(pseqdesc->numblends == 3) { float s; // Get left animation panim = StudioGetAnim(m_pRenderModel, pseqdesc); if(prevseqblending <= 127) { // Set up bones based on final frame of previous sequence StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); s = prevseqblending; s = (s * 2.0); } else { // Skip to middle blend panim += m_pStudioHeader->numbones; StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); s = prevseqblending; s = 2.0 * (s - 127.0); } // Normalize s /= 255.0; panim += m_pStudioHeader->numbones; StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); // Interpolate bones StudioSlerpBones(q1b, pos1b, q2, pos2, s); } else { panim = StudioGetAnim(m_pRenderModel, pseqdesc); // clip prevframe StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } // Now blend last frame of previous sequence with current sequence. s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; StudioSlerpBones(q, pos, q1b, pos1b, s); } else { m_pCurrentEntity->latched.prevframe = f; } // Now convert quaternions and bone positions into matrices pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); 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]); ConcatTransforms((*m_protationmatrix), bonematrix, (*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]); } } }
void CGameStudioModelRenderer::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->player) { CStudioModelRenderer::StudioSetupBones(); return; } 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; panim = StudioGetAnim(m_pRenderModel, pseqdesc); f = StudioEstimateFrame(pseqdesc); if (m_pPlayerInfo->gaitsequence == ANIM_WALK_SEQUENCE) { if (m_pCurrentEntity->curstate.blending[0] <= 26) { m_pCurrentEntity->curstate.blending[0] = 0; m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; } else { m_pCurrentEntity->curstate.blending[0] -= 26; m_pCurrentEntity->latched.prevseqblending[0] = m_pCurrentEntity->curstate.blending[0]; } } if (pseqdesc->numblends == 9) { float s = m_pCurrentEntity->curstate.blending[0]; float t = m_pCurrentEntity->curstate.blending[1]; if (s <= 127.0) { s = (s * 2.0); if (t <= 127.0) { t = (t * 2.0); StudioCalcRotations(pos, q, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 1); StudioCalcRotations(pos2, q2, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 3); StudioCalcRotations(pos3, q3, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos4, q4, pseqdesc, panim, f); } else { t = 2.0 * (t - 127.0); panim = LookupAnimation(pseqdesc, 3); StudioCalcRotations(pos, q, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos2, q2, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 6); StudioCalcRotations(pos3, q3, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 7); StudioCalcRotations(pos4, q4, pseqdesc, panim, f); } } else { s = 2.0 * (s - 127.0); if (t <= 127.0) { t = (t * 2.0); panim = LookupAnimation(pseqdesc, 1); StudioCalcRotations(pos, q, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 2); StudioCalcRotations(pos2, q2, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos3, q3, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 5); StudioCalcRotations(pos4, q4, pseqdesc, panim, f); } else { t = 2.0 * (t - 127.0); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos, q, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 5); StudioCalcRotations(pos2, q2, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 7); StudioCalcRotations(pos3, q3, pseqdesc, panim, f); panim = LookupAnimation(pseqdesc, 8); StudioCalcRotations(pos4, q4, pseqdesc, panim, f); } } s /= 255.0; t /= 255.0; StudioSlerpBones(q, pos, q2, pos2, s); StudioSlerpBones(q3, pos3, q4, pos4, s); StudioSlerpBones(q, pos, q3, pos3, t); } else { StudioCalcRotations(pos, q, pseqdesc, panim, f); } if (m_fDoInterp && m_pCurrentEntity->latched.sequencetime && (m_pCurrentEntity->latched.sequencetime + 0.2 > m_clTime) && (m_pCurrentEntity->latched.prevsequence < m_pStudioHeader->numseq)) { static float pos1b[MAXSTUDIOBONES][3]; static vec4_t q1b[MAXSTUDIOBONES]; float s = m_pCurrentEntity->latched.prevseqblending[0]; float t = m_pCurrentEntity->latched.prevseqblending[1]; pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->latched.prevsequence; panim = StudioGetAnim(m_pRenderModel, pseqdesc); if (pseqdesc->numblends == 9) { if (s <= 127.0) { s = (s * 2.0); if (t <= 127.0) { t = (t * 2.0); StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 1); StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 3); StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } else { t = 2.0 * (t - 127.0); panim = LookupAnimation(pseqdesc, 3); StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 6); StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 7); StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } } else { s = 2.0 * (s - 127.0); if (t <= 127.0) { t = (t * 2.0); panim = LookupAnimation(pseqdesc, 1); StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 2); StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 5); StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } else { t = 2.0 * (t - 127.0); panim = LookupAnimation(pseqdesc, 4); StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 5); StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 7); StudioCalcRotations(pos3, q3, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); panim = LookupAnimation(pseqdesc, 8); StudioCalcRotations(pos4, q4, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } } s /= 255.0; t /= 255.0; StudioSlerpBones(q1b, pos1b, q2, pos2, s); StudioSlerpBones(q3, pos3, q4, pos4, s); StudioSlerpBones(q1b, pos1b, q3, pos3, t); } else { StudioCalcRotations(pos1b, q1b, pseqdesc, panim, m_pCurrentEntity->latched.prevframe); } s = 1.0 - (m_clTime - m_pCurrentEntity->latched.sequencetime) / 0.2; StudioSlerpBones(q, pos, q1b, pos1b, s); } else { m_pCurrentEntity->latched.prevframe = f; } pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); if (m_pPlayerInfo && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_DEATH_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_DEATH_SEQUENCE) && (m_pCurrentEntity->curstate.sequence < ANIM_FIRST_EMOTION_SEQUENCE || m_pCurrentEntity->curstate.sequence > ANIM_LAST_EMOTION_SEQUENCE) && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_1 && m_pCurrentEntity->curstate.sequence != ANIM_SWIM_2) { int copy = 1; 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")) copy = 0; else if (!strcmp(pbones[pbones[i].parent].name, "Bip01 Pelvis")) copy = 1; if (copy) { 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((*m_pbonetransform)[i], (*m_plighttransform)[i]); } else { ConcatTransforms((*m_paliastransform), bonematrix, (*m_pbonetransform)[i]); ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]); } 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]); } } }
/* <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]); } }