综述
通过上一节说的绘制 3D 图形基础,我们应该对绘制 3D 图形有了基本的认识,接下来我们就进行一个实例,绘制一个 3D 机器人。 本节我们要完成的任务有:
1.绘制一个仿真 3D 机器人(样式自选,参考例图),至少包含头、躯干、四肢三个部分. 2.对机器人填充颜色。 3.增加点光源,使得机器人更加真实。 4.实现交互,使得能够控制机器人进行旋转、前进、后退等动作。 键盘”w”:前进 键盘”s”:后退 键盘”a”:顺时针旋转 键盘”d”:逆时针旋转
接下来我们就一步步实现机器人的绘制吧。
绘制球体
绘制球体我们有两种方法,一个叫 glutSolidSphere,另一个叫 glutWireSphere,这两个的区别在于,一个绘制的是实心的球体,另一个绘制的是现状描绘而成的球体,在绘制过程中,我们可以通过一个参数来对其进行控制。 glutSolidSphere 是 GLUT 工具包中的一个函数,该函数用于渲染一个球体。球体球心位于原点。在 OpenGL 中默认的原点就是窗口客户区的中心。 函数原型
1 |
void glutSolidSphere(GLdouble radius , GLint slices , GLint stacks); |
radius,球体的半径 slices,以 Z 轴上线段为直径分布的圆周线的条数(将 Z 轴看成地球的地轴,类似于经线) stacks,围绕在 Z 轴周围的线的条数(类似于地球上纬线) 一般而言, 后两个参数赋予较大的值, 渲染花费的时间要长, 效果更逼真。 然而我们可以发现,这里并没有定义球中心的参数,所以,我们可以利用平移函数组合实现。即利用 glTranslated 函数来实现。最后,我们定义的画球体的方法如下
1 |
//画球 |
其中两个常量定义如下
1 |
|
在这里我们还用到了上一节所说的 PushMatrix 和 PopMatrix 方法。如果不熟悉,请查看上一节的内容。
绘制长方体
同样地,利用变换平移放缩的方法,再加上类库的绘制正方体的方法,我们也可以轻松地实现绘制长方体的方法。 正方体怎样变成长方体,很简单,拉伸一下就好了。所以,我们用到了 glScaled 方法。 绘制长方体的方法如下
1 |
//画长方体 |
这里仍然还是定义了绘图模式,是线条还是实体。
定义光照
在这里提供一篇博文,讲光照讲得比较细致 OPENGL 光照 那么在这里我就直接贴上光照设置的实现
1 |
void init() { |
其中设置了光源颜色,位置等参数。
图形的移动
在这里我们实现了鼠标的监听旋转和键盘的监听旋转,在这里分别描述如下
1.鼠标监听
对于鼠标监听事件,在前面的文章中已经做了说明,如果大家不熟悉可以看下面这篇文章 鼠标监听 我们要实现的就是在拖动鼠标的时候实现图形的旋转功能。 在点击鼠标时,我们记录下来点击的位置,然后在鼠标移动的时候记录下当前坐标与上一个位置的坐标之差。通过定义一个角度的变量,每次鼠标移动的时候让整个图形旋转角度加上这个差值,然后重新绘制图形,就可以实现整个图形的 旋转了。 鼠标监听的两个方法如下,分别是鼠标点击和鼠标移动。 定义两个变量,旋转角度
1 |
int spinX = 0; |
然后定义两个鼠标事件
1 |
// 鼠标移动事件 |
恩,通过定义上面的方法,然后在 main 中加入监听。
1 |
//鼠标点击事件,鼠标点击或者松开时调用 |
display 函数中,在绘图前调用该方法即可
1 |
glRotated(spinX, 0, 1, 0); |
分别是绕 y 轴和 x 轴旋转一定的角度。这样就可以实现鼠标的监听了。
2.键盘监听
键盘事件也很简单,同样是监听按键的按下。其中 w、s 键是用来控制机器人的远近的。 定义一个变量叫 dis,代表远近 键盘事件函数如下:
1 |
//键盘事件 |
在 main 函数中加入监听
1 |
//键盘事件 |
display 函数中加入如下的变换
1 |
glRotated(spinX, 0, 1, 0); |
这样通过上述方法,我们便可以实现鼠标和键盘的监听了。
裁切物体
在这里我们可能要画一个半圆,那么最方便的方法就是裁切了,利用下面的函数,我们可以方便地实现。
void glClipPlane(GLenum plane, const GLdouble *equation);
定义一个裁剪平面。equation 参数指向平面方程 Ax + By + Cz + D = 0 的 4 个系数。 equation=(0,-1,0,0),前三个参数(0,-1,0)可以理解为法线向下,只有向下的,即 Y<0 的才能显示,最后一个参数 0 表示从 z=0 平面开始。这样就是裁剪掉上半平面。 equation=(0,1,0,0)表示裁剪掉下半平面, equation=(1,0,0,0)表示裁剪掉左半平面, equation=(-1,0,0,0)表示裁剪掉右半平面, equation=(0,0,-1,0)表示裁剪掉前半平面, equation=(0,0,1,0)表示裁剪掉后半平面 代码示例如下
1 |
GLdouble eqn[4]={0.0,0.0,-1.0,0.0}; |
首先我们必须要定义一个 GLdouble 数组,然后利用 glClipPlane 方法来设置,然后开启裁切,最后关闭裁切。 利用类似的方法我们可以写出绘制半球的方法如下
1 |
//画半球 |
恩,通过上述方法,我们可以方便地绘制出一个半球体。
绘制机器人
有了上述的铺垫,我们绘制机器人简直易如反掌,同样还可以实现各式各样的监听。 主要就是位置的确定了。 display 函数如下
1 |
void display(void) { |
恩,通过调用这个函数我们便可以完成机器人的绘制了。
完整代码
在这里提供完整代码示例,仅供参考
1 |
#include <glut.h> |
仅供参考,如有问题,敬请指正。 运行结果如下 恩,大体就是这样。
总结
本次实验做的比较匆忙,只研究了一个晚上的时间,所以有些地方还是不太完善,希望发出来对小伙伴们有所启发,有所帮助。如果有问题,欢迎同我交流。谢大家!