From b8eb4cf861b9b0825de7d9f5a15e38c01e5ba2fe Mon Sep 17 00:00:00 2001 From: David Adam Date: Tue, 3 Feb 2009 09:41:12 +0100 Subject: [PATCH] d3dx8: Implement D3DXIntersectTri. --- dlls/d3dx8/d3dx8.spec | 1 + dlls/d3dx8/mesh.c | 42 +++++++++++++++++++++++++ dlls/d3dx8/tests/mesh.c | 61 +++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx9_36.spec | 2 +- include/d3dx8mesh.h | 1 + 5 files changed, 106 insertions(+), 1 deletion(-) diff --git a/dlls/d3dx8/d3dx8.spec b/dlls/d3dx8/d3dx8.spec index 036a510244b..3ee6f1b091f 100644 --- a/dlls/d3dx8/d3dx8.spec +++ b/dlls/d3dx8/d3dx8.spec @@ -109,6 +109,7 @@ @ stub D3DXFVFFromDeclarator @ stub D3DXWeldVertices @ stub D3DXIntersect +@ cdecl D3DXIntersectTri(ptr ptr ptr ptr ptr ptr ptr ptr) @ stdcall D3DXSphereBoundProbe(ptr long ptr ptr) @ stdcall D3DXBoxBoundProbe(ptr ptr ptr ptr) @ stub D3DXCreatePolygon diff --git a/dlls/d3dx8/mesh.c b/dlls/d3dx8/mesh.c index c1d242bf07c..88e9b87867f 100644 --- a/dlls/d3dx8/mesh.c +++ b/dlls/d3dx8/mesh.c @@ -90,6 +90,48 @@ done we've got an intersection of the ray with the box. return TRUE; } +BOOL CDECL D3DXIntersectTri(CONST D3DXVECTOR3 *p0, CONST D3DXVECTOR3 *p1, CONST D3DXVECTOR3 *p2, CONST D3DXVECTOR3 *praypos, CONST D3DXVECTOR3 *praydir, FLOAT *pu, FLOAT *pv, FLOAT *pdist) +{ + D3DXMATRIX m; + D3DXVECTOR4 vec; + + m.m[0][0] = p1->x - p0->x; + m.m[1][0] = p2->x - p0->x; + m.m[2][0] = -praydir->x; + m.m[3][0] = 0.0f; + m.m[0][1] = p1->y - p0->z; + m.m[1][1] = p2->y - p0->z; + m.m[2][1] = -praydir->y; + m.m[3][1] = 0.0f; + m.m[0][2] = p1->z - p0->z; + m.m[1][2] = p2->z - p0->z; + m.m[2][2] = -praydir->z; + m.m[3][2] = 0.0f; + m.m[0][3] = 0.0f; + m.m[1][3] = 0.0f; + m.m[2][3] = 0.0f; + m.m[3][3] = 1.0f; + + vec.x = praypos->x - p0->x; + vec.y = praypos->y - p0->y; + vec.z = praypos->z - p0->z; + vec.w = 0.0f; + + if ( D3DXMatrixInverse(&m, NULL, &m) ) + { + D3DXVec4Transform(&vec, &vec, &m); + if ( (vec.x >= 0.0f) && (vec.y >= 0.0f) && (vec.x + vec.y <= 1.0f) && (vec.z >= 0.0f) ) + { + *pu = vec.x; + *pv = vec.y; + *pdist = fabs( vec.z ); + return TRUE; + } + } + +return FALSE; +} + BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *pcenter, FLOAT radius, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection) { D3DXVECTOR3 difference; diff --git a/dlls/d3dx8/tests/mesh.c b/dlls/d3dx8/tests/mesh.c index e3370de036e..967f3c9c941 100644 --- a/dlls/d3dx8/tests/mesh.c +++ b/dlls/d3dx8/tests/mesh.c @@ -20,6 +20,13 @@ #include "wine/test.h" +#define admitted_error 0.0001f + +BOOL compare(FLOAT u, FLOAT v) +{ + return (fabs(u-v) < admitted_error); +} + static void D3DXBoundProbeTest(void) { BOOL result; @@ -94,7 +101,61 @@ static void D3DXBoundProbeTest(void) ok(result == FALSE, "expected FALSE, received TRUE\n"); } +static void D3DXIntersectTriTest(void) +{ + BOOL exp_res, got_res; + D3DXVECTOR3 position, ray, vertex[3]; + FLOAT exp_dist, got_dist, exp_u, got_u, exp_v, got_v; + + vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; + + position.x = -14.5f; position.y = -23.75f; position.z = -32.0f; + + ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; + + exp_res = TRUE; exp_u = 0.5f; exp_v = 0.25f; exp_dist = 8.0f; + + got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); + ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); + ok( compare(exp_u,got_u), "Expected u = %f, got %f\n",exp_u,got_u); + ok( compare(exp_v,got_v), "Expected v = %f, got %f\n",exp_v,got_v); + ok( compare(exp_dist,got_dist), "Expected distance = %f, got %f\n",exp_dist,got_dist); + +/*Only positive ray is taken in account*/ + + vertex[0].x = 1.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 2.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 0.0f; + + position.x = 17.5f; position.y = 24.25f; position.z = 32.0f; + + ray.x = 2.0f; ray.y = 3.0f; ray.z = 4.0f; + + exp_res = FALSE; + + got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); + ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); + +/*Intersection between ray and triangle in a same plane is considered as empty*/ + + vertex[0].x = 4.0f; vertex[0].y = 0.0f; vertex[0].z = 0.0f; + vertex[1].x = 6.0f; vertex[1].y = 0.0f; vertex[1].z = 0.0f; + vertex[2].x = 4.0f; vertex[2].y = 2.0f; vertex[2].z = 0.0f; + + position.x = 1.0f; position.y = 1.0f; position.z = 0.0f; + + ray.x = 1.0f; ray.y = 0.0f; ray.z = 0.0f; + + exp_res = FALSE; + + got_res = D3DXIntersectTri(&vertex[0],&vertex[1],&vertex[2],&position,&ray,&got_u,&got_v,&got_dist); + ok( got_res == exp_res, "Expected result = %d, got %d\n",exp_res,got_res); +} + START_TEST(mesh) { D3DXBoundProbeTest(); + D3DXIntersectTriTest(); } diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec index d7fba368b55..ab198ab1a4f 100644 --- a/dlls/d3dx9_36/d3dx9_36.spec +++ b/dlls/d3dx9_36/d3dx9_36.spec @@ -167,7 +167,7 @@ @ stdcall D3DXGetVertexShaderProfile(ptr) @ stdcall D3DXIntersect(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) d3dx8.D3DXIntersect @ stdcall D3DXIntersectSubset(ptr long ptr ptr ptr ptr ptr ptr ptr ptr ptr) d3dx8.D3DXIntersectSubset -@ stdcall D3DXIntersectTri(ptr ptr ptr ptr ptr ptr ptr ptr) d3dx8.D3DXIntersectTri +@ stub D3DXIntersectTri @ stub D3DXLoadMeshFromXA @ stub D3DXLoadMeshFromXInMemory @ stub D3DXLoadMeshFromXResource diff --git a/include/d3dx8mesh.h b/include/d3dx8mesh.h index 0d399ea529e..8cdb166b69a 100644 --- a/include/d3dx8mesh.h +++ b/include/d3dx8mesh.h @@ -30,6 +30,7 @@ HRESULT WINAPI D3DXCreateBuffer(DWORD,LPD3DXBUFFER*); UINT WINAPI D3DXGetFVFVertexSize(DWORD); BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *); BOOL WINAPI D3DXSphereBoundProbe(CONST D3DXVECTOR3 *,FLOAT,CONST D3DXVECTOR3 *,CONST D3DXVECTOR3 *); +BOOL CDECL D3DXIntersectTri(CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, CONST D3DXVECTOR3 *, FLOAT *, FLOAT *, FLOAT *); #ifdef __cplusplus }