Signed-off-by: Jeff Smith whydoubt@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);