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]; }
/* ==================== 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]); } } }
/* ==================== 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]; } }