[PATCH 08/12] d3drm: Implement frame position/orientation methods

Jeff Smith whydoubt at gmail.com
Thu Jun 13 23:27:33 CDT 2019


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
 dlls/d3drm/frame.c       | 248 ++++++++++++++++++++++++++++++++++++++++++-----
 dlls/d3drm/tests/d3drm.c |  60 +++++++++++-
 2 files changed, 281 insertions(+), 27 deletions(-)

diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c
index ebe09df141..4de488575c 100644
--- a/dlls/d3drm/frame.c
+++ b/dlls/d3drm/frame.c
@@ -957,6 +957,19 @@ static void matrix_multiply(D3DRMMATRIX4D d, D3DRMMATRIX4D s1, D3DRMMATRIX4D s2)
     d[3][3] = 1.0f;
 }
 
+static void matrix_multiply_orient(D3DRMMATRIX4D d, D3DRMMATRIX4D s1, D3DRMMATRIX4D s2)
+{
+    d[0][0] = s1[0][0] * s2[0][0] + s1[0][1] * s2[1][0] + s1[0][2] * s2[2][0];
+    d[0][1] = s1[0][0] * s2[0][1] + s1[0][1] * s2[1][1] + s1[0][2] * s2[2][1];
+    d[0][2] = s1[0][0] * s2[0][2] + s1[0][1] * s2[1][2] + s1[0][2] * s2[2][2];
+    d[1][0] = s1[1][0] * s2[0][0] + s1[1][1] * s2[1][0] + s1[1][2] * s2[2][0];
+    d[1][1] = s1[1][0] * s2[0][1] + s1[1][1] * s2[1][1] + s1[1][2] * s2[2][1];
+    d[1][2] = s1[1][0] * s2[0][2] + s1[1][1] * s2[1][2] + s1[1][2] * s2[2][2];
+    d[2][0] = s1[2][0] * s2[0][0] + s1[2][1] * s2[1][0] + s1[2][2] * s2[2][0];
+    d[2][1] = s1[2][0] * s2[0][1] + s1[2][1] * s2[1][1] + s1[2][2] * s2[2][1];
+    d[2][2] = s1[2][0] * s2[0][2] + s1[2][1] * s2[1][2] + s1[2][2] * s2[2][2];
+}
+
 static struct d3drm_frame *matrix_expand(D3DRMMATRIX4D d, struct d3drm_frame *s,
         struct d3drm_frame *shortcut)
 {
@@ -1491,28 +1504,82 @@ static void matrix_invert(D3DRMMATRIX4D d, D3DRMMATRIX4D s)
     d[3][3] = 1.0f;
 }
 
+static void matrix_compare(struct d3drm_frame *frame, struct d3drm_frame *reference,
+        D3DRMMATRIX4D matrix)
+{
+    if (frame)
+        reference = matrix_expand(matrix, frame, reference);
+
+    if (reference)
+    {
+        D3DRMMATRIX4D m;
+        frame = matrix_expand(m, reference, frame);
+
+        if (frame)
+        {
+            D3DRMMATRIX4D inverse;
+            matrix_invert(inverse, m);
+            memcpy(m, matrix, sizeof(D3DRMMATRIX4D));
+            matrix_multiply(matrix, m, inverse);
+        }
+        else
+            matrix_invert(matrix, m);
+    }
+}
+
 static HRESULT WINAPI d3drm_frame3_GetPosition(IDirect3DRMFrame3 *iface,
         IDirect3DRMFrame3 *reference, D3DVECTOR *position)
 {
-    FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame3(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, position %p.\n", iface, reference, position);
+
+    if (!position)
+        return D3DRMERR_BADVALUE;
+
+    if (frame == ref)
+    {
+        position->u1.x = 0.0f;
+        position->u2.y = 0.0f;
+        position->u3.z = 0.0f;
+    }
+    else
+    {
+        D3DRMMATRIX4D m;
+        matrix_compare(frame, ref, m);
+        position->u1.x = m[3][0];
+        position->u2.y = m[3][1];
+        position->u3.z = m[3][2];
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_GetPosition(IDirect3DRMFrame2 *iface,
         IDirect3DRMFrame *reference, D3DVECTOR *position)
 {
-    FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, position %p.\n", iface, reference, position);
+
+    return d3drm_frame3_GetPosition(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            position);
 }
 
 static HRESULT WINAPI d3drm_frame1_GetPosition(IDirect3DRMFrame *iface,
         IDirect3DRMFrame *reference, D3DVECTOR *position)
 {
-    FIXME("iface %p, reference %p, position %p stub!\n", iface, reference, position);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, position %p.\n", iface, reference, position);
+
+    return d3drm_frame3_GetPosition(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            position);
 }
 
 
@@ -1698,25 +1765,62 @@ static HRESULT WINAPI d3drm_frame1_GetVelocity(IDirect3DRMFrame *iface,
 static HRESULT WINAPI d3drm_frame3_GetOrientation(IDirect3DRMFrame3 *iface,
         IDirect3DRMFrame3 *reference, D3DVECTOR *dir, D3DVECTOR *up)
 {
-    FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame3(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, dir %p, up %p.\n", iface, reference, dir, up);
+
+    if (!dir || !up)
+        return D3DRMERR_BADVALUE;
+
+    if (frame == ref)
+    {
+        dir->u1.x = 0.0f;
+        dir->u2.y = 0.0f;
+        dir->u3.z = 1.0f;
+        up->u1.x = 0.0f;
+        up->u2.y = 1.0f;
+        up->u3.z = 0.0f;
+    }
+    else
+    {
+        D3DRMMATRIX4D m;
+        matrix_compare(frame, ref, m);
+        dir->u1.x = m[2][0];
+        dir->u2.y = m[2][1];
+        dir->u3.z = m[2][2];
+        up->u1.x = m[1][0];
+        up->u2.y = m[1][1];
+        up->u3.z = m[1][2];
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_GetOrientation(IDirect3DRMFrame2 *iface,
         IDirect3DRMFrame *reference, D3DVECTOR *dir, D3DVECTOR *up)
 {
-    FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, dir %p, up %p.\n", iface, reference, dir, up);
+
+    return d3drm_frame3_GetOrientation(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            dir, up);
 }
 
 static HRESULT WINAPI d3drm_frame1_GetOrientation(IDirect3DRMFrame *iface,
         IDirect3DRMFrame *reference, D3DVECTOR *dir, D3DVECTOR *up)
 {
-    FIXME("iface %p, reference %p, dir %p, up %p stub!\n", iface, reference, dir, up);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, dir %p, up %p.\n", iface, reference, dir, up);
+
+    return d3drm_frame3_GetOrientation(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            dir, up);
 }
 
 static HRESULT WINAPI d3drm_frame3_GetVisuals(IDirect3DRMFrame3 *iface, DWORD *count, IUnknown **visuals)
@@ -2471,52 +2575,148 @@ static HRESULT WINAPI d3drm_frame1_SetMaterialMode(IDirect3DRMFrame *iface, D3DR
 static HRESULT WINAPI d3drm_frame3_SetOrientation(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *reference,
         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
 {
-    FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame3(reference);
+    D3DVECTOR dir, up, right;
+
+    TRACE("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e.\n",
             iface, reference, dx, dy, dz, ux, uy, uz);
 
-    return E_NOTIMPL;
+    if (dx == ux && dy == uy && dz == uz)
+        return D3DRMERR_BADVALUE;
+
+    dir.u1.x = dx;
+    dir.u2.y = dy;
+    dir.u3.z = dz;
+    D3DRMVectorNormalize(&dir);
+    if (ux == 0.0f && uy == 0.0f && uz == 0.0f)
+    {
+        up.u1.x = 1.0f;
+        up.u2.y = 0.0f;
+        up.u3.z = 0.0f;
+        D3DRMVectorCrossProduct(&right, &up, &dir);
+    }
+    else
+    {
+        up.u1.x = ux;
+        up.u2.y = uy;
+        up.u3.z = uz;
+        D3DRMVectorCrossProduct(&right, &up, &dir);
+        D3DRMVectorNormalize(&right);
+        D3DRMVectorCrossProduct(&up, &dir, &right);
+    }
+
+    frame->transform[0][0] = right.u1.x;
+    frame->transform[0][1] = right.u2.y;
+    frame->transform[0][2] = right.u3.z;
+    frame->transform[1][0] = up.u1.x;
+    frame->transform[1][1] = up.u2.y;
+    frame->transform[1][2] = up.u3.z;
+    frame->transform[2][0] = dir.u1.x;
+    frame->transform[2][1] = dir.u2.y;
+    frame->transform[2][2] = dir.u3.z;
+
+    if (ref == frame->parent)
+        return D3DRM_OK;
+
+    if (ref)
+    {
+        D3DRMMATRIX4D frame_copy, ref_matrix;
+        memcpy(frame_copy, frame->transform, sizeof(D3DRMMATRIX4D));
+        matrix_expand(ref_matrix, ref, NULL);
+        matrix_multiply_orient(frame->transform, ref_matrix, frame_copy);
+    }
+
+    if (frame->parent)
+    {
+        D3DRMMATRIX4D inverse, frame_copy, parent;
+        memcpy(frame_copy, frame->transform, sizeof(D3DRMMATRIX4D));
+        matrix_expand(parent, frame->parent, NULL);
+        matrix_invert(inverse, parent);
+        matrix_multiply_orient(frame->transform, frame_copy, inverse);
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_SetOrientation(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *reference,
         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
 {
-    FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
+
+    TRACE("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e.\n",
             iface, reference, dx, dy, dz, ux, uy, uz);
 
-    return E_NOTIMPL;
+    return d3drm_frame3_SetOrientation(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            dx, dy, dz, ux, uy, uz);
 }
 
 static HRESULT WINAPI d3drm_frame1_SetOrientation(IDirect3DRMFrame *iface, IDirect3DRMFrame *reference,
         D3DVALUE dx, D3DVALUE dy, D3DVALUE dz, D3DVALUE ux, D3DVALUE uy, D3DVALUE uz)
 {
-    FIXME("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e stub!\n",
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
+
+    TRACE("iface %p, reference %p, dx %.8e, dy %.8e, dz %.8e, ux %.8e, uy %.8e, uz %.8e.\n",
             iface, reference, dx, dy, dz, ux, uy, uz);
 
-    return E_NOTIMPL;
+    return d3drm_frame3_SetOrientation(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            dx, dy, dz, ux, uy, uz);
 }
 
 static HRESULT WINAPI d3drm_frame3_SetPosition(IDirect3DRMFrame3 *iface,
         IDirect3DRMFrame3 *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame3(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, x %.8e, y %.8e, z %.8e.\n", iface, reference, x, y, z);
+
+    if (ref == frame->parent)
+    {
+        frame->transform[3][0] = x;
+        frame->transform[3][1] = y;
+        frame->transform[3][2] = z;
+    }
+    else
+    {
+        D3DRMMATRIX4D m;
+        matrix_compare(ref, frame->parent, m);
+        frame->transform[3][0] = x * m[0][0] + y * m[1][0] + z * m[2][0] + m[3][0];
+        frame->transform[3][1] = x * m[0][1] + y * m[1][1] + z * m[2][1] + m[3][1];
+        frame->transform[3][2] = x * m[0][2] + y * m[1][2] + z * m[2][2] + m[3][2];
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_SetPosition(IDirect3DRMFrame2 *iface,
         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, x %.8e, y %.8e, z %.8e.\n", iface, reference, x, y, z);
+
+    return d3drm_frame3_SetPosition(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            x, y, z);
 }
 
 static HRESULT WINAPI d3drm_frame1_SetPosition(IDirect3DRMFrame *iface,
         IDirect3DRMFrame *reference, D3DVALUE x, D3DVALUE y, D3DVALUE z)
 {
-    FIXME("iface %p, reference %p, x %.8e, y %.8e, z %.8e stub!\n", iface, reference, x, y, z);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, reference %p, x %.8e, y %.8e, z %.8e.\n", iface, reference, x, y, z);
+
+    return d3drm_frame3_SetPosition(&frame->IDirect3DRMFrame3_iface,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            x, y, z);
 }
 
 static HRESULT WINAPI d3drm_frame3_SetRotation(IDirect3DRMFrame3 *iface,
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index fa23ad7795..16fd6ae7a6 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -2788,21 +2788,33 @@ cleanup:
         EXPECT_TRANSFORM_MATRIX(test_description, matrix, m11,m12,m13, m21,m22,m23, m31,m32,m33, m41,m42,m43); \
     }
 
-#define EXPECT_VECTOR(test_description, vector, vx,vy,vz) \
+#define EXPECT_VECTOR_(test_description, vector, vx,vy,vz) \
     { \
         int pass = 1; \
-        ok(hr == D3DRM_OK, test_description ": returned hr = %x\n", hr); \
         CHECK((vector).x, vx); \
         CHECK((vector).y, vy); \
         CHECK((vector).z, vz); \
         ok(pass, test_description ": vector result is not correct\n"); \
     }
 
+#define EXPECT_VECTOR(test_description, vector, vx,vy,vz) \
+    { \
+        ok(hr == D3DRM_OK, test_description ": returned hr = %x\n", hr); \
+        EXPECT_VECTOR_(test_description, vector, vx,vy,vz); \
+    }
+
+#define EXPECT_VECTORS_2(test_description, vector1, vx1,vy1,vz1, vector2, vx2,vy2,vz2) \
+    { \
+        ok(hr == D3DRM_OK, test_description ": returned hr = %x\n", hr); \
+        EXPECT_VECTOR_(test_description, vector1, vx1,vy1,vz1); \
+        EXPECT_VECTOR_(test_description, vector2, vx2,vy2,vz2); \
+    }
+
 static void test_frame_transform(void)
 {
     HRESULT hr;
     IDirect3DRM *d3drm;
-    IDirect3DRMFrame *frame, *subframe;
+    IDirect3DRMFrame *frame, *subframe, *reference;
     D3DRMMATRIX4D matrix;
     D3DVECTOR v1, v2;
 
@@ -2902,6 +2914,48 @@ static void test_frame_transform(void)
     EXPECT_TRANSFORM("AddRotation around null axis", frame, 1,0,0, 0,0,1, 0,-1,0, 0,0,0);
 
 
+    SET_TRANSFORM(frame, 1,3,2, 4,5,6, 7,8,9, 2,4,3);
+    IDirect3DRM_CreateFrame(d3drm, NULL, &reference);
+    SET_TRANSFORM(reference, 7,8,5, 6,5,4, 5,4,3, 5,5,5);
+
+    hr = IDirect3DRMFrame_SetPosition(frame, reference, 10.0f,11.0f,12.0f);
+    EXPECT_TRANSFORM("SetPosition (vs. reference)", frame, 1,3,2, 4,5,6, 7,8,9, 201,188,135);
+
+    hr = IDirect3DRMFrame_SetPosition(frame, NULL, 10.0f,11.0f,12.0f);
+    EXPECT_TRANSFORM("SetPosition (vs. NULL)", frame, 1,3,2, 4,5,6, 7,8,9, 10,11,12);
+
+    hr = IDirect3DRMFrame_SetPosition(subframe, NULL, 20.0f,35.0f,48.0f);
+    EXPECT_TRANSFORM("SetPosition (sub-frame vs. NULL)", subframe, 1,0,0, 0,1,0, 0,0,1, 2/3.0,238/9.0,-124/9.0);
+
+    hr = IDirect3DRMFrame_SetOrientation(frame, reference, -12.0f,-16.0f,15.0f, 9.0f,12.0f,20.0f);
+    EXPECT_TRANSFORM("SetOrientation (vs. reference)", frame, 6.08,-3.56,9.4, 4.68,-3.76,6.4, 4,-3,5, 10,11,12);
+
+    hr = IDirect3DRMFrame_SetOrientation(frame, NULL, -12.0f,-16.0f,15.0f, 9.0f,12.0f,20.0f);
+    EXPECT_TRANSFORM("SetOrientation (vs. NULL)", frame, 0.8,-0.6,0, 0.36,0.48,0.8, -0.48,-0.64,0.6, 10,11,12);
+
+    hr = IDirect3DRMFrame_SetOrientation(subframe, NULL, 9.0f,12.0f,20.0f, -12.0f,-16.0f,15.0f);
+    EXPECT_TRANSFORM("SetOrientation (sub-frame vs. NULL)", subframe, -1,0,0, 0,0,1, 0,1,0, 2/3.0,238/9.0,-124/9.0);
+
+    hr = IDirect3DRMFrame_GetPosition(frame, reference, &v1);
+    EXPECT_VECTOR("GetPosition (vs. reference)", v1, 0,10,-11);
+
+    hr = IDirect3DRMFrame_GetPosition(frame, NULL, &v1);
+    EXPECT_VECTOR("GetPosition (vs. NULL)", v1, 10,11,12);
+
+    hr = IDirect3DRMFrame_GetPosition(subframe, NULL, &v1);
+    EXPECT_VECTOR("GetPosition (sub-frame vs. NULL)", v1, 80/3.0,289/9.0,224/9.0);
+
+    hr = IDirect3DRMFrame_GetOrientation(frame, reference, &v1, &v2);
+    EXPECT_VECTORS_2("GetOrientation (vs. reference)",  v1, -0.35,2.92,-3.11,  v2, -0.05,1.56,-1.73);
+
+    hr = IDirect3DRMFrame_GetOrientation(frame, NULL, &v1, &v2);
+    EXPECT_VECTORS_2("GetOrientation (vs. NULL)",  v1, -0.48,-0.64,0.6,  v2, 0.36,0.48,0.8);
+
+    hr = IDirect3DRMFrame_GetOrientation(subframe, NULL, &v1, &v2);
+    EXPECT_VECTORS_2("GetOrientation (sub-frame vs. NULL)",  v1, 0.36,0.48,0.8,  v2, -0.48,-0.64,0.6);
+
+
+    IDirect3DRMFrame_Release(reference);
     IDirect3DRMFrame_Release(subframe);
     IDirect3DRMFrame_Release(frame);
     IDirect3DRM_Release(d3drm);
-- 
2.14.3




More information about the wine-devel mailing list