Skip to content

Commit

Permalink
public: merge calc bone quaternion and position into single function
Browse files Browse the repository at this point in the history
Expect that only adj and output quaternion can be NULL.
  • Loading branch information
a1batross committed Feb 11, 2025
1 parent eb09af0 commit 3965964
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 158 deletions.
5 changes: 2 additions & 3 deletions engine/common/mod_studio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 );
}
}
Expand Down
199 changes: 54 additions & 145 deletions public/xash3d_mathlib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
else
{
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j+3]);

k = frame;
if( panimvalue->num.total < panimvalue->num.valid )
j = 0;

// 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;
while( panimvalue->num.total <= j )
{
j -= panimvalue->num.total;
panimvalue += panimvalue->num.valid + 1;

// debug
if( panimvalue->num.total < panimvalue->num.valid )
k = 0;
}
if( panimvalue->num.total < panimvalue->num.valid )
j = 0;
}

// bah, missing blend!
if( panimvalue->num.valid > k )
{
angles1[j] = panimvalue[k+1].value;
if( panimvalue->num.valid > j )
{
v1[i] = panimvalue[j + 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.valid > j + 1 )
v2[i] = panimvalue[j + 2].value;
else 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 )
else
{
angles1[j] += adj[pbone->bonecontroller[j+3]];
angles2[j] += adj[pbone->bonecontroller[j+3]];
}
}
v1[i] = panimvalue[panimvalue->num.valid].value;

if( !VectorCompare( angles1, angles2 ))
{
vec4_t q1, q2;
if( panimvalue->num.total > j + 1 )
v2[i] = v1[i];
else
v2[i] = panimvalue[panimvalue->num.valid + 2].value;
}

AngleQuaternion( angles1, q1, true );
AngleQuaternion( angles2, q2, true );
QuaternionSlerp( q1, q2, s, q );
}
else
{
AngleQuaternion( angles1, q, true );
v1[i] = pbone->value[i] + v1[i] * pbone->scale[i] + fadj;
v2[i] = pbone->value[i] + v2[i] * pbone->scale[i] + fadj;
}
}

/*
====================
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;
if( !VectorCompare( v1, v2 ))
VectorLerp( v1, s, v2, pos );
else
VectorCopy( v1, pos );

for( j = 0; j < 3; j++ )
if( q != NULL )
{
if( !panim || panim->offset[j] == 0 )
if( !VectorCompare( &v1[3], &v2[3] ))
{
origin2[j] = origin1[j] = pbone->value[j]; // default;
}
else
{
mstudioanimvalue_t *panimvalue = (mstudioanimvalue_t *)((byte *)panim + panim->offset[j]);

k = frame;
vec4_t q1, q2;

// 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], q1, true );
AngleQuaternion( &v2[3], q2, true );
QuaternionSlerp( q1, q2, s, q );
}

if( pbone->bonecontroller[j] != -1 && adj != NULL )
else
{
origin1[j] += adj[pbone->bonecontroller[j]];
origin2[j] += adj[pbone->bonecontroller[j]];
AngleQuaternion( &v1[3], q, true );
}
}

if( !VectorCompare( origin1, origin2 ))
{
VectorLerp( origin1, s, origin2, pos );
}
else
{
VectorCopy( origin1, pos );
}
}
4 changes: 2 additions & 2 deletions public/xash3d_mathlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) ? \
Expand Down
5 changes: 1 addition & 4 deletions ref/gl/gl_studio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 1 addition & 4 deletions ref/soft/r_studio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 3965964

Please sign in to comment.