Skip to content

Commit a4f4e34

Browse files
committed
Implement bone position interpolation
1 parent 61d4844 commit a4f4e34

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

rehlds/engine/server.h

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ typedef struct client_bone_state_s
182182
{
183183
bonetransform_t bonetransform;
184184
float rotationmatrix[3][4];
185+
int numbones;
185186
qboolean valid;
186187
} client_bone_state_t;
187188
#endif // REHLDS_FIXES

rehlds/engine/sv_user.cpp

+85-2
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,89 @@ entity_state_t *SV_FindEntInPack(int index, packet_entities_t *pack)
11591159
return NULL;
11601160
}
11611161

1162+
#ifdef REHLDS_FIXES
1163+
void VectorsAngles( const vec3_t forward, const vec3_t right, const vec3_t up, vec3_t angles )
1164+
{
1165+
float pitch, cpitch, yaw, roll;
1166+
1167+
pitch = -asin( forward[2] );
1168+
cpitch = cos( pitch );
1169+
1170+
if( fabs( cpitch ) > 0.001f ) // gimball lock?
1171+
{
1172+
cpitch = 1.0f / cpitch;
1173+
pitch = RAD2DEG( pitch );
1174+
yaw = RAD2DEG( atan2( forward[1] * cpitch, forward[0] * cpitch ));
1175+
roll = RAD2DEG( atan2( -right[2] * cpitch, up[2] * cpitch ));
1176+
}
1177+
else
1178+
{
1179+
pitch = forward[2] > 0 ? -90.0f : 90.0f;
1180+
yaw = RAD2DEG( atan2( right[0], -right[1] ));
1181+
roll = 180.0f;
1182+
}
1183+
1184+
angles[0] = pitch;
1185+
angles[1] = yaw;
1186+
angles[2] = roll;
1187+
}
1188+
1189+
static void LerpRotationMatrix(const float from[3][4], const float to[3][4], float s, float out[3][4])
1190+
{
1191+
vec3_t f1, r1, u1, pos1, ang1;
1192+
vec3_t f2, r2, u2, pos2, ang2;
1193+
vec4_t q1, q2, q3;
1194+
float s1 = 1.0f - s; // backlerp
1195+
1196+
for( int j = 0; j < 3; j++ )
1197+
{
1198+
f1[j] = from[j][0];
1199+
r1[j] = from[j][1];
1200+
u2[j] = from[j][2];
1201+
pos1[j] = from[j][3];
1202+
1203+
f1[j] = to[j][0];
1204+
r1[j] = to[j][1];
1205+
u1[j] = to[j][2];
1206+
pos2[j] = to[j][3];
1207+
}
1208+
1209+
VectorsAngles( f1, r1, u1, ang1 );
1210+
VectorsAngles( f2, r2, u2, ang2 );
1211+
1212+
AngleQuaternion( ang1, q1 );
1213+
AngleQuaternion( ang2, q2 );
1214+
1215+
QuaternionSlerp(q1, q2, s, q3);
1216+
pos1[0] = pos1[0] * s1 + pos2[0] * s;
1217+
pos1[1] = pos1[1] * s1 + pos2[1] * s;
1218+
pos1[2] = pos1[2] * s1 + pos2[2] * s;
1219+
1220+
// result
1221+
QuaternionMatrix(q3, out);
1222+
out[0][3] = pos1[0];
1223+
out[1][3] = pos1[1];
1224+
out[2][3] = pos1[2];
1225+
}
1226+
1227+
static client_bone_state_t SV_StudioUnlagSlerpBones(const client_bone_state_t *from, const client_bone_state_t *to, float s)
1228+
{
1229+
client_bone_state_t ret;
1230+
1231+
ret.valid = true;
1232+
ret.numbones = from->numbones;
1233+
1234+
for (int i = 0; i < from->numbones; i++)
1235+
{
1236+
LerpRotationMatrix(from->bonetransform[i], to->bonetransform[i], s, ret.bonetransform[i]);
1237+
}
1238+
1239+
LerpRotationMatrix(from->rotationmatrix, to->rotationmatrix, s, ret.rotationmatrix);
1240+
1241+
return ret;
1242+
}
1243+
#endif // REHLDS_FIXES
1244+
11621245
void SV_SetupMove(client_t *_host_client)
11631246
{
11641247
struct client_s *cl;
@@ -1355,8 +1438,7 @@ void SV_SetupMove(client_t *_host_client)
13551438
{
13561439
if( frame->bonestate.valid )
13571440
{
1358-
// TODO: interpolate
1359-
pos->bonestate = nextFrame->bonestate;
1441+
pos->bonestate = SV_StudioUnlagSlerpBones(&frame->bonestate, &nextFrame->bonestate, frac);
13601442
}
13611443
else
13621444
{
@@ -1964,6 +2046,7 @@ void SV_SaveBoneState(client_t *_host_client, const edict_t *edict)
19642046

19652047
// copy bones
19662048
frame->bonestate.valid = true;
2049+
frame->bonestate.numbones = pstudiohdr->numbones;
19672050
Q_memcpy( frame->bonestate.bonetransform, bonetransform, sizeof( bonetransform ));
19682051
Q_memcpy( frame->bonestate.rotationmatrix, rotationmatrix, sizeof( rotationmatrix ));
19692052

0 commit comments

Comments
 (0)