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