嗯,我需要我的程序能够在屏幕上显示一个长方体,实际上,它还能随机旋转,像是一个动画演示程序
画3D图形,我需要一个3D图形库吗?像是opengl什么的…
不,我们只需要一些简单的2d图形api,能画线就行,当然还要些高中的数学知识。
这,可以吗?
你有没有想过这个问题,你的显示器是二维的,它为什么能玩3D游戏?(比如wow)
答案是投影,程序构建了一个虚拟的3D世界,然后把它投影到你的二维显示器上,绘制出来。想像这个虚拟的3d世界就像一个鱼缸,你的显示器是一个平面,鱼缸的正面与你显示器重合,鱼缸中会发生许多事情,而你能看到的仅仅是被投影到显示器的部分 。
当然这是个很简化的模型,如果你用过opengl,它就很强大,它所描述的3D世界就是个虚拟世界,你能看见的是被一个老式照相机照到底片的部分,(所以你可以调整照相机的位置,调焦距。。。来看这个虚拟世界)
平行投影和正交投影
平行投影就是简单的把3D投影到一个面,而正交投影因为有视点距离,所以投影出来的图像有近大远小的特征,平行投影物体在哪都那么大,(所以传说平行投影可以看到无限远),画家坐在街角,画的写生就是正交投影,我们高中坐的立体几何题就是平行投影 ,有些蛋疼的人可能会用 正交投影........
下面就是我用python实现的一组关于3D绘图的api,我把一个长方体用八个顶点来表示,每个顶点是一个三维坐标,还能通过 这 八个顶点坐标来取得一个长方体的十二条边(好吧,我承认这两个函数写的是不好,我决定等我要的程序实现后再来修改这两个函数,让他们更 “优美” 一点),我还实现了基本的像平移旋转(绕x, y, z轴的旋转),和投影到一个平面的算法,(因为是平行投影,所以就是简单的把3D转成2D),这些都是高中的数学知识,下次有人再说高中学的东西只能考试的时候,你就可以反驳说,谁说的,你知道3D图形是怎么画出来的吗?
1 | import math |
现在基本的逻辑算法有了,我们用什么画呢?其实随便一个GUI都可以,只要它能画线就行了,比如wxPython,比如Tkinter,不过,我喜欢用pygame。
没错,我就喜欢用pygame做演示程序,用pygame真正写个游戏是比较麻烦,但是用它来做演示程序多好呀?绘图又漂亮,还有双缓存,FPS之类的。。。。GUI画出来的难看死了。
下面是游戏的逻辑代码,就算你没用过pygame,也能看懂,因为python就是这么清晰。
1 | import sys, pygame |
说明
- 我的程序在一个空间绘制一个随机旋转的长方体。我计算出它在空间中的顶点坐标,然后把它们投影到xy平面(屏幕),在把他们连成应该有的线。
- 我总是把它移动到原点在旋转,之后在移回去,因为要自 转 就要这样,否则就是绕轴旋转了。
- 注意屏幕的Y轴正方向是向下的,绘图程序要时刻记住这点。
- 我当然没有一次就写出这个程序,实际上,我先试着画一个不动的,然后旋转它,看我的程序是否有错,实际上,我还试着用不同的颜色表示不同的线,来进行调试,等确认我的算法没有问题在开始下一步,(没有别的程序参考,我只能这样,不过这有点原型开发的意思,是不是,会XP的朋友们?)。
- 我没有用oop,我为什么要用oop?我的目的是为了演示3D图形是如何画出来的,只要能做好就行了,再说了,oop哪有那么强大?人云亦云而已,所以我没有写个主类,然后许多N面体去继承它 。
- 慢,效率低,恩,这点我承认,图形库一般都要很高的效率,像是opengl,都是C语言实现的,不过我说了,我是想展示3D图形是如何绘制的 。
- 我决定要修改那两个函数,得到线和得到顶点的,看上去太难看了。
- 如果你喜欢3D图形编程,请学习Opengl,反正我学的不好,我只是因为受不了老师给我们上计算机图形学的时候,教我们在DOS下画图。。。就是去年的事,我可不会买他的帐,所以就去学Opengl,opengl是3D图形的王者(没有之一,DirectX的同学不要喷我),建模(世界和照相机),变换,光照,纹理,高效…