David Adam : d3drm: Implement D3DRMQuaternionSlerp.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Apr 23 14:26:23 CDT 2007


Module: wine
Branch: master
Commit: d53d7c9ea29bbac5f2527ee042cc60f706836c11
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d53d7c9ea29bbac5f2527ee042cc60f706836c11

Author: David Adam <David.Adam at 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)




More information about the wine-cvs mailing list