Module: wine Branch: master Commit: d53d7c9ea29bbac5f2527ee042cc60f706836c11 URL: http://source.winehq.org/git/wine.git/?a=commit;h=d53d7c9ea29bbac5f2527ee042...
Author: David Adam David.Adam@math.cnrs.fr Date: Thu Apr 19 21:16:57 2007 +0200
d3drm: Implement D3DRMQuaternionSlerp.
---
dlls/d3drm/d3drm.spec | 2 +- dlls/d3drm/math.c | 12 ++++++++++++ dlls/d3drm/tests/vector.c | 35 +++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-)
diff --git a/dlls/d3drm/d3drm.spec b/dlls/d3drm/d3drm.spec index 8713d01..4499211 100644 --- a/dlls/d3drm/d3drm.spec +++ b/dlls/d3drm/d3drm.spec @@ -7,7 +7,7 @@ @ stdcall D3DRMMatrixFromQuaternion(ptr ptr) @ stdcall D3DRMQuaternionFromRotation(ptr ptr long) @ stdcall D3DRMQuaternionMultiply(ptr ptr ptr) -@ stub D3DRMQuaternionSlerp +@ stdcall D3DRMQuaternionSlerp(ptr ptr ptr long) @ stdcall D3DRMVectorAdd(ptr ptr ptr) @ stdcall D3DRMVectorCrossProduct(ptr ptr ptr) @ stdcall D3DRMVectorDotProduct(ptr ptr) diff --git a/dlls/d3drm/math.c b/dlls/d3drm/math.c index 21a4151..0355b22 100644 --- a/dlls/d3drm/math.c +++ b/dlls/d3drm/math.c @@ -78,6 +78,18 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV 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 */ LPD3DVECTOR WINAPI D3DRMVectorAdd(LPD3DVECTOR d, LPD3DVECTOR s1, LPD3DVECTOR s2) { diff --git a/dlls/d3drm/tests/vector.c b/dlls/d3drm/tests/vector.c index 744eb16..1c25c50 100644 --- a/dlls/d3drm/tests/vector.c +++ b/dlls/d3drm/tests/vector.c @@ -153,8 +153,8 @@ static void MatrixTest(void) static void QuaternionTest(void) { D3DVECTOR axis; - D3DVALUE theta; - D3DRMQUATERNION q,r; + D3DVALUE g,h,epsilon,par,theta; + D3DRMQUATERNION q,q1,q2,r;
/*_________________QuaternionFromRotation___________________*/ axis.x=1.0;axis.y=1.0;axis.z=1.0; @@ -162,6 +162,37 @@ static void QuaternionTest(void) D3DRMQuaternionFromRotation(&r,&axis,theta); q.s=0.5;q.v.x=0.5;q.v.y=0.5;q.v.z=0.5; 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)