预备知识:坐标系是按右手定则的笛卡尔坐标系。对话框正正中间是原点,右为+X,上为+Y,屏幕外为+Z。
用openGL画图时,例如画三角面、矩形、点、直线,都是在物体坐标系内画的。
物体坐标系可以平移/旋转/缩放。
平移,就是把物体坐标系在世界坐标系中平移。下面看个示例:
openGL初始化完之后,世界坐标系和物体坐标系是重合的,我先在物体坐标系的原点(0,0,0)处画了个正方体①,然后我又想在这个球的右侧5单位处再画个正方体②,那么该怎么做呢?有两种方法:
(1)直接在物体坐标系的(0+5,0,0)处画正方体;
(2)把物体坐标系平移(0+5,0,0),使之位于世界坐标系的(5,0,0),然后在物体坐标系的(0,0,0)处画正方体。
此时在世界坐标系中已经有2个立方体了,我想在立方体体①的正上方6单位处再画个正方体③,该怎么办?
很简单,把物体坐标系平移(-5,6,0)使之位于世界坐标系的(0,6,0)处,然后在物体坐标系的(0,0,0)处画立方体③。
主要程序如下:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity();//重置物体坐标系,使之与世界坐标系重合
gluLookAt(-3, 8, 10,//眼睛的位置
0, 0, 0, //聚焦点
0, 1, 0);//头顶的方向
glTranslatef(0, 0, 0);//平移物体坐标系
paintGL_pureCube();//绘制立方体
glTranslatef(5, 0, 0);
paintGL_pureCube();//绘制立方体
glTranslatef(-5, 6, 0);
paintGL_pureCube();//绘制立方体
综上可见,通过移动坐标系来画图是很简便的,比如上面画的3个正方体,可以共用同一个函数,因为三个立方体都是在物体坐标系的(0,0,0)处画的。如果不移动物体坐标系,那么想画这3个立方体,你就得分别计算出他们的面坐才行,这计算就复杂了。有人可能觉得,这一点都不复杂,我稍微一算就能算出来,那么请你再看看下面这个需求,你就能体会到操作物体坐标系的优势了。
例题:要求在世界坐标系的(0,0,0)处画一个2x2x2的正方体①,然后在它的右侧5单位处画一个绕屏幕法线(即Z轴)旋转了45度的立方体②,然后在①的上方画一个水平线旋转45度的正方体③。
程序如下:
glClearColor(0.0f, 0.00f, 0.00f, 1.0f);//重新填充背景色
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除屏幕和深度缓存
glLoadIdentity();//重置物体坐标系,使之与世界坐标系重合
gluLookAt(-3, 8, 10,//眼睛的位置
0, 0, 0, //聚焦点
0, 1, 0);//头顶的方向
glTranslatef(0, 0, 0);
paintGL_pureCube();//绘制立方体
glTranslatef(5, 0, 0);//平移物体坐标系
glRotatef(45, 0.0f, 0.0f, 1.0f);//把物体坐标系绕自己的Z轴转45度
paintGL_pureCube();//绘制立方体
glRotatef(-45, 0.0f, 0.0f, 1.0f);//旋转回来摆正
glTranslatef(-5, 6, 0);
glRotatef(45, 1.0f, 0.0f, 0.0f);//把物体坐标系绕自己的X轴转45度
paintGL_pureCube();//绘制立方体
这种歪曲的立方体想要人工算出面的角点坐标就很困难了,这就体现出操作物体坐标系的优势了。
最后再来看一个缩放的例子:要求在世界坐标系的(0,0,0)处画一个2x2x2的正方体①,然后在它的右侧5单位处画一个绕屏幕法线(即Z轴)旋转了45度的4*4*4立方体②,然后在①的上方画一个水平线旋转45度的1*1*1正方体③。
glTranslatef(0, 0, 0);
paintGL_pureCube();//绘制2x2x2立方体
glTranslatef(5, 0, 0);//平移物体坐标系
glRotatef(45, 0.0f, 0.0f, 1.0f);//把物体坐标系绕自己的Z轴转45度
glScalef(2.0f, 2.0f, 2.0f);//物体坐标系缩小(物体放大2倍)
paintGL_pureCube();//绘制立方体
glScalef(0.5f, 0.5f, 0.5f);//物体坐标系放大回来
glRotatef(-45, 0.0f, 0.0f, 1.0f);//旋转回来摆正
glTranslatef(-5, 6, 0);
glRotatef(45, 1.0f, 0.0f, 0.0f);//把物体坐标系绕自己的X轴转45度
glScalef(0.5f, 0.5f, 0.5f);//物体坐标系放大(物体缩小为1/2)
paintGL_pureCube();//绘制立方体