David Adam : d3drm: Implement the spherical interpolation part of D3DRMQuaternionSlerp.

Alexandre Julliard julliard at winehq.org
Mon Feb 16 09:35:37 CST 2009


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

Author: David Adam <david.adam.cnrs at gmail.com>
Date:   Sat Feb 14 13:56:00 2009 +0100

d3drm: Implement the spherical interpolation part of D3DRMQuaternionSlerp.

---

 dlls/d3drm/math.c         |   24 +++++++++++++++++++-----
 dlls/d3drm/tests/vector.c |   12 +++++++++---
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/dlls/d3drm/math.c b/dlls/d3drm/math.c
index 801a1bf..8bf5035 100644
--- a/dlls/d3drm/math.c
+++ b/dlls/d3drm/math.c
@@ -123,12 +123,26 @@ LPD3DRMQUATERNION WINAPI D3DRMQuaternionFromRotation(LPD3DRMQUATERNION q, LPD3DV
 /* Interpolation between two quaternions */
 LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha)
 {
-    D3DVALUE epsilon=1.0;
+    D3DVALUE dot, epsilon, temp, theta, u;
     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));
+    dot = a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v);
+    epsilon = 1.0f;
+    temp = 1.0f - 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;
 }
 
diff --git a/dlls/d3drm/tests/vector.c b/dlls/d3drm/tests/vector.c
index 4b0f97f..75c05fc 100644
--- a/dlls/d3drm/tests/vector.c
+++ b/dlls/d3drm/tests/vector.c
@@ -227,10 +227,9 @@ static void QuaternionTest(void)
     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
+/* 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. */
+ * this fact. */
     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;
     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)
     U3(q.v).z=g*U3(q1.v).z+h*U3(q2.v).z;
     pD3DRMQuaternionSlerp(&r,&q1,&q2,par);
     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)




More information about the wine-cvs mailing list