OpenGL的矩阵使用——绘制桌子

其中最左边的桌子循环上移(即匀速上移到一定位置后回到原点继续匀速上移),中间的桌子不断旋转(即绕自身中间轴旋转),最右边的桌子循环缩小(即不断缩小到一定大小后回归原来大小继续缩小)。

img

桌子的模型尺寸如下:

img


操作方法和实验步骤

绘制桌子

根据题目要求,主要实现的是桌子的移动、旋转和缩放,因此首先需要绘制出桌子的形状。

由于题目要求的桌子主要由五个立法体组成,分别是一个桌面和四个桌脚,而立方体又是由6个面组成的,因此通过绘制模式GL_QUAD绘制所有的面即可;如图:

img

一个立方体的大小和位置有中心点位置和长宽高决定(假设中点位置坐标为x、y、z),因此我们可以得到四个面、二十四个点的位置为:

1
2
3
4
5
6
7
8
9
10
11
{ x + width,y + depth,z },{ x + width,y - depth,z },{ x - width,y - depth,z },{ x - width,y + depth,z },

{ x - width,y + depth,z },{ x - width,y - depth,z },{ x - width,y - depth,z - height },{ x - width,y + depth,z - height },

{ x - width,y + depth,z - height },{ x - width,y - depth,z - height },{ x + width,y - depth,z - height },{ x + width,y + depth,z - height },

{ x + width,y + depth,z - height },{ x + width,y - depth,z - height },{ x + width,y - depth,z },{ x + width,y + depth,z },

{ x + width,y + depth,z },{ x - width,y + depth,z },{ x - width,y + depth,z - height },{ x + width,y + depth,z - height },

{ x + width,y - depth,z },{ x - width,y - depth,z },{ x - width,y - depth,z - height },{ x + width,y - depth,z - height }

设置多边形的绘制模式为glPolygonMode(GL_FRONT_AND_BACK,GL_LINE),绘制出立方体来:

1
2
3
4
glBegin(GL_QUADS);
for (int i = 0; i < 24; i++)
glVertex3f(point[i][0], point[i][1],point[i][2]);
glEnd();

最后把绘制立方体的过程封装成函数,传入中心点位置和长宽高即可绘制出桌子;


桌子循环上移、旋转、缩小放大

循环上移通过函数glTranslatefglRotateglScale完成桌子移动、旋转和缩放的操作;这几个函数的操作原理是将当前的栈顶矩阵乘以一个操作矩阵(移动、旋转、缩放),因此每次绘制前我们都需要通过glLoadIdentity()将当前的操作矩阵矩阵重置为单位矩阵;然在具体的移动或旋转或缩放操作时,将操作矩阵压进栈中,避免这三个操作相互影响;


移动

void glTranslatef(GLfloatx,GLfloat y,GLfloat z);

函数功能: 沿X轴正方向平移x个单位

​ 沿Y轴正方向平移y个单位

​ 沿Z轴正方向平移z个单位

img

旋转

void glRotatef(GLfloatangle,GLfloat x,GLfloat y,GLfloat z);

函数功能:以点(0,0,0)到点(x,y,z)为轴,旋转angle角度;

img

根据题目要求,绕着y轴旋转,即用右手握住这条y轴向量,大拇指指向向量的正方向,四指环绕的方向就是旋转的方向;

缩放

void glScalef(GLfloat Sx, GLfloat Sy, GLfloat Sz);

函数功能:Sx,Sy,Sz分别为模型在x,y,z轴方向的缩放比;

img


源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119


float fTranslate;
float fRotate;
float fScale = 1.0f;

void (GLfloat x, GLfloat y , GLfloat z,GLfloat width_, GLfloat depth_, GLfloat height_) {
GLfloat width = width_ * 0.5;
GLfloat depth = depth_ * 大专栏  OpenGL的矩阵使用——绘制桌子pan class="number">0.5;
GLfloat height = height_;

GLfloat point[24][3] = {
{ x + width,y + depth,z },{ x + width,y - depth,z },{ x - width,y - depth,z },{ x - width,y + depth,z },
{ x - width,y + depth,z },{ x - width,y - depth,z },{ x - width,y - depth,z - height },{ x - width,y + depth,z - height },
{ x - width,y + depth,z - height },{ x - width,y - depth,z - height },{ x + width,y - depth,z - height },{ x + width,y + depth,z - height },
{ x + width,y + depth,z - height },{ x + width,y - depth,z - height },{ x + width,y - depth,z },{ x + width,y + depth,z },
{ x + width,y + depth,z },{ x - width,y + depth,z },{ x - width,y + depth,z - height },{ x + width,y + depth,z - height },
{ x + width,y - depth,z },{ x - width,y - depth,z },{ x - width,y - depth,z - height },{ x + width,y - depth,z - height }
};

glBegin(GL_QUADS);
for (int i = 0; i < 24; i++)
glVertex3f(point[i][0], point[i][1],point[i][2]);
glEnd();
}

void Draw_Dest() // This function draws a triangle with RGB colors
{
Draw_Cube(0, 0, 0, 1, 0.8, 0.2); //桌面
Draw_Cube(0.3, 0.2, -0.2, 0.2, 0.2, 0.6);//桌脚
Draw_Cube(-0.3, 0.2, -0.2, 0.2, 0.2, 0.6);
Draw_Cube(0.3, -0.2, -0.2, 0.2, 0.2, 0.6);
Draw_Cube(-0.3, -0.2, -0.2, 0.2, 0.2, 0.6);
}

void reshape(int width, int height)
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}

glViewport(0,0,width,height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}

void idle()
{
glutPostRedisplay();
}

void redraw()
{

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity(); // Reset The Current Modelview Matrix

glPushMatrix();
glTranslatef(-2.0f, 0.0f,-6.0f); // Place the triangle Left
glTranslatef(0.0f, fTranslate, 0.0f); // Translate in Y direction
Draw_Dest(); // Draw desk
glPopMatrix();

glPushMatrix();
glTranslatef(0.0f, 0.0f,-6.0f); // Place the dest at Center
glRotatef(fRotate, 0, 3.0f, 0); // Rotate around Y axis
Draw_Dest(); // Draw desk
glPopMatrix();

glPushMatrix();
glTranslatef(2.0f, 0.0f, -6.0f); // Place the dest right
glScalef(fScale, fScale, fScale); // Scale
Draw_Dest(); // Draw Draw desk
glPopMatrix();

fScale -= 0.005f;
fTranslate += 0.005f;
fRotate += 0.3f;

if (fTranslate > 0.5f) fTranslate = 0.0f;
if (fScale < 0.5f) fScale = 1.0f;

glutSwapBuffers();
}

void processNormalKeys(unsigned char key, int x, int y)
{

if (key == 27) //按ESC退出
exit(0);
}

int main (int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(640,480);
glutCreateWindow("Exercise2");

glutDisplayFunc(redraw);
glutReshapeFunc(reshape);
glutIdleFunc(idle);

glutKeyboardFunc(processNormalKeys);

glutMainLoop();

return 0;
}


效果

img

原文地址:https://www.cnblogs.com/lijianming180/p/12255935.html