diff --git a/engine/client/ref_common.c b/engine/client/ref_common.c index 71cbd87c..a736f51f 100644 --- a/engine/client/ref_common.c +++ b/engine/client/ref_common.c @@ -278,9 +278,6 @@ static ref_api_t gEngfuncs = Mod_PointInLeaf, Mod_CreatePolygonsForHull, - R_StudioSlerpBones, - R_StudioCalcBoneQuaternion, - R_StudioCalcBonePosition, R_StudioGetAnim, pfnStudioEvent, diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index 16c29531..3dcf50dc 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -182,9 +182,6 @@ qboolean Mod_GetStudioBounds( const char *name, vec3_t mins, vec3_t maxs ); void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *org, float *ang ); void Mod_GetBonePosition( const edict_t *e, int iBone, float *org, float *ang ); hull_t *Mod_HullForStudio( model_t *m, float frame, int seq, vec3_t ang, vec3_t org, vec3_t size, byte *pcnt, byte *pbl, int *hitboxes, edict_t *ed ); -void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ); -void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q ); -void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, vec3_t adj, vec3_t pos ); void *R_StudioGetAnim( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc ); void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean ignore_sequences ); int Mod_HitgroupForStudioHull( int index ); diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index 56f241ae..251c9a0c 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -397,196 +397,6 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f; } -/* -==================== -StudioCalcBoneQuaternion - -==================== -*/ -void R_StudioCalcBoneQuaternion( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q ) -{ - vec3_t angles1; - vec3_t angles2; - int j, k; - - for( j = 0; j < 3; j++ ) - { - if( !panim || panim->offset[j+3] == 0 ) - { - angles2[j] = angles1[j] = pbone->value[j+3]; // default; - } - else - { - mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); - - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - - // find span of values that includes the frame we want - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // bah, missing blend! - if( panimvalue->num.valid > k ) - { - angles1[j] = panimvalue[k+1].value; - - if( panimvalue->num.valid > k + 1 ) - { - angles2[j] = panimvalue[k+2].value; - } - else - { - if( panimvalue->num.total > k + 1 ) - angles2[j] = angles1[j]; - else angles2[j] = panimvalue[panimvalue->num.valid+2].value; - } - } - else - { - angles1[j] = panimvalue[panimvalue->num.valid].value; - if( panimvalue->num.total > k + 1 ) - angles2[j] = angles1[j]; - else angles2[j] = panimvalue[panimvalue->num.valid+2].value; - } - - angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3]; - angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3]; - } - - if( pbone->bonecontroller[j+3] != -1 && adj != NULL ) - { - angles1[j] += adj[pbone->bonecontroller[j+3]]; - angles2[j] += adj[pbone->bonecontroller[j+3]]; - } - } - - if( !VectorCompare( angles1, angles2 )) - { - vec4_t q1, q2; - - AngleQuaternion( angles1, q1, true ); - AngleQuaternion( angles2, q2, true ); - QuaternionSlerp( q1, q2, s, q ); - } - else - { - AngleQuaternion( angles1, q, true ); - } -} - -/* -==================== -StudioCalcBonePosition - -==================== -*/ -void R_StudioCalcBonePosition( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec3_t pos ) -{ - vec3_t origin1; - vec3_t origin2; - int j, k; - - for( j = 0; j < 3; j++ ) - { - if( !panim || panim->offset[j] == 0 ) - { - origin2[j] = origin1[j] = pbone->value[j]; // default; - } - else - { - mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); - - k = frame; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - - // find span of values that includes the frame we want - while( panimvalue->num.total <= k ) - { - k -= panimvalue->num.total; - panimvalue += panimvalue->num.valid + 1; - - // debug - if( panimvalue->num.total < panimvalue->num.valid ) - k = 0; - } - - // bah, missing blend! - if( panimvalue->num.valid > k ) - { - origin1[j] = panimvalue[k+1].value; - - if( panimvalue->num.valid > k + 1 ) - { - origin2[j] = panimvalue[k+2].value; - } - else - { - if( panimvalue->num.total > k + 1 ) - origin2[j] = origin1[j]; - else origin2[j] = panimvalue[panimvalue->num.valid+2].value; - } - } - else - { - origin1[j] = panimvalue[panimvalue->num.valid].value; - if( panimvalue->num.total > k + 1 ) - origin2[j] = origin1[j]; - else origin2[j] = panimvalue[panimvalue->num.valid+2].value; - } - - origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j]; - origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j]; - } - - if( pbone->bonecontroller[j] != -1 && adj != NULL ) - { - origin1[j] += adj[pbone->bonecontroller[j]]; - origin2[j] += adj[pbone->bonecontroller[j]]; - } - } - - if( !VectorCompare( origin1, origin2 )) - { - VectorLerp( origin1, s, origin2, pos ); - } - else - { - VectorCopy( origin1, pos ); - } -} - -/* -==================== -StudioSlerpBones - -==================== -*/ -void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ) -{ - int i; - - s = bound( 0.0f, s, 1.0f ); - - for( i = 0; i < numbones; i++ ) - { - QuaternionSlerp( q1[i], q2[i], s, q1[i] ); - VectorLerp( pos1[i], s, pos2[i], pos1[i] ); - } -} /* ==================== diff --git a/engine/ref_api.h b/engine/ref_api.h index 3c14b719..1ac5adcb 100644 --- a/engine/ref_api.h +++ b/engine/ref_api.h @@ -32,7 +32,8 @@ GNU General Public License for more details. // RefAPI changelog: // 1. Initial release // 2. FS functions are removed, instead we have full fs_api_t -#define REF_API_VERSION 2 +// 3. SlerpBones, CalcBonePosition/Quaternion calls were moved to libpublic/mathlib +#define REF_API_VERSION 3 #define TF_SKY (TF_SKYSIDE|TF_NOMIPMAP) @@ -312,9 +313,6 @@ typedef struct ref_api_s void (*Mod_CreatePolygonsForHull)( int hullnum ); // studio models - void (*R_StudioSlerpBones)( int numbones, vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s ); - void (*R_StudioCalcBoneQuaternion)( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, float *adj, vec4_t q ); - void (*R_StudioCalcBonePosition)( int frame, float s, mstudiobone_t *pbone, mstudioanim_t *panim, vec3_t adj, vec3_t pos ); void *(*R_StudioGetAnim)( studiohdr_t *m_pStudioHeader, model_t *m_pSubModel, mstudioseqdesc_t *pseqdesc ); void (*pfnStudioEvent)( const struct mstudioevent_s *event, const cl_entity_t *entity ); diff --git a/public/xash3d_mathlib.c b/public/xash3d_mathlib.c index 2fd8f705..39dc3089 100644 --- a/public/xash3d_mathlib.c +++ b/public/xash3d_mathlib.c @@ -872,3 +872,193 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ) return sides; } +/* +==================== +StudioSlerpBones + +==================== +*/ +void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], const vec4_t q2[], const float pos2[][3], float s ) +{ + int i; + + s = bound( 0.0f, s, 1.0f ); + + for( i = 0; i < numbones; i++ ) + { + QuaternionSlerp( q1[i], q2[i], s, q1[i] ); + VectorLerp( pos1[i], s, pos2[i], pos1[i] ); + } +} + +/* +==================== +StudioCalcBoneQuaternion + +==================== +*/ +void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q ) +{ + vec3_t angles1; + vec3_t angles2; + int j, k; + + for( j = 0; j < 3; j++ ) + { + if( !panim || panim->offset[j+3] == 0 ) + { + angles2[j] = angles1[j] = pbone->value[j+3]; // default; + } + else + { + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); + + k = frame; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + + // find span of values that includes the frame we want + while( panimvalue->num.total <= k ) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + } + + // bah, missing blend! + if( panimvalue->num.valid > k ) + { + angles1[j] = panimvalue[k+1].value; + + if( panimvalue->num.valid > k + 1 ) + { + angles2[j] = panimvalue[k+2].value; + } + else + { + if( panimvalue->num.total > k + 1 ) + angles2[j] = angles1[j]; + else angles2[j] = panimvalue[panimvalue->num.valid+2].value; + } + } + else + { + angles1[j] = panimvalue[panimvalue->num.valid].value; + if( panimvalue->num.total > k + 1 ) + angles2[j] = angles1[j]; + else angles2[j] = panimvalue[panimvalue->num.valid+2].value; + } + + angles1[j] = pbone->value[j+3] + angles1[j] * pbone->scale[j+3]; + angles2[j] = pbone->value[j+3] + angles2[j] * pbone->scale[j+3]; + } + + if( pbone->bonecontroller[j+3] != -1 && adj != NULL ) + { + angles1[j] += adj[pbone->bonecontroller[j+3]]; + angles2[j] += adj[pbone->bonecontroller[j+3]]; + } + } + + if( !VectorCompare( angles1, angles2 )) + { + vec4_t q1, q2; + + AngleQuaternion( angles1, q1, true ); + AngleQuaternion( angles2, q2, true ); + QuaternionSlerp( q1, q2, s, q ); + } + else + { + AngleQuaternion( angles1, q, true ); + } +} + +/* +==================== +StudioCalcBonePosition + +==================== +*/ +void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos ) +{ + vec3_t origin1; + vec3_t origin2; + int j, k; + + for( j = 0; j < 3; j++ ) + { + if( !panim || panim->offset[j] == 0 ) + { + origin2[j] = origin1[j] = pbone->value[j]; // default; + } + else + { + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]); + + k = frame; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + + // find span of values that includes the frame we want + while( panimvalue->num.total <= k ) + { + k -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + // debug + if( panimvalue->num.total < panimvalue->num.valid ) + k = 0; + } + + // bah, missing blend! + if( panimvalue->num.valid > k ) + { + origin1[j] = panimvalue[k+1].value; + + if( panimvalue->num.valid > k + 1 ) + { + origin2[j] = panimvalue[k+2].value; + } + else + { + if( panimvalue->num.total > k + 1 ) + origin2[j] = origin1[j]; + else origin2[j] = panimvalue[panimvalue->num.valid+2].value; + } + } + else + { + origin1[j] = panimvalue[panimvalue->num.valid].value; + if( panimvalue->num.total > k + 1 ) + origin2[j] = origin1[j]; + else origin2[j] = panimvalue[panimvalue->num.valid+2].value; + } + + origin1[j] = pbone->value[j] + origin1[j] * pbone->scale[j]; + origin2[j] = pbone->value[j] + origin2[j] * pbone->scale[j]; + } + + if( pbone->bonecontroller[j] != -1 && adj != NULL ) + { + origin1[j] += adj[pbone->bonecontroller[j]]; + origin2[j] += adj[pbone->bonecontroller[j]]; + } + } + + if( !VectorCompare( origin1, origin2 )) + { + VectorLerp( origin1, s, origin2, pos ); + } + else + { + VectorCopy( origin1, pos ); + } +} diff --git a/public/xash3d_mathlib.h b/public/xash3d_mathlib.h index 259c79fb..02c10c3e 100644 --- a/public/xash3d_mathlib.h +++ b/public/xash3d_mathlib.h @@ -23,6 +23,7 @@ GNU General Public License for more details. #include "build.h" #include "com_model.h" +#include "studio.h" // euler angle order #define PITCH 0 @@ -210,6 +211,10 @@ qboolean Matrix4x4_Invert_Full( matrix4x4 out, const matrix4x4 in1 ); float V_CalcFov( float *fov_x, float width, float height ); void V_AdjustFov( float *fov_x, float *fov_y, float width, float height, qboolean lock_x ); +void R_StudioSlerpBones( int numbones, vec4_t q1[], float pos1[][3], const vec4_t q2[], const float pos2[][3], float s ); +void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q ); +void R_StudioCalcBonePosition( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const vec3_t adj, vec3_t pos ); + int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ); #define BOX_ON_PLANE_SIDE( emins, emaxs, p ) \ ((( p )->type < 3 ) ? \ diff --git a/ref/gl/gl_studio.c b/ref/gl/gl_studio.c index af117914..1c0aa6a4 100644 --- a/ref/gl/gl_studio.c +++ b/ref/gl/gl_studio.c @@ -847,8 +847,8 @@ void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, mstudiose for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) { - gEngfuncs.R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); - gEngfuncs.R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); + R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); + R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); } if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; @@ -960,7 +960,7 @@ void R_StudioSetupBones( cl_entity_t *e ) dadt = R_StudioEstimateInterpolant( e ); s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q2, pos2, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q2, pos2, s ); if( pseqdesc->numblends == 4 ) { @@ -971,10 +971,10 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f ); s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); s = (e->curstate.blending[1] * dadt + e->latched.prevblending[1] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q3, pos3, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q3, pos3, s ); } } @@ -997,7 +997,7 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, e->latched.prevframe ); s = (e->latched.prevseqblending[0]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q2, pos2, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q2, pos2, s ); if( pseqdesc->numblends == 4 ) { @@ -1008,15 +1008,15 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, e->latched.prevframe ); s = (e->latched.prevseqblending[0]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); s = (e->latched.prevseqblending[1]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q3, pos3, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q3, pos3, s ); } } s = 1.0f - ( g_studio.time - e->latched.sequencetime ) / 0.2f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q1b, pos1b, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q1b, pos1b, s ); } else { diff --git a/ref/soft/r_studio.c b/ref/soft/r_studio.c index a678715b..e3df3fa3 100644 --- a/ref/soft/r_studio.c +++ b/ref/soft/r_studio.c @@ -843,8 +843,8 @@ void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, mstudiose for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) { - gEngfuncs.R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); - gEngfuncs.R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); + R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); + R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); } if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; @@ -956,7 +956,7 @@ void R_StudioSetupBones( cl_entity_t *e ) dadt = R_StudioEstimateInterpolant( e ); s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q2, pos2, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q2, pos2, s ); if( pseqdesc->numblends == 4 ) { @@ -967,10 +967,10 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f ); s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); s = (e->curstate.blending[1] * dadt + e->latched.prevblending[1] * (1.0f - dadt)) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q3, pos3, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q3, pos3, s ); } } @@ -993,7 +993,7 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, e->latched.prevframe ); s = (e->latched.prevseqblending[0]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q2, pos2, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q2, pos2, s ); if( pseqdesc->numblends == 4 ) { @@ -1004,15 +1004,15 @@ void R_StudioSetupBones( cl_entity_t *e ) R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, e->latched.prevframe ); s = (e->latched.prevseqblending[0]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); s = (e->latched.prevseqblending[1]) / 255.0f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q3, pos3, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q3, pos3, s ); } } s = 1.0f - ( g_studio.time - e->latched.sequencetime ) / 0.2f; - gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q1b, pos1b, s ); + R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q1b, pos1b, s ); } else {