[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