引言
- 要在opengl中显示三维物体需要将投影模式设置为透视 如gluPerspective(45, 1, 0, 100);
第一个参数为fov角,第二个参数是宽高比,后两个参数分别是最近可视距离和最远可视距离
#include<glut.h>
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(500, 500);
glutInitWindowSize(500, 500);
glutCreateWindow("title");
init();
glutDisplayFunc(display);
glutMainLoop();
}
void display()
{
}
void init()
{
glClearColor(1, 1, 1, 1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1, 0, 100);
}
以下例子加入到display方法中即可运行
opengl三维平移变换
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1, 0, -10);
glColor3f(1, 0, 0);
glutWireCube(1);
glTranslatef(3, 0, 0);
glColor3f(0, 1, 0);
glutWireCube(1);
- opengl使用glTranslatef构建平移矩阵,参数分别为朝x,y,z轴移动的方向,三维和二维变换区别不大,二维只要填前两个参数第三个参数置为0即可。
上面先在(-1,0,-10)处绘制了一个红色的线框立方体,然后使用glTranslatef向右平移三个单位,绘制一个绿色的线框立方体
opengl三维缩放变换
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1, 0, -10);
glColor3f(1, 0, 0);
glutWireCube(1);
glScalef(1.5, 1.5, 1.5);
glColor3f(0, 1, 0);
glutWireCube(1);
- opengl使用
glScalef函数构建缩放矩阵。有三个参数,分别是沿x,y,z轴的缩放参数,大于1代表扩大,小于1代表缩小。三维变换和二维差不多,要构建二维缩放矩阵只要把第三个参数设为1即可,代表在z轴上不发生变化。
缩放变化同时还需要一个缩放参照点,因为缩放变化不仅改变自身大小,也改变了自身到缩放点的距离。
opengl默认使用原点作为缩放变换的参照点。 这个例子先创建一个绿色的线框立方体,然后再创建了一个放大版的绿色线框立方体
绕平行于坐标轴的一条轴旋转
- 三维缩放和平移都仅仅是二维缩放和平移的简单扩充,只要加上一个参数代表新增加的一条轴即可。而三维旋转比二维旋转要复杂的多,这是因为在二维旋转中往往注意不到旋转轴的存在。二维旋转中旋转轴可以说是始终垂直于显示平面,而在三维旋转中,需要始终意识到旋转轴的存在。
- 在三维中进行一次旋转需要确定旋转轴和旋转角度,其中旋转轴即三维空间中的一条直线,需要同时用一个三维点和一个三维方向向量来确定,或者使用两个三维点来确定一条直线。所以需要六个参数来确定一条旋转轴。而opengl没有一个单独的函数来完成绕指定旋转轴的旋转。opengl的旋转轴默认经过原点,只能指定朝向,因此只需要三个参数。想要完成绕任意旋转轴旋转需要复合平移变换。
- 在三维旋转中,如果要绕平行于坐标轴的一条轴旋转,只能先平移旋转轴和某条坐标轴重合,旋转之后进行逆平移即可。
//opengl三维旋转(绕平行于坐标轴的轴旋转)
//此例为原点绕经过(0,0,-5)垂直于xz平面的旋转轴进行旋转
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//为了方便查看效果,将整体向z轴负向平移10个单位
glTranslatef(0, 0, -10);
for (int i = 0; i < 18; i++)
{
//进行逆平移
glTranslatef(0, 0, -5);
//进行所需的旋转
glRotatef(20, 0, 1, 0);
//将坐标轴平移至与y轴重合
glTranslatef(0, 0, 5);
glColor3f(1, 0, 0);
glutWireCube(1);
}
- opengl使用
glRotatef函数构建旋转矩阵。一共有四个参数。第一个参数为旋转角度,后面三个参数确定旋转轴的朝向,此轴默认经过原点。在二维变换中,需要注意的是第一个参数为角度而不是弧度,许多其他图形系统的API都为弧度。
以上这个例子是处于原点的立方体绕经过(0,0,-5)垂直于xz平面的旋转轴进行循环旋转,此时该轴平行于y轴,所以将其平移至与y轴重合之后调用glRotatef绕y轴旋转,之后再做逆平移
(为了方便查看效果,将整体向z轴负向平移了10个单位)
绕任意轴旋转
- 在三维旋转中最困难的就是绕任意轴旋转,此旋转轴可能与三条坐标轴分别成某个角度。因此需要先将该轴平移通过原点,再进行两次旋转变换,使其与任意一条坐标轴重合,然后再调用旋转方法,最后使用逆变换。
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(-1, -1, -20);
glColor3f(0, 1, 0);
glBegin(GL_LINES);
//绘制出旋转轴
glVertex3f(-25, -30, -25);
glVertex3f(20, 15, 20);
glEnd();
glColor3f(1, 0, 0);
for (int i = 0; i < 36; i++)
{
//逆变换
glTranslatef(5, 0, 5);
glRotatef(-45, 0, 0, 1);
glRotatef(45, 1, 0, 0);
glRotatef(10, 0, 1, 0);
//再绕x轴顺时针旋转45度使旋转轴与y轴重合
glRotatef(-45, 1, 0, 0);
//先绕z轴逆时针旋转45度使旋转轴位于yz平面上
glRotatef(45, 0, 0, 1);
//先将旋转轴平移至经过原点
glTranslatef(-5, 0, -5);
glutWireCube(1);
}
- 上面这个例子是原点绕经过(-25, -30, -25),(20, 15, 20)两点的直线进行循环旋转。
我们目标是将其重合于y轴,当然也可以选择z轴和x轴。
从下往上看,最下方是首先应用的矩阵,首先经过简单的数学计算可以知道该直线经过(5,0,5)点,所以调用glTranslatef(-5,
0, -5)使其经过原点。
接下来先绕z轴逆时针旋转45度使旋转轴位于yz平面上,再绕x轴顺时针旋转45度使旋转轴与y轴重合。之后调用glRotatef(10,
0, 1, 0);绕y轴旋转,最后进行逆变换即可
这个角度的计算也很简单,例如求某条轴与xz平面所成的角度,只要求该轴投影至yz平面上与x轴所成的角度即可。投影至yz平面,也只要设置x坐标为0即可,接下来根据正弦和余弦值调用反三角函数就可得出角度。
此例中为了简易起见,将该旋转轴简单设置成与三个平面都成45度角。 (为了方便查看效果,调用glTranslatef(-1, -1,
-20);对整体进行了平移)