d3drm: Implement D3DRMQuaternionSlerp.

This commit is contained in:
David Adam 2007-04-19 21:16:57 +02:00 committed by Alexandre Julliard
parent 909b502360
commit d53d7c9ea2
3 changed files with 46 additions and 3 deletions

View File

@ -7,7 +7,7 @@
@ stdcall D3DRMMatrixFromQuaternion(ptr ptr) @ stdcall D3DRMMatrixFromQuaternion(ptr ptr)
@ stdcall D3DRMQuaternionFromRotation(ptr ptr long) @ stdcall D3DRMQuaternionFromRotation(ptr ptr long)
@ stdcall D3DRMQuaternionMultiply(ptr ptr ptr) @ stdcall D3DRMQuaternionMultiply(ptr ptr ptr)
@ stub D3DRMQuaternionSlerp @ stdcall D3DRMQuaternionSlerp(ptr ptr ptr long)
@ stdcall D3DRMVectorAdd(ptr ptr ptr) @ stdcall D3DRMVectorAdd(ptr ptr ptr)
@ stdcall D3DRMVectorCrossProduct(ptr ptr ptr) @ stdcall D3DRMVectorCrossProduct(ptr ptr ptr)
@ stdcall D3DRMVectorDotProduct(ptr ptr) @ stdcall D3DRMVectorDotProduct(ptr ptr)

View File

@ -78,6 +78,18 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV
return q; return q;
} }
/* Interpolation between two quaternions */
LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha)
{
D3DVALUE epsilon=1.0;
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));
return q;
}
/* Add Two Vectors */ /* Add Two Vectors */
LPD3DVECTOR WINAPI D3DRMVectorAdd(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2) LPD3DVECTOR WINAPI D3DRMVectorAdd(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2)
{ {

View File

@ -153,8 +153,8 @@ static void MatrixTest(void)
static void QuaternionTest(void) static void QuaternionTest(void)
{ {
D3DVECTOR axis; D3DVECTOR axis;
D3DVALUE theta; D3DVALUE g,h,epsilon,par,theta;
D3DRMQUATERNION q,r; D3DRMQUATERNION q,q1,q2,r;
/*_________________QuaternionFromRotation___________________*/ /*_________________QuaternionFromRotation___________________*/
axis.x=1.0;axis.y=1.0;axis.z=1.0; axis.x=1.0;axis.y=1.0;axis.z=1.0;
@ -162,6 +162,37 @@ static void QuaternionTest(void)
D3DRMQuaternionFromRotation(&r,&axis,theta); D3DRMQuaternionFromRotation(&r,&axis,theta);
q.s=0.5;q.v.x=0.5;q.v.y=0.5;q.v.z=0.5; q.s=0.5;q.v.x=0.5;q.v.y=0.5;q.v.z=0.5;
expect_quat(q,r); 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
* interpolates between the first quaternion and the opposite of the second one. The test proves
* these two facts. */
par=0.31;
q1.s=1.0; q1.v.x=2.0; q1.v.y=3.0; q1.v.z=50.0;
q2.s=-4.0; q2.v.x=6.0; q2.v.y=7.0; q2.v.z=8.0;
/* The angle between q1 and q2 is in [-PI/2,PI/2]. So, one interpolates between q1 and q2. */
epsilon=1.0;
g=1.0-par; h=epsilon*par;
/* Part of the test proving that the interpolation is linear. */
q.s=g*q1.s+h*q2.s;
q.v.x=g*q1.v.x+h*q2.v.x;
q.v.y=g*q1.v.y+h*q2.v.y;
q.v.z=g*q1.v.z+h*q2.v.z;
D3DRMQuaternionSlerp(&r,&q1,&q2,par);
expect_quat(q,r);
q1.s=1.0; q1.v.x=2.0; q1.v.y=3.0; q1.v.z=50.0;
q2.s=-94.0; q2.v.x=6.0; q2.v.y=7.0; q2.v.z=-8.0;
/* The angle between q1 and q2 is not in [-PI/2,PI/2]. So, one interpolates between q1 and -q2. */
epsilon=-1.0;
g=1.0-par; h=epsilon*par;
q.s=g*q1.s+h*q2.s;
q.v.x=g*q1.v.x+h*q2.v.x;
q.v.y=g*q1.v.y+h*q2.v.y;
q.v.z=g*q1.v.z+h*q2.v.z;
D3DRMQuaternionSlerp(&r,&q1,&q2,par);
expect_quat(q,r);
} }
START_TEST(vector) START_TEST(vector)