Patch [15/15]: Implements D3DRMQuaternionSlerp [try 2]

David.Adam at math.cnrs.fr David.Adam at math.cnrs.fr
Thu Apr 19 14:16:57 CDT 2007


All these patches were done in collaboration with Vijay Kamuju.

David ADAM
-------------- next part --------------
>From ae006c5ed24021200271c8fb2130543cdf1c80cd Mon Sep 17 00:00:00 2001
From: Adam <David.Adam at math.cnrs.fr>
Date: Fri, 20 Apr 2007 03:33:06 +0200
Subject: [PATCH] Implements D3DRMQuaternionSlerp with test.

---
 dlls/d3drm/d3drm.spec     |    2 +-
 dlls/d3drm/math.c         |   11 +++++++++++
 dlls/d3drm/tests/vector.c |   32 ++++++++++++++++++++++++++++++--
 3 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/dlls/d3drm/d3drm.spec b/dlls/d3drm/d3drm.spec
index c73b416..45bbd08 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)
diff --git a/dlls/d3drm/math.c b/dlls/d3drm/math.c
index a561e50..cf95773 100644
--- a/dlls/d3drm/math.c
+++ b/dlls/d3drm/math.c
@@ -63,6 +63,17 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternion
     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 7b5f4ec..485d4a5 100644
--- a/dlls/d3drm/tests/vector.c
+++ b/dlls/d3drm/tests/vector.c
@@ -141,8 +141,8 @@ void MatrixTest(void)
 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;
@@ -150,6 +150,34 @@ 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)
-- 
1.4.2



More information about the wine-patches mailing list