diff --git a/dlls/d3dx8/d3dx8.spec b/dlls/d3dx8/d3dx8.spec index d3b0ffaf99f..4e7996a708b 100644 --- a/dlls/d3dx8/d3dx8.spec +++ b/dlls/d3dx8/d3dx8.spec @@ -50,7 +50,7 @@ @ stdcall D3DXMatrixShadow(ptr ptr ptr) @ stdcall D3DXMatrixReflect(ptr ptr) @ stdcall D3DXQuaternionToAxisAngle(ptr ptr ptr) -@ stub D3DXQuaternionRotationMatrix +@ stdcall D3DXQuaternionRotationMatrix(ptr ptr) @ stdcall D3DXQuaternionRotationAxis(ptr ptr long) @ stub D3DXQuaternionRotationYawPitchRoll @ stdcall D3DXQuaternionMultiply(ptr ptr ptr) diff --git a/dlls/d3dx8/math.c b/dlls/d3dx8/math.c index adc100d52d4..f1cbf22c9ba 100644 --- a/dlls/d3dx8/math.c +++ b/dlls/d3dx8/math.c @@ -655,6 +655,57 @@ D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis(D3DXQUATERNION *pout, CONST D3 return pout; } +D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix(D3DXQUATERNION *pout, CONST D3DXMATRIX *pm) +{ + int i, maxi; + FLOAT maxdiag, S, trace; + + trace = pm->u.m[0][0] + pm->u.m[1][1] + pm->u.m[2][2] + 1.0f; + if ( trace > 0.0f) + { + pout->x = ( pm->u.m[1][2] - pm->u.m[2][1] ) / ( 2.0f * sqrt(trace) ); + pout->y = ( pm->u.m[2][0] - pm->u.m[0][2] ) / ( 2.0f * sqrt(trace) ); + pout->z = ( pm->u.m[0][1] - pm->u.m[1][0] ) / ( 2.0f * sqrt(trace) ); + pout->w = sqrt(trace) / 2.0f; + return pout; + } + maxi = 0; + maxdiag = pm->u.m[0][0]; + for (i=1; i<3; i++) + { + if ( pm->u.m[i][i] > maxdiag ) + { + maxi = i; + maxdiag = pm->u.m[i][i]; + } + } + switch( maxi ) + { + case 0: + S = 2.0f * sqrt(1.0f + pm->u.m[0][0] - pm->u.m[1][1] - pm->u.m[2][2]); + pout->x = 0.25f * S; + pout->y = ( pm->u.m[0][1] + pm->u.m[1][0] ) / S; + pout->z = ( pm->u.m[0][2] + pm->u.m[2][0] ) / S; + pout->w = ( pm->u.m[1][2] - pm->u.m[2][1] ) / S; + break; + case 1: + S = 2.0f * sqrt(1.0f + pm->u.m[1][1] - pm->u.m[0][0] - pm->u.m[2][2]); + pout->x = ( pm->u.m[0][1] + pm->u.m[1][0] ) / S; + pout->y = 0.25f * S; + pout->z = ( pm->u.m[1][2] + pm->u.m[2][1] ) / S; + pout->w = ( pm->u.m[2][0] - pm->u.m[0][2] ) / S; + break; + case 2: + S = 2.0f * sqrt(1.0f + pm->u.m[2][2] - pm->u.m[0][0] - pm->u.m[1][1]); + pout->x = ( pm->u.m[0][2] + pm->u.m[2][0] ) / S; + pout->y = ( pm->u.m[1][2] + pm->u.m[2][1] ) / S; + pout->z = 0.25f * S; + pout->w = ( pm->u.m[0][1] - pm->u.m[1][0] ) / S; + break; + } + return pout; +} + D3DXQUATERNION* WINAPI D3DXQuaternionSlerp(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, FLOAT t) { FLOAT dot, epsilon; diff --git a/dlls/d3dx8/tests/math.c b/dlls/d3dx8/tests/math.c index 589bb2ac8b9..6a63fd8fd26 100644 --- a/dlls/d3dx8/tests/math.c +++ b/dlls/d3dx8/tests/math.c @@ -552,6 +552,7 @@ static void D3DXPlaneTest(void) static void D3X8QuaternionTest(void) { + D3DXMATRIX mat; D3DXQUATERNION expectedquat, gotquat, Nq, nul, q, r, s, t, u; LPD3DXQUATERNION funcpointer; D3DXVECTOR3 axis, expectedvec; @@ -668,6 +669,38 @@ static void D3X8QuaternionTest(void) D3DXQuaternionRotationAxis(&gotquat,&axis,angle); expect_vec4(expectedquat,gotquat); +/*_______________D3DXQuaternionRotationMatrix___________________*/ + /* test when the trace is >0 */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = 10.0f; U(mat).m[1][1] = 20.0f; U(mat).m[2][2] = 30.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 2.368682f; expectedquat.y = 0.768221f; expectedquat.z = -0.384111f; expectedquat.w = 3.905125f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_vec4(expectedquat,gotquat); + /* test the case when the greater element is (2,2) */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = -60.0f; U(mat).m[2][2] = 40.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 1.233905f; expectedquat.y = -0.237290f; expectedquat.z = 5.267827f; expectedquat.w = -0.284747f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_vec4(expectedquat,gotquat); + /* test the case when the greater element is (1,1) */ + U(mat).m[0][1] = 5.0f; U(mat).m[0][2] = 7.0f; U(mat).m[0][3] = 8.0f; + U(mat).m[1][0] = 11.0f; U(mat).m[1][2] = 16.0f; U(mat).m[1][3] = 33.0f; + U(mat).m[2][0] = 19.0f; U(mat).m[2][1] = -21.0f; U(mat).m[2][3] = 43.0f; + U(mat).m[3][0] = 2.0f; U(mat).m[3][1] = 3.0f; U(mat).m[3][2] = -4.0f; + U(mat).m[0][0] = -10.0f; U(mat).m[1][1] = 60.0f; U(mat).m[2][2] = -80.0f; + U(mat).m[3][3] = 48.0f; + expectedquat.x = 0.651031f; expectedquat.y = 6.144103f; expectedquat.z = -0.203447f; expectedquat.w = 0.488273f; + D3DXQuaternionRotationMatrix(&gotquat,&mat); + expect_vec4(expectedquat,gotquat); + /*_______________D3DXQuaternionSlerp________________________*/ expectedquat.x = -0.2f; expectedquat.y = 2.6f; expectedquat.z = 1.3f; expectedquat.w = 9.1f; D3DXQuaternionSlerp(&gotquat,&q,&r,scale); diff --git a/include/d3dx8math.h b/include/d3dx8math.h index c5f18a2afd9..f9bc7773f99 100644 --- a/include/d3dx8math.h +++ b/include/d3dx8math.h @@ -307,6 +307,7 @@ D3DXQUATERNION* WINAPI D3DXQuaternionInverse(D3DXQUATERNION *pout, CONST D3DXQUA D3DXQUATERNION* WINAPI D3DXQuaternionMultiply(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2); D3DXQUATERNION* WINAPI D3DXQuaternionNormalize(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq); D3DXQUATERNION* WINAPI D3DXQuaternionRotationAxis(D3DXQUATERNION *pout, CONST D3DXVECTOR3 *pv, FLOAT angle); +D3DXQUATERNION* WINAPI D3DXQuaternionRotationMatrix(D3DXQUATERNION *pout, CONST D3DXMATRIX *pm); D3DXQUATERNION* WINAPI D3DXQuaternionSlerp(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, FLOAT t); D3DXQUATERNION* WINAPI D3DXQuaternionSquad(D3DXQUATERNION *pout, CONST D3DXQUATERNION *pq1, CONST D3DXQUATERNION *pq2, CONST D3DXQUATERNION *pq3, CONST D3DXQUATERNION *pq4, FLOAT t); void WINAPI D3DXQuaternionToAxisAngle(CONST D3DXQUATERNION *pq, D3DXVECTOR3 *paxis, FLOAT *pangle);