From: Jeff Smith Subject: [PATCH 12/12] d3drm: Implement frame LookAt Message-Id: <20190614042737.13992-12-whydoubt@gmail.com> Date: Thu, 13 Jun 2019 23:27:37 -0500 In-Reply-To: <20190614042737.13992-1-whydoubt@gmail.com> References: <20190614042737.13992-1-whydoubt@gmail.com> Signed-off-by: Jeff Smith --- 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