Commit 44e74969 authored by David Adam's avatar David Adam Committed by Alexandre Julliard

d3drm: Implement the spherical interpolation part of D3DRMQuaternionSlerp.

parent a737dcf0
...@@ -123,12 +123,26 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV ...@@ -123,12 +123,26 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV
/* Interpolation between two quaternions */ /* Interpolation between two quaternions */
LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha) LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha)
{ {
D3DVALUE epsilon=1.0; D3DVALUE dot, epsilon, temp, theta, u;
D3DVECTOR sca1,sca2; D3DVECTOR sca1,sca2;
if (a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v) < 0.0) epsilon = -1.0; dot = a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v);
q->s = (1.0 - alpha) * a->s + epsilon * alpha * b->s; epsilon = 1.0f;
D3DRMVectorAdd(&q->v, D3DRMVectorScale(&sca1, &a->v, 1.0 - alpha), temp = 1.0f - alpha;
D3DRMVectorScale(&sca2, &b->v, epsilon * 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; return q;
} }
......
...@@ -227,10 +227,9 @@ static void QuaternionTest(void) ...@@ -227,10 +227,9 @@ static void QuaternionTest(void)
expect_quat(q,r); expect_quat(q,r);
/*_________________QuaternionSlerp_________________________*/ /*_________________QuaternionSlerp_________________________*/
/* Interpolation slerp is in fact a linear interpolation, not a spherical linear /* If the angle of the two quaternions is in ]PI/2;3PI/2[, QuaternionSlerp
* interpolation. Moreover, 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 * interpolates between the first quaternion and the opposite of the second one. The test proves
* these two facts. */ * this fact. */
par=0.31f; 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; 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; 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) ...@@ -256,6 +255,13 @@ static void QuaternionTest(void)
U3(q.v).z=g*U3(q1.v).z+h*U3(q2.v).z; U3(q.v).z=g*U3(q1.v).z+h*U3(q2.v).z;
pD3DRMQuaternionSlerp(&r,&q1,&q2,par); pD3DRMQuaternionSlerp(&r,&q1,&q2,par);
expect_quat(q,r); 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) static void ColorTest(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment