• 沒有找到結果。

三维游戏引擎中的几何基础

4.1 向量及其运算

4.1 向量及其运算

4.1.1 向量的定义

向量(Vector)也称为矢量,简单来说,就是在给定的坐标系(Coordinate System)中描述位 置或方向的一组数。在 3D 图形学中,这个坐标系往往是笛卡儿坐标系(Cartesian Coordinates),

比如,一个向量可以用(4,5,3)来表示,如图 4-1 所示。向量不同于标量,标量仅有大小,而向量 既有大小又有方向。具体在 3D 图形学中,向量可以用来表示粒子的速度、加速度和光线方向等 既有大小又有方向的量。总之,向量为在三维空间中表示方向提供了方便。

Y

X (5,3)

Y

X

Z 2D 坐标系

中的向量 3D 坐标系

中的向量 (4,5,3)

图 4-1 2D 向量和 3D 向量

在 D3DX 库中,用 D3DXVECTOR3 来表示 3D 空间中的三维向量,它是从 D3DVECTOR 继 承过来的,D3DVECTOR 结构体定义如以下代码所示:

typedef struct D3DVECTOR { float x, y, z;

} D3DVECTOR, *LPD3DVECTOR;

D3DVECTOR 含 有 3 个 浮 点 型 变 量 , 分 别 表 示 三 维 向 量 的 一 个 分 量 。 D3DX 库 中 对 D3DVECTOR 的派生类 D3DXVECTOR3 的定义如下:

typedef struct D3DXVECTOR3 : public D3DVECTOR {

public:

// 构造函数

D3DXVECTOR3() {};

D3DXVECTOR3( CONST FLOAT * );

D3DXVECTOR3( CONST D3DVECTOR& );

D3DXVECTOR3( CONST D3DXFLOAT16 * );

D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z );

// 类型转换函数 operator FLOAT* ();

operator CONST FLOAT* () const;

// 赋值操作符

D3DXVECTOR3& operator += ( CONST D3DXVECTOR3& );

D3DXVECTOR3& operator -= ( CONST D3DXVECTOR3& );

72

三维游戏

引 擎 设 计 技术 及 其 应用

D3DXVECTOR3& operator *= ( FLOAT );

D3DXVECTOR3& operator /= ( FLOAT );

// 一元操作符

D3DXVECTOR3 operator + () const;

D3DXVECTOR3 operator - () const;

// 二元操作符

D3DXVECTOR3 operator + ( CONST D3DXVECTOR3& ) const;

D3DXVECTOR3 operator - ( CONST D3DXVECTOR3& ) const;

D3DXVECTOR3 operator * ( FLOAT ) const;

D3DXVECTOR3 operator / ( FLOAT ) const;

// 友元函数操作符

friend D3DXVECTOR3 operator * ( FLOAT, CONST struct D3DXVECTOR3& );

// 比较两个向量是否相等操作符

BOOL operator == ( CONST D3DXVECTOR3& ) const;

BOOL operator != ( CONST D3DXVECTOR3& ) const;

} D3DXVECTOR3, *LPD3DXVECTOR3;

可以看出,与 D3DVECTOR 相比,D3DXVECTOR3 仅仅扩展了许多操作符和函数,便于向 量与数、向量与向量之间的数学运算。如果你的 C++学得很好,大概已经看出这些操作符有什么 用途了;如果你一头雾水,没有关系,这里将简要讲述上述函数的作用。

前 5 个构造函数允许你从 FLOAT 数组、16 位 FLOAT 数组、D3DVECTOR 向量等创建一个 D3DXVECTOR3 对象。然后是两个类型转换函数,它允许将一个 D3DXVECTOR3 对象直接转换 成一个 FLOAT 指针,指向该对象的第一个变量 x。然后重载了 4 个赋值操作符,它们允许你像 操作内置数据类型那样操作 D3DXVECTOR3 对象,请看以下代码:

D3DXVECTOR3 vec1(1,2,3);

D3DXVECTOR3 vec2(vec1);

D3DXVECTOR3 vec3;

vec3 = vec1 + vec2;

执行完毕后,vec2 的大小等于(1,2,3),vec3 的大小等于(2,4,6)。

然后定义了两个单目运算符,分别为取正“+”和取负操作“-”。请看代码:

D3DXVECTOR3 vec4 = - vec2;

执行完毕,vec4 的大小为(-1,-2,-3)。

然后定义了 4 个双目运算符,其中加运算符和减运算符允许两个 D3DXVECTOR3 类型向量 相加(减),返回一个 D3DXVECTOR3 类型,运算规则为分别将两个向量对应的分量相加(减)。

乘运算符和除运算符允许一个 D3DXVECTOR3 向量和一个 FLOAT 类型相乘(除),运算规则为 将向量中的每个分量乘(除)以那个 FLOAT 数据,返回一个 D3DXVECTOR3 类型。

上面定义的乘法运算符只允许将一个 D3DXVECTOR3 类型和一个 FLOAT 数据相乘,若是想 将一个 FLOAT 数据和一个 D3DXVECTOR3 类型相乘,怎么办呢?这时使用上述的*运算符是错 误的,必须另外定义一个友元函数操作符,它含有两个参数;第一个是 FLOAT 数据,第二个是 D3DXVECTOR3 类型向量。

73 第 章

三维游戏引擎中的几何基础

4 下面给出代码说明作为友元函数操作符的“*”与属于类本身的二元操作符之间的区别:

D3DXVECTOR3 vec1(1,2,3);

D3DXVECTOR3 vec2 = vec1 * 2; // 调用属于类本身的二元操作符 D3DXVECTOR3 vec3 = 2 * vec1; // 调用友元函数操作符

最后两个操作符实现判断两个 D3DXVECTOR3 向量是否相等的功能。这两个操作符都只含 有一个 D3DXVECTOR3 参数。只有在每个分量都相等的情况下,才能说明某两个向量是相等的。

下面给出代码说明:

D3DXVECTOR3 vec1(1,2,3);

D3DXVECTOR3 vec2(vec1);

D3DXVECTOR3 vec3(1,2,4);

ASSERT(vec1 == vec2);

ASSERT(vec1 != vec3);

本节仅介绍了 D3DXVECTOR3 类(虽然定义为结构体,但 C++中的结构体与类已经没有很 大区别了)的用法,D3DX 数学库中还定义了 D3DXVECTOR2 和 D3DXVECTOR4 向量类,分别 是二维向量和四维向量,其用法和 D3DXVECTOR3 都很相似,在此就不详细介绍了。

4.1.2 向量的数学运算及在 D3D 中的实现

上一节讲述向量类 D3DXVECTOR3 时,已经介绍了一些简单的向量数学运算,它们都是通 过定义在类内部的数学操作符实现的。本节将介绍 D3DX 实现的用于向量数学运算的函数,分别 为求向量长度、归一化、点积、叉积等。

1.向量的长度与归一化

使用向量时,经常遇到的一个问题是计算一个向量的长度。向量的长度在数学上也称为范数

(Norm)。从几何上表示,向量的长度是从向量原点到向量终点之间的距离。要计算一个向量的 长度,应用以下公式即可:

2 2 2

| |

v

 | . |

v x

| . |

x y

| . |

v z

(4-1)

D3DX 库为计算向量长度专门提供了一个函数,其原型为:

FLOAT D3DXVec3Length(

CONST D3DXVECTOR3 * pV );

pV 指向所要求的三维向量,函数返回值即为向量的长度。

知道向量的长度后,即可对其进行归一化(Normalize)处理了,归一化即对向量进行缩放,

使其长度为 1.0,并且方向保持不变。对一个向量求归一化,可以使用以下公式:

2 2 2

ˆ | | | . | | . | | . |

v v

v v v x v y v z

 

 

(4-2)

D3DX 库为对向量进行归一化也提供了一个函数,其原型为:

D3DXVECTOR3 * D3DXVec3Normalize(

D3DXVECTOR3 * pOut, CONST D3DXVECTOR3 * pV );

pV 指向要输入的待归一化处理的向量,归一化之后的向量保存在 pOut 指向的对象中。该函

74

数还返回一个 D3DXVECTOR3 指针值,该指针值和 pOut 的最终值相等,这样做的好处是该函数 可以作为其他函数的参数。

FLOAT D3DXVec3Dot(

CONST D3DXVECTOR3 * pV1, CONST D3DXVECTOR3 * pV2 );

75 第 章

三维游戏引擎中的几何基础

相關文件