天行健 君子当自强而不息

DirectX 9的一些数学计算函数:矩阵,坐标变换。


向量的运算已超了传统意义上的数的运算,因为向量并不是一般的数字。这意味着一切可用符号表示出来的事物,都可以对其进行各种关系运算,而不必关心事物的本身。这种符号运算的观点,推动了近代数学对一般的集合元素进行的抽象代数方面的研究。

在线性方程组的求解上,变元较少的方程组(如仅有两个未知数x和y的方程组)的解很容易表达出来,但是推广到较为复杂的更多变元的情形,如何推测方程组的解以及如何用确定的式子表达出来,引发了对行列式的提出和研究。行列式实质上是方阵数据的一种运算,由此自然地想到,可对一般行列数据定义代数运算,就像对向量定义运算一样,这就是矩阵运算的产生历史。

由于DirectX三维游戏的开发仅需要应用4x4矩阵的计算,因此,DirectX 9在d3dx9math.h文件中定义了对应于4x4矩阵的D3DMATRIX结构体和一个提供了4X4矩阵的各种运算处理的D3DXMATRIX类。

typedef struct _D3DMATRIX {
    union {
        
struct {
            
float        _11, _12, _13, _14;
            
float        _21, _22, _23, _24;
            
float        _31, _32, _33, _34;
            
float        _41, _42, _43, _44;

        };
        
float m[4][4];
    };
} D3DMATRIX;

typedef 
struct D3DXMATRIX : public D3DMATRIX
{
public:
    D3DXMATRIX() {};
    D3DXMATRIX( CONST FLOAT 
* );
    D3DXMATRIX( CONST D3DMATRIX
& );
    D3DXMATRIX( CONST D3DXFLOAT16 
* );
    D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,
                FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,
                FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,
                FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );


    
// access grants
    FLOAT& operator () ( UINT Row, UINT Col );
    FLOAT  
operator () ( UINT Row, UINT Col ) const;

    
// casting operators
    operator FLOAT* ();
    
operator CONST FLOAT* () const;

    
// assignment operators
    D3DXMATRIX& operator *= ( CONST D3DXMATRIX& );
    D3DXMATRIX
& operator += ( CONST D3DXMATRIX& );
    D3DXMATRIX
& operator -= ( CONST D3DXMATRIX& );
    D3DXMATRIX
& operator *= ( FLOAT );
    D3DXMATRIX
& operator /= ( FLOAT );

    
// unary operators
    D3DXMATRIX operator + () const;
    D3DXMATRIX 
operator - () const;

    
// binary operators
    D3DXMATRIX operator * ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX 
operator + ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX 
operator - ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX 
operator * ( FLOAT ) const;
    D3DXMATRIX 
operator / ( FLOAT ) const;

    friend D3DXMATRIX 
operator * ( FLOAT, CONST D3DXMATRIX& );

    BOOL 
operator == ( CONST D3DXMATRIX& ) const;
    BOOL 
operator != ( CONST D3DXMATRIX& ) const;

} D3DXMATRIX, 
*LPD3DXMATRIX;

要正确运行以下的示例程序,需要在工程中包含d3dx9.lib,或者在main函数前加入
#pragma comment(lib, "d3dx9.lib")

以指示编译器链接d3dx9.lib。

矩阵的基本运算:包括加,减,乘。

函数原型:
    D3DXMATRIX operator * ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX operator + ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX operator - ( CONST D3DXMATRIX& ) const;
    D3DXMATRIX operator * ( FLOAT ) const;
    D3DXMATRIX operator / ( FLOAT ) const;

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    
// initialize and print matrix A
    D3DXMATRIX A(11.012.013.014.0,
                 
21.022.023.024.0,
                 
31.032.033.034.0,
                 
41.042.043.044.0);

    printf(
"\n");

    printf(
"     |%f   %f    %f    %f|\n", A._11,A._12,A._13,A._14);
    printf(
"     |%f   %f    %f    %f|\n", A._21,A._22,A._23,A._24);
    printf(
"  A= |%f   %f    %f    %f|\n", A._31,A._32,A._33,A._34);
    printf(
"     |%f   %f    %f    %f|\n", A._41,A._42,A._43,A._44);

    printf(
"\n\n\n");

    
// initialize and print matrix B
    D3DXMATRIX B(-10.0-12.0-13.0-14.0,
                 
-21.0-21.0-23.0-24.0,
                 
-31.0-32.0-32.0-34.0,
                 
-41.0-42.0-43.0-43.0);

    printf(
"     |%f   %f    %f    %f|\n", B._11,B._12,B._13,B._14);
    printf(
"     |%f   %f    %f    %f|\n", B._21,B._22,B._23,B._24);
    printf(
"  B= |%f   %f    %f    %f|\n", B._31,B._32,B._33,B._34);
    printf(
"     |%f   %f    %f    %f|\n", B._41,B._42,B._43,B._44);

    printf(
"\n\n\n");

    
// calculate A+B
    D3DXMATRIX C = A + B;

    
for(int i=0; i<4; i++)
    {
        
if(i != 2)
            printf(
"      |%f   %f    %f    %f|\n", C(i,0), C(i,1), C(i,2), C(i,3));
        
else 
            printf(
"  A+B=|%f   %f    %f    %f|\n", C(i,0), C(i,1), C(i,2), C(i,3));
    }

    printf(
"\n\n\n");

    
// calculate A * B
    C = A * B;
    
    
for(int i=0; i<4; i++)
    {
        
if(i != 2)
            printf(
"     |%f   %f    %f    %f|\n", C(i,0), C(i,1), C(i,2), C(i,3));
        
else 
            printf(
"  AB=|%f   %f    %f    %f|\n", C(i,0), C(i,1), C(i,2), C(i,3));
    }
    
    printf(
"\n");

    
return 0;
}

输出:



矩阵求逆:

// Calculate inverse of matrix.  Inversion my fail, in which case NULL will
// be returned.  The determinant of pM is also returned it pfDeterminant
// is non-NULL.
D3DXMATRIX* WINAPI D3DXMatrixInverse
    ( D3DXMATRIX *pOut, FLOAT *pDeterminant, CONST D3DXMATRIX *pM );

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    
// initialize and print matrix A
    D3DXMATRIX A(1.012.013.014.0,
                 
0.01.0,  23.024.0,
                 
0.00.0,  1.0,  34.0,
                 
0.00.0,  0.0,  1.0);

    printf(
"       |%-4.6f   %-4.6f    %-4.6f    %-4.6f|\n", A._11, A._12, A._13, A._14);
    printf(
"       |%04.6f   %04.6f    %04.6f    %04.6f|\n", A._21, A._22, A._23, A._24);
    printf(
"   A=  |%04.6f   %04.6f    %04.6f    %04.6f|\n", A._31, A._32, A._33, A._34);
    printf(
"       |%04.6f   %04.6f    %04.6f    %04.6f|\n", A._41, A._42, A._43, A._44);

    printf(
"\n\n\n");

    
// calculate inverse matrix for A
    D3DXMATRIX B;

    D3DXMatrixInverse(
&B, NULL, &A);

    printf(
"        |%04.6f   %04.6f    %04.6f    %04.6f|\n", B._11, B._12, B._13, B._14);
    printf(
"        |%04.6f   %04.6f    %04.6f    %04.6f|\n", B._21, B._22, B._23, B._24);
    printf(
"inv(A)= |%04.6f   %04.6f    %04.6f    %04.6f|\n", B._31, B._32, B._33, B._34);
    printf(
"        |%04.6f   %04.6f    %04.6f    %04.6f|\n", B._41, B._42, B._43, B._44);

    printf(
"\n\n\n");

    
return 0;
}

输出:



矩阵转置:

D3DXMATRIX* WINAPI D3DXMatrixTranspose
    ( D3DXMATRIX *pOut, CONST D3DXMATRIX *pM );

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    
// initialize and print matrix
    D3DXMATRIX A(11.0f12.0f13.0f14.0f,
                
21.0f22.0f23.0f24.0f,
                
31.0f32.0f33.0f34.0f,
                
41.0f42.0f43.0f44.0f);

    printf(
"          |%f   %f    %f    %f|\n", A._11, A._12, A._13, A._14);
    printf(
"          |%f   %f    %f    %f|\n", A._21, A._22, A._23, A._24);
    printf(
"       A= |%f   %f    %f    %f|\n", A._31, A._32, A._33, A._34);
    printf(
"          |%f   %f    %f    %f|\n", A._41, A._42, A._43, A._44);

    printf(
"\n\n\n");

    
// calculate matrix transpose
    D3DXMATRIX C;

    D3DXMatrixTranspose(
&C, &A);

    printf(
"              |%f   %f    %f    %f|\n", C._11, C._12, C._13, C._14);
    printf(
"              |%f   %f    %f    %f|\n", C._21, C._22, C._23, C._24);
    printf(
" transpose A= |%f   %f    %f    %f|\n", C._31, C._32, C._33, C._34);
    printf(
"              |%f   %f    %f    %f|\n", C._41, C._42, C._43, C._44);

    printf(
"\n\n\n");

    
return 0;
}

输出:



坐标平移变换:

1) Builds a matrix using the specified offsets.

D3DXMATRIX *WINAPI D3DXMatrixTranslation(D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z);

2) Transforms a 3-D vector by a given matrix, projecting the result back into w = 1.

D3DXVECTOR3 *WINAPI D3DXVec3TransformCoord(D3DXVECTOR3 *pOut,
    CONST D3DXVECTOR3 *pV,
    CONST D3DXMATRIX *pM
);

This function transforms the vector, pV (x, y, z, 1), by the matrix, pM, projecting the result back into w=1.

3) Transforms the 3-D vector normal by the given matrix.

D3DXVECTOR3 *WINAPI D3DXVec3TransformNormal(D3DXVECTOR3 *pOut,
    CONST D3DXVECTOR3 *pV,
    CONST D3DXMATRIX *pM
);

This function transforms the vector normal (x, y, z, 0) of the vector, pV, by the matrix, pM.

If you transform a normal by a non-affine matrix, the matrix you pass to this function should be the transpose of the inverse of the matrix you would use to transform a coordinate.

D3DXVec3TransformNormal这个函数似乎执行与 D3DXVec3TransformCoord相反的运算,没搞懂。

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    D3DXVECTOR3 v(
1.02.03.0);
    D3DXMATRIX M;

    D3DXMatrixTranslation(
&M, v.x, v.y, v.z);

    printf(
"             |%f   %f    %f    %f|\n", M._11, M._12, M._13, M._14);
    printf(
"             |%f   %f    %f    %f|\n", M._21, M._22, M._23, M._24);
    printf(
"Translate M= |%f   %f    %f    %f|\n", M._31, M._32, M._33, M._34);
    printf(
"             |%f   %f    %f    %f|\n", M._41, M._42, M._43, M._44);

    printf(
"\n\n");

    D3DXVECTOR3 P(
20.03.08.0);
    D3DXVECTOR3 new_P;

    D3DXVec3TransformCoord(
&new_P, &P, &M);

    printf(
"p coordinate (%f, %f, %f) in new coordinate reference\n\n", new_P.x, new_P.y, new_P.z);

    D3DXVec3TransformNormal(
&new_P, &P, &M);

    printf(
"p transform normal (%f, %f, %f)\n\n", new_P.x, new_P.y, new_P.z);

    
return 0;
}

输出:



坐标的放大缩小变换:

Builds a matrix that scales along the x-axis, the y-axis, and the z-axis.

D3DXMATRIX * D3DXMatrixScaling(
D3DXMATRIX *pOut,
FLOAT sx,
FLOAT sy,
FLOAT sz
);
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
sx
[in] Scaling factor that is applied along the x-axis.
sy
[in] Scaling factor that is applied along the y-axis.
sz
[in] Scaling factor that is applied along the z-axis.

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    D3DXMATRIX M;
    D3DXMatrixScaling(
&M, 2.02.02.0);

    printf(
"                   |%f   %f    %f    %f|\n", M._11, M._12, M._13, M._14);
    printf(
"                   |%f   %f    %f    %f|\n", M._21, M._22, M._23, M._24);
    printf(
"Scaling Matrix: M= |%f   %f    %f    %f|\n", M._31, M._32, M._33, M._34);
    printf(
"                   |%f   %f    %f    %f|\n", M._41, M._42, M._43 ,M._44);

    printf(
"\n\n\n");

    D3DXVECTOR3  P(
3.08.033.0);
    D3DXVECTOR3 new_P;

    D3DXVec3TransformCoord(
&new_P, &P, &M);
    printf(
"After transform coordinate: (%f, %f, %f)\n\n", new_P.x, new_P.y, new_P.z);

    
return 0;
}

输出:



旋转变换:

对于旋转变换的矩阵计算,DirectX提供了 D3DXMatrixRotationX,D3DXMatrixRotationY, D3DXMatrixRotationZ和D3DXMatrixRotationAxis等函数来计算沿x,y,z轴以及任意轴线的旋转变换矩阵,这4个函数的旋转角都采用弧度作为计量单位.

// Build a matrix which rotates around the X axis
D3DXMATRIX* WINAPI D3DXMatrixRotationX
    ( D3DXMATRIX *pOut, FLOAT Angle );

// Build a matrix which rotates around the Y axis
D3DXMATRIX* WINAPI D3DXMatrixRotationY
    ( D3DXMATRIX *pOut, FLOAT Angle );

// Build a matrix which rotates around the Z axis
D3DXMATRIX* WINAPI D3DXMatrixRotationZ
    ( D3DXMATRIX *pOut, FLOAT Angle );

// Build a matrix which rotates around an arbitrary axis
D3DXMATRIX* WINAPI D3DXMatrixRotationAxis
    ( D3DXMATRIX *pOut, CONST D3DXVECTOR3 *pV, FLOAT Angle );

代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma warning(disable : 
4305)

int main()
{
    D3DXMATRIX M;
    D3DXVECTOR3 vec_rotate(
5.05.05.0);
    
float angle = D3DX_PI;

    D3DXMatrixRotationAxis(
&M, &vec_rotate, angle);

    printf(
"                    |%f   %f    %f    %f|\n", M._11, M._12, M._13, M._14);
    printf(
"                    |%f   %f    %f    %f|\n", M._21, M._22, M._23, M._24);
    printf(
"Rotation Matrix M = |%f   %f    %f    %f|\n", M._31, M._32, M._33, M._34);
    printf(
"                    |%f   %f    %f    %f|\n", M._41, M._42, M._43, M._44);

    printf(
"\n\n\n");

    D3DXVECTOR3 P(
2.03.06.0);
    D3DXVec3TransformCoord(
&P, &P, &M);

    printf(
"After rotation: P(%f, %f, %f)\n\n", P.x, P.y, P.z);

    
return 0;
}

输出:



还有一个函数 D3DXMatrixRotationYawPitchRoll,可以直接计算沿x,y,z轴旋转的变换矩阵。

Builds a matrix with a specified yaw, pitch, and roll.

D3DXMATRIX * D3DXMatrixRotationYawPitchRoll(
D3DXMATRIX *pOut,
FLOAT Yaw,
FLOAT Pitch,
FLOAT Roll
);

Parameters

pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
Yaw
[in] Yaw around the y-axis, in radians.
Pitch
[in] Pitch around the x-axis, in radians.
Roll
[in] Roll around the z-axis, in radians.

Return Values

Pointer to a D3DXMATRIX structure with the specified yaw, pitch, and roll.

Remarks

The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixRotationYawPitchRoll function can be used as a parameter for another function.

The order of transformations is roll first, then pitch, then yaw. Relative to the object's local coordinate axis, this is equivalent to rotation around the z-axis, followed by rotation around the x-axis, followed by rotation around the y-axis.
 

Figure 1.  Roll, pitch, yaw diagram




代码示例:

#include <stdio.h>
#include 
<D3DX9Math.h>

#pragma comment(lib, 
"d3dx9.lib")

#pragma warning(disable : 
4305)

int main()
{
    D3DXMATRIX M;
    D3DXVECTOR3 P(
2.03.06.0);

    printf(
"Before rotation: P(%f, %f, %f)\n\n", P.x, P.y, P.z);

    
// Rotate around y-axis with 0 degree, around x-axis with PI degree, around z-axis with PI degree.
    D3DXMatrixRotationYawPitchRoll(&M, 0, D3DX_PI, D3DX_PI);

    printf(
"                    |%f   %f    %f    %f|\n", M._11, M._12, M._13, M._14);
    printf(
"                    |%f   %f    %f    %f|\n", M._21, M._22, M._23, M._24);
    printf(
"Rotation Matrix M = |%f   %f    %f    %f|\n", M._31, M._32, M._33, M._34);
    printf(
"                    |%f   %f    %f    %f|\n", M._41, M._42, M._43, M._44);

    printf(
"\n\n\n");
    
    D3DXVec3TransformCoord(
&P, &P, &M);

    printf(
"After rotation: P(%f, %f, %f)\n\n", P.x, P.y, P.z);

    
return 0;
}

运行截图:



posted on 2007-04-27 20:04 lovedday 阅读(2353) 评论(0)  编辑 收藏 引用 所属分类: ■ DirectX 9 Program


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论