From: Jeff Smith Subject: [PATCH 08/12] d3drm: Implement frame position/orientation methods Message-Id: <20190614042737.13992-8-whydoubt@gmail.com> Date: Thu, 13 Jun 2019 23:27:33 -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 | 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