diff --git a/engine/common/mod_studio.c b/engine/common/mod_studio.c index cc5fb544..718ec8cd 100644 --- a/engine/common/mod_studio.c +++ b/engine/common/mod_studio.c @@ -382,8 +382,7 @@ static void Mod_StudioCalcRotations( int boneused[], int numbones, const byte *p for( j = numbones - 1; j >= 0; j-- ) { i = boneused[j]; - R_StudioCalcBoneQuaternion( frame, s, &pbone[i], &panim[i], adj, q[i] ); - R_StudioCalcBonePosition( frame, s, &pbone[i], &panim[i], adj, pos[i] ); + R_StudioCalcBones( frame, s, &pbone[i], &panim[i], adj, pos[i], q[i] ); } if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; @@ -724,7 +723,7 @@ void Mod_StudioComputeBounds( void *buffer, vec3_t mins, vec3_t maxs, qboolean i { for( k = 0; k < pseqdesc->numframes; k++ ) { - R_StudioCalcBonePosition( k, 0, &pbones[j], panim, NULL, pos ); + R_StudioCalcBones( k, 0, &pbones[i], panim, NULL, pos, NULL ); Mod_StudioBoundVertex( vert_mins, vert_maxs, &bone_count, pos ); } } diff --git a/public/xash3d_mathlib.c b/public/xash3d_mathlib.c index 6a608887..a499dc49 100644 --- a/public/xash3d_mathlib.c +++ b/public/xash3d_mathlib.c @@ -453,174 +453,83 @@ int BoxOnPlaneSide( const vec3_t emins, const vec3_t emaxs, const mplane_t *p ) return sides; } -/* -==================== -StudioCalcBoneQuaternion - -==================== -*/ -void R_StudioCalcBoneQuaternion( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec4_t q ) +void R_StudioCalcBones( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos, vec4_t q ) { - vec3_t angles1; - vec3_t angles2; - int j, k; + float v1[6], v2[6]; + int i, max; - for( j = 0; j < 3; j++ ) + max = q != NULL ? 6 : 3; + + for( ; i < max; i++ ) { - if( !panim || panim->offset[j+3] == 0 ) + mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[i] ); + int j = frame; + float fadj = 0.0f; + + if( pbone->bonecontroller[i] >= 0 && adj != NULL ) + fadj = adj[pbone->bonecontroller[i]]; + + if( panim->offset[i] == 0 ) { - angles2[j] = angles1[j] = pbone->value[j+3]; // default; + v1[i] = v2[i] = pbone->value[i] + fadj; + continue; + } + + if( panimvalue->num.total < panimvalue->num.valid ) + j = 0; + + while( panimvalue->num.total <= j ) + { + j -= panimvalue->num.total; + panimvalue += panimvalue->num.valid + 1; + + if( panimvalue->num.total < panimvalue->num.valid ) + j = 0; + } + + if( panimvalue->num.valid > j ) + { + v1[i] = panimvalue[j + 1].value; + + if( panimvalue->num.valid > j + 1 ) + v2[i] = panimvalue[j + 2].value; + else if( panimvalue->num.total > j + 1 ) + v2[i] = v1[i]; + else + v2[i] = panimvalue[panimvalue->num.valid + 2].value; } else { - mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]); + v1[i] = panimvalue[panimvalue->num.valid].value; - 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; - } - } + if( panimvalue->num.total > j + 1 ) + v2[i] = v1[i]; 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]; + v2[i] = panimvalue[panimvalue->num.valid + 2].value; } - if( pbone->bonecontroller[j+3] != -1 && adj != NULL ) - { - angles1[j] += adj[pbone->bonecontroller[j+3]]; - angles2[j] += adj[pbone->bonecontroller[j+3]]; - } + v1[i] = pbone->value[i] + v1[i] * pbone->scale[i] + fadj; + v2[i] = pbone->value[i] + v2[i] * pbone->scale[i] + fadj; } - if( !VectorCompare( angles1, angles2 )) - { - vec4_t q1, q2; - - AngleQuaternion( angles1, q1, true ); - AngleQuaternion( angles2, q2, true ); - QuaternionSlerp( q1, q2, s, q ); - } + if( !VectorCompare( v1, v2 )) + VectorLerp( v1, s, v2, pos ); else + VectorCopy( v1, pos ); + + if( q != NULL ) { - 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 ) + if( !VectorCompare( &v1[3], &v2[3] )) { - origin2[j] = origin1[j] = pbone->value[j]; // default; + vec4_t q1, q2; + + AngleQuaternion( &v1[3], q1, true ); + AngleQuaternion( &v2[3], q2, true ); + QuaternionSlerp( q1, q2, s, q ); } 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]; + AngleQuaternion( &v1[3], q, true ); } - - 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 ed4dd7d5..98ac4164 100644 --- a/public/xash3d_mathlib.h +++ b/public/xash3d_mathlib.h @@ -168,8 +168,8 @@ void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, v void PlaneIntersect( const mplane_t *plane, const vec3_t p0, const vec3_t p1, vec3_t out ); qboolean SphereIntersect( const vec3_t vSphereCenter, float fSphereRadiusSquared, const vec3_t vLinePt, const vec3_t vLineDir ); void QuaternionSlerp( const vec4_t p, const vec4_t q, float t, vec4_t qt ); -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 ); + +void R_StudioCalcBones( int frame, float s, const mstudiobone_t *pbone, const mstudioanim_t *panim, const float *adj, vec3_t pos, vec4_t q ); 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 6e3f28be..3507b06f 100644 --- a/ref/gl/gl_studio.c +++ b/ref/gl/gl_studio.c @@ -816,10 +816,7 @@ static void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, ms R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen ); for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) - { - R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); - R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); - } + R_StudioCalcBones( frame, s, pbone, panim, adj, q[i], pos[i] ); if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f; diff --git a/ref/soft/r_studio.c b/ref/soft/r_studio.c index 714b25bb..51b19375 100644 --- a/ref/soft/r_studio.c +++ b/ref/soft/r_studio.c @@ -835,10 +835,7 @@ static void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, ms R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen ); for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) - { - R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); - R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); - } + R_StudioCalcBones( frame, s, pbone, panim, adj, q[i], pos[i] ); if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f;