C中用运算符重载实现矩阵运算

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

走进3D的世界

-- C++中用运算符重载实现矩阵运算

作者:周军

矩阵(Matrix)无处不在,我们的生活中到处都能找到矩阵的身影,然而此处我不想把这个定义放大,我们只讨论线性代数中的矩阵,我们要用它们来完成我们的3D变换。为什么矩阵可以完成3D变换呢?下面,我们就来介绍矩阵是如何变换坐标的:

设空间中有一坐标(x,y,z),如果我们想把它变换成另一坐标(x,’y’,z’),我们可以进行如下操作:

= (x’,y’,z’,1)

这就是矩阵的妙用了。它在复杂处理变换的时候表现得尤为突出。假设我们想要把一个物体先沿z轴旋转角thetaZ,再沿x轴旋转角thetaX,我们可以进行如下操作(pseudo-code):

obj*=rotX(thetaX)*rotZ(thetaZ);

注意:矩阵的乘法是不可逆的,而且我们要按变化顺序的逆序进行乘法,具体推导见计算几何相关书籍。

下面,我们进入正题:如何再C++中用重载运算符的方法来进行矩阵运算以完成线性变换呢?我们需要变换坐标,所以很自然地,我们需要一个向量(Vector)类;同时我们要进行

为直观、人性化,我选用了运算符重载这以技巧而不是简单地调用函数,下面请看我的具体实现:

以上便是CVector类的具体实现,我想对C++和线性代数有所了解的读者都能很清楚地理解这段代码,在次不累述。

上述代码的成员函数实在类外定义的,如果读者在实践中为了提高速度可以把这些成员函数定义在类内以起到内联函数的作用,可以省去参数压栈、出栈时的时间。

下面是CMatrix类的具体实现:

是不是也很好理解呢?哈哈,这就是用运算符重载的好处。不过这种方法也确实有它的不足,而且这个不足在游戏编程中是致命的,那就是效率不高,这也正是为什么Microsoft 在DirectX中也使用难看的一般函数调用来完成矩阵运算的原因。影响速度的主要原因是在使用运算符+、-、*、/等时,程序会在每次运算时创建临时对象再将临时对象返回,对于重复多次的矩阵运算来说,这无疑成为了一笔庞大的额外开销(好在现在的计算机的处理速度还算快)。但注意:在使用+=、-=、*=、/=时不会有上述问题,因为在使用这些运算符时程序只需要修改第一个对象不需要创建并返回临时对象。所以在能使用+=、-=、*=、/=时尽量不要使用单一的=、-、*、/运算符。

好了,这两个类我们已经封装好了,下面还有什么呢?是的,忘了向大家交代旋转矩阵了:

这三个就是再前面出现过的rotX、rotY、rotZ了,这些都是由数学家推导出来的,至于具体怎么推导(向量法),有兴趣的朋友可以参考计算几何相关书籍。

这篇文章到这里似乎应该结束了,不知道我是不是讲清楚了,嘿嘿 ^_^

还是按照惯例附上两个例子吧,都是旋转3D物体的例子,物体是由一些点随机生成的,具体运行效果见下图:

图1. 3D物体的旋转例子()

操作说明:

上、下键:使物体沿x轴旋转

左、右键:使物体沿y轴旋转

Delete、PageDown键:使物体沿z轴旋转

Home、End键:改变物体距视点的距离

还记得,在上一篇《粒子系统的应用》中,我提到过利用粒子系统可以模拟一些特殊的光影效果,但是我当时并没有附上例子,因为它要用到矩阵变换的一些知识,所以现在我把这个例子附上。其中包括一些放缩、模糊等技巧我会在以后的文章中涉及。

具体运行效果见下图:

图 2. 光影效果模拟()

很眩吧,哈哈!!!

文章中的实例在Watcom C++中调试成功,读者在运行的时候必须保证您的运行目录里有,这是一个开启保护模式的程序,如果没有程序将无法运行。

相关文档
最新文档