Module: wine Branch: master Commit: 44e74969e3753d5517277afa2aa9a798e37e2cdf URL: http://source.winehq.org/git/wine.git/?a=commit;h=44e74969e3753d5517277afa2a...
Author: David Adam david.adam.cnrs@gmail.com Date: Sat Feb 14 13:56:00 2009 +0100
d3drm: Implement the spherical interpolation part of D3DRMQuaternionSlerp.
---
dlls/d3drm/math.c | 24 +++++++++++++++++++----- dlls/d3drm/tests/vector.c | 12 +++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/dlls/d3drm/math.c b/dlls/d3drm/math.c index 801a1bf..8bf5035 100644 --- a/dlls/d3drm/math.c +++ b/dlls/d3drm/math.c @@ -123,12 +123,26 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV /* Interpolation between two quaternions */ LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha) { - D3DVALUE epsilon=1.0; + D3DVALUE dot, epsilon, temp, theta, u; D3DVECTOR sca1,sca2; - if (a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v) < 0.0) epsilon = -1.0; - q->s = (1.0 - alpha) * a->s + epsilon * alpha * b->s; - D3DRMVectorAdd(&q->v, D3DRMVectorScale(&sca1, &a->v, 1.0 - alpha), - D3DRMVectorScale(&sca2, &b->v, epsilon * alpha)); + dot = a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v); + epsilon = 1.0f; + temp = 1.0f - alpha; + u = alpha; + if (dot < 0.0) + { + epsilon = -1.0; + dot = -dot; + } + if( 1.0f - dot > 0.001f ) + { + theta = acos(dot); + temp = sin(theta * temp) / sin(theta); + u = sin(theta * alpha) / sin(theta); + } + q->s = temp * a->s + epsilon * u * b->s; + D3DRMVectorAdd(&q->v, D3DRMVectorScale(&sca1, &a->v, temp), + D3DRMVectorScale(&sca2, &b->v, epsilon * u)); return q; }
diff --git a/dlls/d3drm/tests/vector.c b/dlls/d3drm/tests/vector.c index 4b0f97f..75c05fc 100644 --- a/dlls/d3drm/tests/vector.c +++ b/dlls/d3drm/tests/vector.c @@ -227,10 +227,9 @@ static void QuaternionTest(void) expect_quat(q,r);
/*_________________QuaternionSlerp_________________________*/ -/* Interpolation slerp is in fact a linear interpolation, not a spherical linear - * interpolation. Moreover, if the angle of the two quaternions is in ]PI/2;3PI/2[, QuaternionSlerp +/* If the angle of the two quaternions is in ]PI/2;3PI/2[, QuaternionSlerp * interpolates between the first quaternion and the opposite of the second one. The test proves - * these two facts. */ + * this fact. */ par=0.31f; q1.s=1.0f; U1(q1.v).x=2.0f; U2(q1.v).y=3.0f; U3(q1.v).z=50.0f; q2.s=-4.0f; U1(q2.v).x=6.0f; U2(q2.v).y=7.0f; U3(q2.v).z=8.0f; @@ -256,6 +255,13 @@ static void QuaternionTest(void) U3(q.v).z=g*U3(q1.v).z+h*U3(q2.v).z; pD3DRMQuaternionSlerp(&r,&q1,&q2,par); expect_quat(q,r); + +/* Test the spherical interpolation part */ + q1.s=0.1f; U1(q1.v).x=0.2f; U2(q1.v).y=0.3f; U3(q1.v).z=0.4f; + q2.s=0.5f; U1(q2.v).x=0.6f; U2(q2.v).y=0.7f; U3(q2.v).z=0.8f; + q.s = 0.243943f; U1(q.v).x = 0.351172f; U2(q.v).y = 0.458401f; U3(q.v).z = 0.565629f; + pD3DRMQuaternionSlerp(&r,&q1,&q2,par); + expect_quat(q,r); }
static void ColorTest(void)