[PATCH 02/12] d3drm: Implement frame InverseTransform

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


Signed-off-by: Jeff Smith <whydoubt at gmail.com>
---
 dlls/d3drm/frame.c       | 96 +++++++++++++++++++++++++++++++++++++++++++++---
 dlls/d3drm/tests/d3drm.c |  7 ++++
 2 files changed, 97 insertions(+), 6 deletions(-)

diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c
index 14a524ea7d..f5e24efb6f 100644
--- a/dlls/d3drm/frame.c
+++ b/dlls/d3drm/frame.c
@@ -937,6 +937,41 @@ static HRESULT WINAPI d3drm_frame1_AddMoveCallback(IDirect3DRMFrame *iface,
     return E_NOTIMPL;
 }
 
+static void matrix_multiply(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[0][3] = 0.0f;
+    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[1][3] = 0.0f;
+    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];
+    d[2][3] = 0.0f;
+    d[3][0] = s1[3][0] * s2[0][0] + s1[3][1] * s2[1][0] + s1[3][2] * s2[2][0] + s2[3][0];
+    d[3][1] = s1[3][0] * s2[0][1] + s1[3][1] * s2[1][1] + s1[3][2] * s2[2][1] + s2[3][1];
+    d[3][2] = s1[3][0] * s2[0][2] + s1[3][1] * s2[1][2] + s1[3][2] * s2[2][2] + s2[3][2];
+    d[3][3] = 1.0f;
+}
+
+static struct d3drm_frame *matrix_expand(D3DRMMATRIX4D d, struct d3drm_frame *s,
+        struct d3drm_frame *shortcut)
+{
+    D3DRMMATRIX4D m;
+    memcpy(d, s->transform, sizeof(D3DRMMATRIX4D));
+    while ((s = s->parent))
+    {
+        if (s == shortcut)
+            return NULL;
+        memcpy(m, d, sizeof(D3DRMMATRIX4D));
+        matrix_multiply(d, m, s->transform);
+    }
+    return shortcut;
+}
+
 static HRESULT WINAPI d3drm_frame3_AddTransform(IDirect3DRMFrame3 *iface,
         D3DRMCOMBINETYPE type, D3DRMMATRIX4D matrix)
 {
@@ -1269,6 +1304,41 @@ static HRESULT WINAPI d3drm_frame1_GetParent(IDirect3DRMFrame *iface, IDirect3DR
     return d3drm_frame2_GetParent(&frame->IDirect3DRMFrame2_iface, parent);
 }
 
+static void matrix_invert(D3DRMMATRIX4D d, D3DRMMATRIX4D s)
+{
+    D3DVALUE determinant;
+    D3DVALUE cofac[3];
+
+    cofac[0] = s[1][1] * s[2][2] - s[1][2] * s[2][1];
+    cofac[1] = s[1][2] * s[2][0] - s[1][0] * s[2][2];
+    cofac[2] = s[1][0] * s[2][1] - s[1][1] * s[2][0];
+
+    determinant = s[0][0] * cofac[0] + s[0][1] * cofac[1] + s[0][2] * cofac[2];
+
+    if (determinant == 0.0f)
+    {
+        memcpy(d, identity, sizeof(D3DRMMATRIX4D));
+        return;
+    }
+
+    d[0][0] = cofac[0] / determinant;
+    d[0][1] = (s[2][1] * s[0][2] - s[2][2] * s[0][1]) / determinant;
+    d[0][2] = (s[0][1] * s[1][2] - s[0][2] * s[1][1]) / determinant;
+    d[0][3] = 0.0f;
+    d[1][0] = cofac[1] / determinant;
+    d[1][1] = (s[2][2] * s[0][0] - s[2][0] * s[0][2]) / determinant;
+    d[1][2] = (s[0][2] * s[1][0] - s[0][0] * s[1][2]) / determinant;
+    d[1][3] = 0.0f;
+    d[2][0] = cofac[2] / determinant;
+    d[2][1] = (s[2][0] * s[0][1] - s[2][1] * s[0][0]) / determinant;
+    d[2][2] = (s[0][0] * s[1][1] - s[0][1] * s[1][0]) / determinant;
+    d[2][3] = 0.0f;
+    d[3][0] = -(d[0][0] * s[3][0] + d[1][0] * s[3][1] + d[2][0] * s[3][2]);
+    d[3][1] = -(d[0][1] * s[3][0] + d[1][1] * s[3][1] + d[2][1] * s[3][2]);
+    d[3][2] = -(d[0][2] * s[3][0] + d[1][2] * s[3][1] + d[2][2] * s[3][2]);
+    d[3][3] = 1.0f;
+}
+
 static HRESULT WINAPI d3drm_frame3_GetPosition(IDirect3DRMFrame3 *iface,
         IDirect3DRMFrame3 *reference, D3DVECTOR *position)
 {
@@ -1547,23 +1617,37 @@ static HRESULT WINAPI d3drm_frame1_GetTextureTopology(IDirect3DRMFrame *iface, B
 
 static HRESULT WINAPI d3drm_frame3_InverseTransform(IDirect3DRMFrame3 *iface, D3DVECTOR *d, D3DVECTOR *s)
 {
-    FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    D3DRMMATRIX4D m, m2;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, d %p, s %p.\n", iface, d, s);
+
+    matrix_expand(m2, frame, NULL);
+    matrix_invert(m, m2);
+
+    d->u1.x = s->u1.x * m[0][0] + s->u2.y * m[1][0] + s->u3.z * m[2][0] + m[3][0];
+    d->u2.y = s->u1.x * m[0][1] + s->u2.y * m[1][1] + s->u3.z * m[2][1] + m[3][1];
+    d->u3.z = s->u1.x * m[0][2] + s->u2.y * m[1][2] + s->u3.z * m[2][2] + m[3][2];
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_InverseTransform(IDirect3DRMFrame2 *iface, D3DVECTOR *d, D3DVECTOR *s)
 {
-    FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, d %p, s %p.\n", iface, d, s);
+
+    return d3drm_frame3_InverseTransform(&frame->IDirect3DRMFrame3_iface, d, s);
 }
 
 static HRESULT WINAPI d3drm_frame1_InverseTransform(IDirect3DRMFrame *iface, D3DVECTOR *d, D3DVECTOR *s)
 {
-    FIXME("iface %p, d %p, s %p stub!\n", iface, d, s);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, d %p, s %p.\n", iface, d, s);
+
+    return d3drm_frame3_InverseTransform(&frame->IDirect3DRMFrame3_iface, d, s);
 }
 
 static HRESULT WINAPI d3drm_frame3_Load(IDirect3DRMFrame3 *iface, void *filename,
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 76e0ec19fb..1c02d639a0 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -2801,6 +2801,13 @@ static void test_frame_transform(void)
     hr = IDirect3DRMFrame_Transform(subframe, &v2, &v1);
     EXPECT_VECTOR("Transform (subframe)", v2, 92,128,208);
 
+    SET_VECTOR(v1, 70,84,120);
+    hr = IDirect3DRMFrame_InverseTransform(frame, &v2, &v1);
+    EXPECT_VECTOR("InverseTransform", v2, 3,5,7);
+    SET_VECTOR(v1, 92,128,208);
+    hr = IDirect3DRMFrame_InverseTransform(subframe, &v2, &v1);
+    EXPECT_VECTOR("InverseTransform (subframe)", v2, 3,5,7);
+
 
     IDirect3DRMFrame_Release(subframe);
     IDirect3DRMFrame_Release(frame);
-- 
2.14.3




More information about the wine-devel mailing list