[PATCH 12/12] d3drm: Implement frame LookAt

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


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

diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c
index cccd0f9e15..9ca32916fe 100644
--- a/dlls/d3drm/frame.c
+++ b/dlls/d3drm/frame.c
@@ -1945,25 +1945,110 @@ static HRESULT WINAPI d3drm_frame1_Load(IDirect3DRMFrame *iface, void *filename,
 static HRESULT WINAPI d3drm_frame3_LookAt(IDirect3DRMFrame3 *iface, IDirect3DRMFrame3 *target,
         IDirect3DRMFrame3 *reference, D3DRMFRAMECONSTRAINT constraint)
 {
-    FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame3(iface);
+    struct d3drm_frame *tar = unsafe_impl_from_IDirect3DRMFrame3(target);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame3(reference);
+    D3DVECTOR dir, up, right;
 
-    return E_NOTIMPL;
+    TRACE("iface %p, target %p, reference %p, constraint %#x.\n", iface, target, reference, constraint);
+
+    if (!tar)
+        return D3DRMERR_BADOBJECT;
+
+    dir.u1.x = tar->transform[3][0] - frame->transform[3][0];
+    dir.u2.y = tar->transform[3][1] - frame->transform[3][1];
+    dir.u3.z = tar->transform[3][2] - frame->transform[3][2];
+
+    if (ref)
+    {
+        D3DRMMATRIX4D m;
+        D3DVECTOR v;
+
+        matrix_invert(m, ref->transform);
+        memcpy(&v, &dir, sizeof(D3DVECTOR));
+        dir.u1.x = m[0][0] * v.u1.x + m[1][0] * v.u2.y + m[2][0] * v.u3.z;
+        dir.u2.y = m[0][1] * v.u1.x + m[1][1] * v.u2.y + m[2][1] * v.u3.z;
+        dir.u3.z = m[0][2] * v.u1.x + m[1][2] * v.u2.y + m[2][2] * v.u3.z;
+    }
+
+    D3DRMVectorNormalize(&dir);
+
+    switch (constraint)
+    {
+        case D3DRMCONSTRAIN_Z:
+            right.u1.x = dir.u3.z;
+            right.u2.y = 0.0f;
+            right.u3.z = -dir.u1.x;
+            D3DRMVectorNormalize(&right);
+            D3DRMVectorCrossProduct(&up, &dir, &right);
+            break;
+        case D3DRMCONSTRAIN_Y:
+            right.u1.x = dir.u2.y;
+            right.u2.y = -dir.u1.x;
+            right.u3.z = 0.0f;
+            D3DRMVectorNormalize(&right);
+            D3DRMVectorCrossProduct(&up, &dir, &right);
+            break;
+        case D3DRMCONSTRAIN_X:
+            up.u1.x = -dir.u2.y;
+            up.u2.y = dir.u1.x;
+            up.u3.z = 0.0f;
+            D3DRMVectorNormalize(&up);
+            D3DRMVectorCrossProduct(&right, &up, &dir);
+            break;
+        default:
+            WARN("Unknown Constraint %u\n", constraint);
+            return D3DRMERR_BADVALUE;
+    }
+
+    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)
+    {
+        D3DRMMATRIX4D m;
+        memcpy(m, frame->transform, sizeof(D3DRMMATRIX4D));
+        matrix_multiply_orient(frame->transform, ref->transform, m);
+    }
+
+    return D3DRM_OK;
 }
 
 static HRESULT WINAPI d3drm_frame2_LookAt(IDirect3DRMFrame2 *iface, IDirect3DRMFrame *target,
         IDirect3DRMFrame *reference, D3DRMFRAMECONSTRAINT constraint)
 {
-    FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame2(iface);
+    struct d3drm_frame *tar = unsafe_impl_from_IDirect3DRMFrame(target);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, target %p, reference %p, constraint %#x.\n", iface, target, reference, constraint);
+
+    return d3drm_frame3_LookAt(&frame->IDirect3DRMFrame3_iface,
+            (tar) ? &tar->IDirect3DRMFrame3_iface : NULL,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            constraint);
 }
 
 static HRESULT WINAPI d3drm_frame1_LookAt(IDirect3DRMFrame *iface, IDirect3DRMFrame *target,
         IDirect3DRMFrame *reference, D3DRMFRAMECONSTRAINT constraint)
 {
-    FIXME("iface %p, target %p, reference %p, constraint %#x stub!\n", iface, target, reference, constraint);
+    struct d3drm_frame *frame = impl_from_IDirect3DRMFrame(iface);
+    struct d3drm_frame *tar = unsafe_impl_from_IDirect3DRMFrame(target);
+    struct d3drm_frame *ref = unsafe_impl_from_IDirect3DRMFrame(reference);
 
-    return E_NOTIMPL;
+    TRACE("iface %p, target %p, reference %p, constraint %#x.\n", iface, target, reference, constraint);
+
+    return d3drm_frame3_LookAt(&frame->IDirect3DRMFrame3_iface,
+            (tar) ? &tar->IDirect3DRMFrame3_iface : NULL,
+            (ref) ? &ref->IDirect3DRMFrame3_iface : NULL,
+            constraint);
 }
 
 static HRESULT WINAPI d3drm_frame3_Move(IDirect3DRMFrame3 *iface, D3DVALUE delta)
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 1e41023f8f..60f0da8001 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -2824,7 +2824,7 @@ static void test_frame_transform(void)
 {
     HRESULT hr;
     IDirect3DRM *d3drm;
-    IDirect3DRMFrame *frame, *subframe, *reference;
+    IDirect3DRMFrame *frame, *subframe, *reference, *target;
     IDirect3DRMFrame3 *frame3, *subframe3, *reference3;
     D3DRMMATRIX4D matrix;
     D3DVECTOR v1, v2;
@@ -3036,9 +3036,39 @@ static void test_frame_transform(void)
     ok(hr == D3DRMERR_BADVALUE, "InverseTransformVectors: BADVALUE error expected when reference == self\n");
 
 
+    hr = IDirect3DRM_CreateFrame(d3drm, frame, &target);
+    IDirect3DRMFrame_AddTransform(frame, D3DRMCOMBINE_REPLACE, identity);
+    IDirect3DRMFrame_AddTranslation(target, D3DRMCOMBINE_REPLACE, 0.0f, 3.0f, 2.0f);
+    IDirect3DRMFrame_AddTranslation(subframe, D3DRMCOMBINE_REPLACE, 3.0f, 6.0f, 4.0f);
+    SET_TRANSFORM(reference, 1,3,2, 4,5,6, 7,8,9, 2,4,3);
+
+    hr = IDirect3DRMFrame_LookAt(subframe, target, reference, D3DRMCONSTRAIN_Z);
+    EXPECT_TRANSFORM("GetTransform (constrain Z)", subframe,
+            -0.757679,3.39217,1.385316, -3.848481,7.797251,1.179861, -6.681523,11.993283,2.349128, 3,6,4);
+
+    hr = IDirect3DRMFrame_LookAt(subframe, target, reference, D3DRMCONSTRAIN_Y);
+    EXPECT_TRANSFORM("GetTransform (constrain Y)", subframe,
+            1.008568,0.005039,-3.603161, 3.700569,2.467296,-7.564274, 6.581180,3.546424,-11.752062, 3,6,4);
+
+    hr = IDirect3DRMFrame_LookAt(subframe, target, reference, D3DRMCONSTRAIN_X);
+    EXPECT_TRANSFORM("GetTransform (constrain X)", subframe,
+            -3.112735,0.623119,-1.980556, -5.295893,1.830544,-6.752972, -8.360264,2.098992,-10.94076, 3,6,4);
+
+    hr = IDirect3DRMFrame_LookAt(subframe, target, NULL, D3DRMCONSTRAIN_Z);
+    EXPECT_TRANSFORM("GetTransform (vs. NULL)", subframe,
+            -0.5547,0,0.83205, -0.532181,0.768706,-0.354787, -0.639602,-0.639602,-0.426401, 3,6,4);
+
+    hr = IDirect3DRMFrame_LookAt(subframe, NULL, reference, D3DRMCONSTRAIN_Z);
+    ok(hr == D3DRMERR_BADOBJECT, "InverseTransformVectors: BADOBJECT error expected when target is null\n");
+
+    hr = IDirect3DRMFrame_LookAt(subframe, target, reference, (D3DRMFRAMECONSTRAINT)-1);
+    ok(hr == D3DRMERR_BADVALUE, "InverseTransformVectors: BADVALUE error expected when constraint invalid\n");
+
+
     IDirect3DRMFrame3_Release(reference3);
     IDirect3DRMFrame3_Release(subframe3);
     IDirect3DRMFrame3_Release(frame3);
+    IDirect3DRMFrame_Release(target);
     IDirect3DRMFrame_Release(reference);
     IDirect3DRMFrame_Release(subframe);
     IDirect3DRMFrame_Release(frame);
-- 
2.14.3




More information about the wine-devel mailing list