Skip to content

Commit 836bcd0

Browse files
authored
Merge pull request #383 from MoeMod/studio_util
update studio_util neon
2 parents f1c484a + abb4bff commit 836bcd0

3 files changed

Lines changed: 93 additions & 19 deletions

File tree

cl_dll/StudioModelRenderer.cpp

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,6 @@ StudioSlerpBones
339339
void CStudioModelRenderer::StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_t q2[], float pos2[][3], float s )
340340
{
341341
int i;
342-
vec4_t q3;
343342
float s1;
344343

345344
if( s < 0.0f )
@@ -349,13 +348,28 @@ void CStudioModelRenderer::StudioSlerpBones( vec4_t q1[], float pos1[][3], vec4_
349348

350349
s1 = 1.0f - s;
351350

351+
switch (m_pStudioHeader->numbones % 4)
352+
{
353+
case 3:
354+
QuaternionSlerp( q1[0], q2[0], s, q1[0] );
355+
QuaternionSlerp( q1[1], q2[1], s, q1[1] );
356+
QuaternionSlerp( q1[2], q2[2], s, q1[2] );
357+
break;
358+
case 2:
359+
QuaternionSlerp( q1[0], q2[0], s, q1[0] );
360+
QuaternionSlerp( q1[1], q2[1], s, q1[1] );
361+
break;
362+
case 1:
363+
QuaternionSlerp( q1[0], q2[0], s, q1[0] );
364+
break;
365+
case 0:
366+
break;
367+
}
368+
for ( i = m_pStudioHeader->numbones % 4; i < m_pStudioHeader->numbones; i += 4 )
369+
QuaternionSlerpX4( q1 + i, q2 + i, s, q1 + i );
370+
352371
for( i = 0; i < m_pStudioHeader->numbones; i++ )
353372
{
354-
QuaternionSlerp( q1[i], q2[i], s, q3 );
355-
q1[i][0] = q3[0];
356-
q1[i][1] = q3[1];
357-
q1[i][2] = q3[2];
358-
q1[i][3] = q3[3];
359373
pos1[i][0] = pos1[i][0] * s1 + pos2[i][0] * s;
360374
pos1[i][1] = pos1[i][1] * s1 + pos2[i][1] * s;
361375
pos1[i][2] = pos1[i][2] * s1 + pos2[i][2] * s;

cl_dll/studio_util.cpp

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,10 @@ void CrossProduct( const float *v1, const float *v2, float *cross )
143143
memcpy(&v1_reg, v1, sizeof(float) * 3);
144144
memcpy(&v2_reg, v2, sizeof(float) * 3);
145145

146-
float32x4_t yzxy_a = vextq_f32(vextq_f32(v1_reg, v1_reg, 3), v1_reg, 2); // [aj, ak, ai, aj]
147-
float32x4_t yzxy_b = vextq_f32(vextq_f32(v2_reg, v2_reg, 3), v2_reg, 2); // [bj, bk, bi, bj]
146+
float32x2_t xy_a = vget_low_f32(v1_reg);
147+
float32x2_t xy_b = vget_low_f32(v2_reg);
148+
float32x4_t yzxy_a = vcombine_f32(vext_f32(xy_a, vget_high_f32(v1_reg), 1), xy_a); // [aj, ak, ai, aj]
149+
float32x4_t yzxy_b = vcombine_f32(vext_f32(xy_b, vget_high_f32(v2_reg), 1), xy_b); // [bj, bk, bi, bj]
148150
float32x4_t zxyy_a = vextq_f32(yzxy_a, yzxy_a, 1); // [ak, ai, aj, aj]
149151
float32x4_t zxyy_b = vextq_f32(yzxy_b, yzxy_b, 1); // [bk, ai, bj, bj]
150152
float32x4_t cross_reg = vfmsq_f32(vmulq_f32(yzxy_a, zxyy_b), zxyy_a, yzxy_b); // [ajbk-akbj, akbi-aibk, aibj-ajbi, 0]
@@ -265,23 +267,23 @@ void AngleQuaternion( float *angles, vec4_t quaternion )
265267
sincos_ps(vmulq_n_f32(angles_reg, 0.5), &sr_sp_sy_0_cr_cp_cy_1.val[0], &sr_sp_sy_0_cr_cp_cy_1.val[1]);
266268

267269
float32x4x2_t sr_sy_cr_cy_sp_0_cp_1 = vuzpq_f32(sr_sp_sy_0_cr_cp_cy_1.val[0], sr_sp_sy_0_cr_cp_cy_1.val[1]);
268-
float32x4_t cp_cp_cp_cp = vdupq_laneq_f32(sr_sp_sy_0_cr_cp_cy_1.val[1], 1);
269-
float32x4_t sp_sp_sp_sp = vdupq_laneq_f32(sr_sp_sy_0_cr_cp_cy_1.val[0], 1);
270270

271271
float32x4_t sr_sy_cr_cy = sr_sy_cr_cy_sp_0_cp_1.val[0];
272272
float32x4_t sy_cr_cy_sr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 1);
273-
float32x4_t cr_cy_sr_sy = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 2);
274-
float32x4_t cy_sr_sy_cr = vextq_f32(sr_sy_cr_cy_sp_0_cp_1.val[0], sr_sy_cr_cy_sp_0_cp_1.val[0], 3);
275-
float32x4_t sp_sp_sp_sp_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(sp_sp_sp_sp), AngleQuaternion_sign2));
273+
float32x4_t srsy_sycr_crcy_cysr = vmulq_f32(sr_sy_cr_cy, sy_cr_cy_sr);
274+
float32x4_t sycr_crcy_cysr_srsy = vextq_f32(srsy_sycr_crcy_cysr, srsy_sycr_crcy_cysr, 1);
275+
float32x4_t cysr_srsy_sycr_crcy = vextq_f32(srsy_sycr_crcy_cysr, srsy_sycr_crcy_cysr, 3);
276+
float32x4_t sycr_crcy_cysr_srsy_signed = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(sycr_crcy_cysr_srsy), AngleQuaternion_sign2));
276277

277-
float32x4_t left = vmulq_f32(vmulq_f32(sr_sy_cr_cy, cp_cp_cp_cp), cy_sr_sy_cr);
278+
float32x4_t left = vmulq_laneq_f32(cysr_srsy_sycr_crcy, sr_sp_sy_0_cr_cp_cy_1.val[1], 1);
278279

279-
float32x4_t out_reg = vfmaq_f32(left, vmulq_f32(cr_cy_sr_sy, sp_sp_sp_sp_signed), sy_cr_cy_sr);
280+
float32x4_t out_reg = vfmaq_laneq_f32(left, sycr_crcy_cysr_srsy_signed, sr_sp_sy_0_cr_cp_cy_1.val[0], 1);
280281
memcpy(quaternion, &out_reg, sizeof(float) * 4);
281-
//quaternion[0] = sr * cp * cy - cr * sp * sy; // X
282-
//quaternion[1] = sy * cp * sr + cy * sp * cr; // Y
283-
//quaternion[2] = cr * cp * sy - sr * sp * cy; // Z
284-
//quaternion[3] = cy * cp * cr + sy * sp * sr; // W
282+
// A = sr * sy, B = sy * cr, C = cr * cy, D = cy * sr
283+
//quaternion[0] = D * cp - B * sp; // X
284+
//quaternion[1] = A * cp + C * sp; // Y
285+
//quaternion[2] = B * cp - D * sp; // Z
286+
//quaternion[3] = C * cp + A * sp; // W
285287
#else
286288
float angle;
287289
float sr, sp, sy, cr, cp, cy;
@@ -400,6 +402,63 @@ void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt )
400402
#endif
401403
}
402404

405+
/*
406+
====================
407+
QuaternionSlerpX4
408+
409+
====================
410+
*/
411+
void QuaternionSlerpX4( vec4_t p[4], vec4_t q[4], float t, vec4_t qt[4] )
412+
{
413+
#if XASH_SIMD_NEON
414+
float32x4x4_t p_reg, q_reg;
415+
memcpy(&p_reg, p, sizeof(float) * 4 * 4);
416+
memcpy(&q_reg, q, sizeof(float) * 4 * 4);
417+
418+
//float32x4_t cosom = { DotProduct(p[0], q[0]), DotProduct(p[1], q[1]), DotProduct(p[2], q[2]), DotProduct(p[3], q[3]) };
419+
float32x4x4_t p_t = vld4q_f32((const float*)&p_reg);
420+
float32x4x4_t q_t = vld4q_f32((const float*)&q_reg);
421+
float32x4_t cosom = vmulq_f32(p_t.val[0], q_t.val[0]);
422+
cosom = vfmaq_f32(cosom, p_t.val[1], q_t.val[1]);
423+
cosom = vfmaq_f32(cosom, p_t.val[2], q_t.val[2]);
424+
cosom = vfmaq_f32(cosom, p_t.val[3], q_t.val[3]);
425+
426+
// if(cosom < 0) q=-q, cosom=-cosom
427+
uint32x4_t sign = vandq_u32(vreinterpretq_u32_f32(cosom), vdupq_n_u32(0x80000000));
428+
q_reg.val[0] = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q_reg.val[0]), vdupq_laneq_u32(sign, 0)));
429+
q_reg.val[1] = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q_reg.val[1]), vdupq_laneq_u32(sign, 1)));
430+
q_reg.val[2] = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q_reg.val[2]), vdupq_laneq_u32(sign, 2)));
431+
q_reg.val[3] = vreinterpretq_f32_u32(veorq_u32(vreinterpretq_u32_f32(q_reg.val[3]), vdupq_laneq_u32(sign, 3)));
432+
cosom = vabsq_f32(cosom);
433+
434+
float32x4_t sclp = vdupq_n_f32(1.0f - t);
435+
float32x4_t sclq = vdupq_n_f32(t);
436+
// if ((1.0 - cosom) > 0.000001) scl = sin(scl * omega) / sinom;
437+
uint32x4_t cosom_less_then_one = vcltq_f32(cosom, vdupq_n_f32(1.0f - 0.00001f));
438+
float32x4_t omega = acos_ps(cosom);
439+
// 1/sinom = rsqrt(1-cosom*cosom)
440+
float32x4_t sinom = sin_ps(omega);
441+
float32x4_t sinom_reciprocal = vrecpeq_f32(sinom); // vdivq_f32(vdupq_n_f32(1), sin_ps(omega));
442+
sinom_reciprocal = vmulq_f32(sinom_reciprocal, vrecpsq_f32(sinom, sinom_reciprocal));
443+
sclp = vbslq_f32(cosom_less_then_one, sclp, vmulq_f32(sin_ps(vmulq_f32(sclp, omega)), sinom_reciprocal));
444+
sclq = vbslq_f32(cosom_less_then_one, sclq, vmulq_f32(sin_ps(vmulq_f32(sclq, omega)), sinom_reciprocal));
445+
446+
// qt = (sclp * p + sclq * q);
447+
float32x4x4_t qt_reg;
448+
qt_reg.val[0] = vfmaq_laneq_f32(vmulq_laneq_f32(p_reg.val[0], sclp, 0), q_reg.val[0], sclq, 0);
449+
qt_reg.val[1] = vfmaq_laneq_f32(vmulq_laneq_f32(p_reg.val[1], sclp, 1), q_reg.val[1], sclq, 1);
450+
qt_reg.val[2] = vfmaq_laneq_f32(vmulq_laneq_f32(p_reg.val[2], sclp, 2), q_reg.val[2], sclq, 2);
451+
qt_reg.val[3] = vfmaq_laneq_f32(vmulq_laneq_f32(p_reg.val[3], sclp, 3), q_reg.val[3], sclq, 3);
452+
453+
memcpy(qt, &qt_reg, sizeof(float) * 4 * 4);
454+
#else
455+
QuaternionSlerp(p[0], q[0], t, qt[0]);
456+
QuaternionSlerp(p[1], q[1], t, qt[1]);
457+
QuaternionSlerp(p[2], q[2], t, qt[2]);
458+
QuaternionSlerp(p[3], q[3], t, qt[3]);
459+
#endif
460+
}
461+
403462
/*
404463
====================
405464
QuaternionMatrix

cl_dll/studio_util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,6 @@ void ConcatTransforms( float in1[3][4], float in2[3][4], float out[3][4] );
3636
void MatrixCopy( float in[3][4], float out[3][4] );
3737
void QuaternionMatrix( vec4_t quaternion, float (*matrix)[4] );
3838
void QuaternionSlerp( vec4_t p, vec4_t q, float t, vec4_t qt );
39+
void QuaternionSlerpX4( vec4_t p[4], vec4_t q[4], float t, vec4_t qt[4] );
3940
void AngleQuaternion( float *angles, vec4_t quaternion );
4041
#endif // STUDIO_UTIL_H

0 commit comments

Comments
 (0)