From 5be7be5dbf1adb00c8763f7b7a7b4205ae5e93be Mon Sep 17 00:00:00 2001
From: David Adam <david.adam.cnrs@gmail.com>
Date: Wed, 4 Feb 2009 09:26:12 +0100
Subject: Try of implementation of D3DXComputeSphereBounding

---
 dlls/d3dx8/d3dx8.spec   |    2 +-
 dlls/d3dx8/mesh.c       |   35 +++++++++++++++++++++++++++++++++++
 dlls/d3dx8/tests/mesh.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 include/d3dx8mesh.h     |    1 +
 4 files changed, 83 insertions(+), 1 deletions(-)

diff --git a/dlls/d3dx8/d3dx8.spec b/dlls/d3dx8/d3dx8.spec
index 3ee6f1b..ff9ec79 100644
--- a/dlls/d3dx8/d3dx8.spec
+++ b/dlls/d3dx8/d3dx8.spec
@@ -92,7 +92,7 @@
 @ stub D3DXValidMesh
 @ stub D3DXGeneratePMesh
 @ stub D3DXSimplifyMesh
-@ stub D3DXComputeBoundingSphere
+@ stdcall D3DXComputeBoundingSphere(ptr long long ptr ptr)
 @ stub D3DXComputeBoundingBox
 @ stub D3DXComputeNormals
 @ stdcall D3DXCreateBuffer(long ptr)
diff --git a/dlls/d3dx8/mesh.c b/dlls/d3dx8/mesh.c
index 88e9b87..65cae83 100644
--- a/dlls/d3dx8/mesh.c
+++ b/dlls/d3dx8/mesh.c
@@ -20,6 +20,8 @@
 #include "wingdi.h"
 #include "d3dx8.h"
 
+#include "stdio.h"
+
 BOOL WINAPI D3DXBoxBoundProbe(CONST D3DXVECTOR3 *pmin, CONST D3DXVECTOR3 *pmax, CONST D3DXVECTOR3 *prayposition, CONST D3DXVECTOR3 *praydirection)
 
 /* Algorithm taken from the article: An Efficient and Robust Ray-Box Intersection Algoritm
@@ -90,6 +92,39 @@ done we've got an intersection of the ray with the box.
     return TRUE;
 }
 
+HRESULT WINAPI D3DXComputeBoundingSphere(PVOID ppointsFVF, DWORD numvertices, DWORD FVF, D3DXVECTOR3 *pcenter, FLOAT *pradius)
+{
+    D3DXVECTOR3 temp, temp1;
+    FLOAT d;
+    unsigned int i;
+
+    if( !ppointsFVF || !pcenter || !pradius ) return D3DERR_INVALIDCALL;
+
+    temp.x = 0.0f;
+    temp.y = 0.0f;
+    temp.z = 0.0f;
+    temp1 = temp;
+    d = 0.0f;
+    *pradius = 0.0f;
+
+    for(i=0; i<numvertices; i++)
+    {
+        D3DXVec3Add(&temp1, &temp, (D3DXVECTOR3*)((char*)ppointsFVF + FVF * i));
+        temp = temp1;
+    }
+
+    D3DXVec3Scale(pcenter, &temp, 1.0f/((FLOAT)numvertices));
+
+    for(i=0; i<numvertices; i++)
+    {
+        temp = *((D3DXVECTOR3*)((char*)ppointsFVF + FVF * i));
+        printf("temp[%d]= (%f, %f, %f)\n",i,temp.x, temp.y,temp.z);
+        d = D3DXVec3Length(D3DXVec3Subtract(&temp, (D3DXVECTOR3*)((char*)ppointsFVF + FVF * i), pcenter)); 
+        if ( d > *pradius ) *pradius = d;
+    }
+    return D3D_OK;
+}
+
 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;
diff --git a/dlls/d3dx8/tests/mesh.c b/dlls/d3dx8/tests/mesh.c
index 967f3c9..4099a59 100644
--- a/dlls/d3dx8/tests/mesh.c
+++ b/dlls/d3dx8/tests/mesh.c
@@ -27,6 +27,11 @@ BOOL compare(FLOAT u, FLOAT v)
     return (fabs(u-v) < admitted_error);
 }
 
+BOOL compare_vec3(D3DXVECTOR3 u, D3DXVECTOR3 v)
+{
+    return ( compare(u.x, v.x) && compare(u.y, v.y) && compare(u.z, v.z) );
+}
+
 static void D3DXBoundProbeTest(void)
 {
     BOOL result;
@@ -101,6 +106,46 @@ static void D3DXBoundProbeTest(void)
     ok(result == FALSE, "expected FALSE, received TRUE\n");
 }
 
+static void D3DXComputeBoundingSphereTest()
+{
+    D3DXVECTOR3 exp_cen, got_cen, vertex[5];
+    FLOAT exp_rad, got_rad;
+    HRESULT hr;
+
+    vertex[0].x = 1.0f; vertex[0].y = 1.0f; vertex[0].z = 1.0f;
+    vertex[1].x = 1.0f; vertex[1].y = 1.0f; vertex[1].z = 1.0f;
+    vertex[2].x = 1.0f; vertex[2].y = 1.0f; vertex[2].z = 1.0f;
+    vertex[3].x = 1.0f; vertex[3].y = 1.0f; vertex[3].z = 1.0f;
+    vertex[4].x = 9.0f; vertex[4].y = 9.0f; vertex[4].z = 9.0f;
+
+    exp_rad = 6.928203f;
+    exp_cen.x = 5.0; exp_cen.y = 5.0; exp_cen.z = 5.0;
+
+    hr = D3DXComputeBoundingSphere((D3DXVECTOR3*)&vertex[3],2,sizeof(D3DXVECTOR3),&got_cen,&got_rad);
+
+    ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+    ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
+    ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z);
+
+/*________________________*/
+
+    vertex[0].x = 2.0f; vertex[0].y = 5.9f; vertex[0].z = -1.2f;
+    vertex[1].x = -1.87f; vertex[1].y = 7.9f; vertex[1].z = 7.4f;
+    vertex[2].x = 7.43f; vertex[2].y = -0.9f; vertex[2].z = 11.9f;
+    vertex[3].x = -6.92f; vertex[3].y = 6.3f; vertex[3].z = -3.8f;
+    vertex[4].x = 11.4f; vertex[4].y = -8.1f; vertex[4].z = 4.5f;
+
+    exp_rad = 13.707883f;
+    exp_cen.x = 2.408f; exp_cen.y = 2.22f; exp_cen.z = 3.76f;
+
+    hr = D3DXComputeBoundingSphere((D3DXVECTOR3*)&vertex[0],5,sizeof(D3DXVECTOR3),&got_cen,&got_rad);
+
+    ok( hr == D3D_OK, "Expected D3D_OK, got %#x\n", hr);
+    ok( compare(exp_rad, got_rad), "Expected radius: %f, got radius: %f\n", exp_rad, got_rad);
+    ok( compare_vec3(exp_cen,got_cen), "Expected center: (%f, %f, %f), got center: (%f, %f, %f)\n", exp_cen.x,exp_cen.y,exp_cen.z,got_cen.x,got_cen.y,got_cen.z);
+    
+}
+
 static void D3DXIntersectTriTest(void)
 {
     BOOL exp_res, got_res;
@@ -157,5 +202,6 @@ static void D3DXIntersectTriTest(void)
 START_TEST(mesh)
 {
     D3DXBoundProbeTest();
+    D3DXComputeBoundingSphereTest();
     D3DXIntersectTriTest();
 }
diff --git a/include/d3dx8mesh.h b/include/d3dx8mesh.h
index 8cdb166..ba88522 100644
--- a/include/d3dx8mesh.h
+++ b/include/d3dx8mesh.h
@@ -31,6 +31,7 @@ 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 *);
+HRESULT WINAPI D3DXComputeBoundingSphere(PVOID ppointsFVF, DWORD numvertices,   DWORD FVF, D3DXVECTOR3 *pcenter, FLOAT *pradius);
 
 #ifdef __cplusplus
 }
-- 
1.6.0.2

