opengl绘制桌子(平移、旋转、缩放)

时间:2022-04-28 10:21:47

主要仪器设备

VisualStudio C++2015

Windows10环境

Glut压缩包

Ex2工程

操作方法和实验步骤

1.绘制立方体

opengl绘制桌子(平移、旋转、缩放)

桌子由立方体组成,我们可以通过绘制六个面来构造一个立方体。六个面的绘制需要八个顶点的参数,而每个顶点均有x,y,z三个参数,如果全部传入的话参数的个数会达到8*3=24个。而我们只需要知道2个x,2个y以及2个z即可构造八个顶点。如图所示,它们的坐标分别是(x1,y1,z2), (x2,y1,z2), (x1,y2,z2), (x2,y2,z2), (x1,y1,z1),(x2,y1,z1), (x1,y2,z1), (x2,y2,z1)。每个面使用QL_QUADS方式绘制所使用的顶点是(v1,v2,v4,v3),(v5,v6,v8,v7), (v3,v4,v8,v7), (v1,v2,v6,v5), (v1,v3,v7,v5), (v2,v4,v8,,v6)。

2.绘制桌子

之前已经完成了绘制立方体的函数,现在只需要把桌子拆分成5个立方体进行绘制就可以了。计算需要传入的参数,使用Draw_Cube函数进行绘制。

3.模型变换——平移、旋转、缩放

这部分功能的实现通过重绘时调用函数redraw实现。根据要求使用glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);来确定显示模式为使用线段显示物体所有面。在模型进行平移、旋转、缩放时用到的函数分别是glTranslatef,glRotatef以及glScalef函数。这三个函数中分别利用了三个因子fTranslate,fRotate以及fScale。他们控制了平移的方向,旋转轴以及缩放尺寸等等。

代码如下:

// main.cpp : 定义控制台应用程序的入口点。
#include "glut.h"

float fTranslate;//平移因子
float fRotate;//旋转因子
float fScale=1.0f;//缩放因子

void Draw_Cube(GLfloat x1, GLfloat x2, GLfloat y1,GLfloat y2,GLfloat z1,GLfloat z2)
{ //桌子由立方体组成,已知六个参数即可构造八个顶点
int i, j;
GLfloat vertex[8][3] = {
//八个顶点,从v1-v8
x1,y1,z2,
x2,y1,z2,
x1,y2,z2,
x2,y2,z2,
x1,y1,z1,
x2,y1,z1,
x1,y2,z1,
x2,y2,z1
};
GLint surface[6][4] = {
//v1对应0,以此类推
0,1,3,2,
4,5,7,6,
2,3,7,6,
0,1,5,4,
0,2,6,4,
1,3,7,5
};

glBegin(GL_QUADS);//指定绘制方式
//将每个立方体分成六个面绘制
for (i = 0; i < 6; i++)
for (j = 0; j < 4; j++)
glVertex3fv(vertex[surface[i][j]]);
glEnd();
}
void Draw_Table()
{
//将桌子拆分成5个立方体绘制
Draw_Cube(0.0, 1.0, 0.0, 0.8, 0.6, 0.8);//桌面
Draw_Cube(0.1, 0.3, 0.1, 0.3, 0.0, 0.6);//四条腿
Draw_Cube(0.7, 0.9, 0.1, 0.3, 0.0, 0.6);
Draw_Cube(0.1, 0.3, 0.5, 0.7, 0.0, 0.6);
Draw_Cube(0.7, 0.9, 0.5, 0.7, 0.0, 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()
{
//display in wireframe mode
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glClear(GL_COLOR_BUFFER_BIT);//清除窗口
glLoadIdentity(); // Reset The Current Modelview Matrix
//模型变换——移动
glPushMatrix();//glpushmatrix与glpopmatrix配合使用可以消除上一次变换对本次变换的影响
glTranslatef(-2.5f, 0.0f,-6.0f);//放在左边
glTranslatef(0.0f, fTranslate, 0.0f);
Draw_Table();
glPopMatrix();
//模型变换——旋转
glPushMatrix();
glTranslatef(0.0f, 0.0f,-6.0f);//放在中间
glRotatef(fRotate, 0, 1.0f, 0); // Rotate around Y axis
Draw_Table(); // Draw triangle
glPopMatrix();
//模型变换——缩放
glPushMatrix();
glTranslatef(2.0f, 0.0f, -6.0f);
glScalef(fScale, fScale,fScale);
Draw_Table();
glPopMatrix();
//更新因子
fTranslate += 0.005f;
fRotate += 0.5f;
fScale -= 0.005f;

if(fTranslate > 0.5f)
fTranslate = 0.0f;
if (fScale < 0.5f)//缩小到一定程度之后变回原来大小
fScale = 1.0f;
glutSwapBuffers();
}

int main (int argc, char *argv[])
{
glutInit(&argc, argv);//对glut函数库进行初始化
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);//指定glutCreateWindow函数将要创建的窗口显示模式 RGB 双缓冲
glutInitWindowSize(640,480);//窗口大小
glutCreateWindow("Exercise2");//打开设置好的窗口,进入glutMainLoop之前这个窗口不会显示

glutDisplayFunc(redraw);//指定当前窗口需要重绘时调用的函数
glutReshapeFunc(reshape);//注册窗口大小改变时回调函数
glutIdleFunc(idle); //可以执行连续动画

glutMainLoop();//进入glut事件处理循环,永远不会返回

return 0;
}


实验结果

opengl绘制桌子(平移、旋转、缩放)

其中左边的桌子向上平移到一定的位置回到原位置继续重复动作,中间的桌子绕y轴旋转,右边的桌子逐渐缩小到一定程度回到原大小继续重复动作。



如有错误,请批评指正(*/ω╲*)