From 22bfd1396c72e113fadaf1b5cfa746cd22d84be7 Mon Sep 17 00:00:00 2001 From: David Adam Date: Thu, 26 Feb 2009 08:55:07 +0100 Subject: [PATCH] ddraw: Implement ComputeSphereVisibility. --- dlls/ddraw/ddraw_private.h | 2 + dlls/ddraw/device.c | 96 ++++++++++++++++++------ dlls/ddraw/tests/d3d.c | 180 +++++++++++++++++++++++++++++---------------- dlls/ddraw/utils.c | 25 +++++++ 4 files changed, 217 insertions(+), 86 deletions(-) diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 8b401d5ccfe..27261a1c5f6 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -722,6 +722,8 @@ void DDRAW_dump_cooperativelevel(DWORD cooplevel); * IDirect3DExecuteBuffer isn't in WineD3D */ void multiply_matrix(LPD3DMATRIX dest, const D3DMATRIX *src1, const D3DMATRIX *src2); +void multiply_matrix_D3D_way(LPD3DMATRIX result, const D3DMATRIX *m1, const D3DMATRIX *m2); + /* Helper function in main.c */ BOOL LoadWineD3D(void); diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index d97b7447b5f..8f8437457e4 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -4593,6 +4593,19 @@ Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB(IDirect3DDevice3 *iface, * is singular) * *****************************************************************************/ + +static DWORD in_plane(UINT plane, D3DVECTOR normal, D3DVALUE origin_plane, D3DVECTOR center, D3DVALUE radius) +{ + float distance, norm; + + norm = sqrt( normal.u1.x * normal.u1.x + normal.u2.y * normal.u2.y + normal.u3.z * normal.u3.z ); + distance = ( origin_plane + normal.u1.x * center.u1.x + normal.u2.y * center.u2.y + normal.u3.z * center.u3.z ) / norm; + + if ( fabs( distance ) < radius ) return D3DSTATUS_CLIPUNIONLEFT << plane; + if ( distance < -radius ) return (D3DSTATUS_CLIPUNIONLEFT | D3DSTATUS_CLIPINTERSECTIONLEFT) << plane; + return 0; +} + static HRESULT WINAPI IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface, D3DVECTOR *Centers, @@ -4601,30 +4614,65 @@ IDirect3DDeviceImpl_7_ComputeSphereVisibility(IDirect3DDevice7 *iface, DWORD Flags, DWORD *ReturnValues) { - IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface; - FIXME("(%p)->(%p,%p,%08x,%08x,%p): stub!\n", This, Centers, Radii, NumSpheres, Flags, ReturnValues); - - /* the DirectX 7 sdk says that the visibility is computed by - * back-transforming the viewing frustum to model space - * using the inverse of the combined world, view and projection - * matrix. If the matrix can't be reversed, D3DERR_INVALIDMATRIX - * is returned. - * - * Basic implementation idea: - * 1) Check if the center is in the viewing frustum - * 2) Cut the sphere with the planes of the viewing - * frustum - * - * ->Center inside the frustum, no intersections: - * Fully visible - * ->Center outside the frustum, no intersections: - * Not visible - * ->Some intersections: Partially visible - * - * Implement this call in WineD3D. Either implement the - * matrix and vector stuff in WineD3D, or use some external - * math library. - */ + D3DMATRIX m, temp; + D3DVALUE origin_plane[6]; + D3DVECTOR vec[6]; + HRESULT hr; + UINT i, j; + + TRACE("(%p)->(%p,%p,%08x,%08x,%p)\n", iface, Centers, Radii, NumSpheres, Flags, ReturnValues); + + hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_WORLD, &m); + if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; + hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_VIEW, &temp); + if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; + multiply_matrix_D3D_way(&m, &m, &temp); + + hr = IDirect3DDeviceImpl_7_GetTransform(iface, D3DTRANSFORMSTATE_PROJECTION, &temp); + if ( hr != DD_OK ) return DDERR_INVALIDPARAMS; + multiply_matrix_D3D_way(&m, &m, &temp); + +/* Left plane */ + vec[0].u1.x = m._14 + m._11; + vec[0].u2.y = m._24 + m._21; + vec[0].u3.z = m._34 + m._31; + origin_plane[0] = m._44 + m._41; + +/* Right plane */ + vec[1].u1.x = m._14 - m._11; + vec[1].u2.y = m._24 - m._21; + vec[1].u3.z = m._34 - m._31; + origin_plane[1] = m._44 - m._41; + +/* Top plane */ + vec[2].u1.x = m._14 - m._12; + vec[2].u2.y = m._24 - m._22; + vec[2].u3.z = m._34 - m._32; + origin_plane[2] = m._44 - m._42; + +/* Bottom plane */ + vec[3].u1.x = m._14 + m._12; + vec[3].u2.y = m._24 + m._22; + vec[3].u3.z = m._34 + m._32; + origin_plane[3] = m._44 + m._42; + +/* Front plane */ + vec[4].u1.x = m._13; + vec[4].u2.y = m._23; + vec[4].u3.z = m._33; + origin_plane[4] = m._43; + +/* Back plane*/ + vec[5].u1.x = m._14 - m._13; + vec[5].u2.y = m._24 - m._23; + vec[5].u3.z = m._34 - m._33; + origin_plane[5] = m._44 - m._43; + + for(i=0; i_11 * m2->_11 + m1->_12 * m2->_21 + m1->_13 * m2->_31 + m1->_14 * m2->_41; + temp._12 = m1->_11 * m2->_12 + m1->_12 * m2->_22 + m1->_13 * m2->_32 + m1->_14 * m2->_42; + temp._13 = m1->_11 * m2->_13 + m1->_12 * m2->_23 + m1->_13 * m2->_33 + m1->_14 * m2->_43; + temp._14 = m1->_11 * m2->_14 + m1->_12 * m2->_24 + m1->_13 * m2->_34 + m1->_14 * m2->_44; + temp._21 = m1->_21 * m2->_11 + m1->_22 * m2->_21 + m1->_23 * m2->_31 + m1->_24 * m2->_41; + temp._22 = m1->_21 * m2->_12 + m1->_22 * m2->_22 + m1->_23 * m2->_32 + m1->_24 * m2->_42; + temp._23 = m1->_21 * m2->_13 + m1->_22 * m2->_23 + m1->_23 * m2->_33 + m1->_24 * m2->_43; + temp._24 = m1->_21 * m2->_14 + m1->_22 * m2->_24 + m1->_23 * m2->_34 + m1->_24 * m2->_44; + temp._31 = m1->_31 * m2->_11 + m1->_32 * m2->_21 + m1->_33 * m2->_31 + m1->_34 * m2->_41; + temp._32 = m1->_31 * m2->_12 + m1->_32 * m2->_22 + m1->_33 * m2->_32 + m1->_34 * m2->_42; + temp._33 = m1->_31 * m2->_13 + m1->_32 * m2->_23 + m1->_33 * m2->_33 + m1->_34 * m2->_43; + temp._34 = m1->_31 * m2->_14 + m1->_32 * m2->_24 + m1->_33 * m2->_34 + m1->_34 * m2->_44; + temp._41 = m1->_41 * m2->_11 + m1->_42 * m2->_21 + m1->_43 * m2->_31 + m1->_44 * m2->_41; + temp._42 = m1->_41 * m2->_12 + m1->_42 * m2->_22 + m1->_43 * m2->_32 + m1->_44 * m2->_42; + temp._43 = m1->_41 * m2->_13 + m1->_42 * m2->_23 + m1->_43 * m2->_33 + m1->_44 * m2->_43; + temp._44 = m1->_41 * m2->_14 + m1->_42 * m2->_24 + m1->_43 * m2->_34 + m1->_44 * m2->_44; + + *result = temp; + + return; +} HRESULT hr_ddraw_from_wined3d(HRESULT hr) -- 2.11.4.GIT