构建和观察三维物体

【实验目的】

1. 掌握三维物体的显示方法。

2. 掌握投影变换和照相机位置及方向的设置方法。

3. 掌握几何变换的方法。

【实验原理】 

【实验内容】

阅读arraycube.c,掌握彩色立方体的建模方法,为程序加注释

#include <stdlib.h>

#ifdef __APPLE__

#include <GLUT/glut.h>

#else

#include <GL/glut.h>

#endif

// 顶点坐标

GLdouble vertices[8][3] =

{ {-1.0, -1.0, 1.0},

{-1.0,1.0,1.0},

{1.0,1.0,1.0},

{1.0,-1.0,1.0},{-1.0,-1.0,-1.0},

{-1.0,1.0,-1.0}, {1.0,1.0,-1.0}, {1.0,-1.0,-1.0} };

// 颜色值

GLdouble colors[8][3] = { {0.0,0.0,0.0}, {1.0,0.0,0.0},

{1.0,1.0,0.0},{0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0},{0.0,1.0,1.0} };

// 绘制一个四边形,分别设置顶点坐标和颜色

void polygon(int a, int b, int c, int d)

{

/* draw a polygon via list of vertices */

glBegin(GL_QUADS);

glColor3dv(colors[a]);

glVertex3dv(vertices[a]);

glColor3dv(colors[b]);

glVertex3dv(vertices[b]);

glColor3dv(colors[c]);

glVertex3dv(vertices[c]);

glColor3dv(colors[d]);

glVertex3dv(vertices[d]);

glEnd();

}

// 绘制彩色立方体的面

void colorcube()

{

/* map vertices to faces */

polygon(0, 3, 2, 1);

polygon(2, 3, 7, 6);

polygon(0, 4, 7, 3);

polygon(1, 2, 6, 5);

polygon(4, 5, 6, 7);

polygon(0, 1, 5, 4);

}

// 显示回调函数

void display()

{

/* display callback, clear frame buffer and z buffer,/

   and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除颜色缓冲区和深度缓冲区

glMatrixMode(GL_MODELVIEW); //设置当前矩阵为模型视图矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);// 设置观察矩阵

colorcube();// 绘制彩色立方体

glutSwapBuffers(); // 交换前后缓冲区

}

// 窗口大小改变回调函数

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);// 设置视口大小

glMatrixMode(GL_PROJECTION);// 设置当前矩阵为投影矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,

2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);// 设置正交投影矩阵

else

glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,

2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);// 设置正交投影矩阵

glMatrixMode(GL_MODELVIEW);// 设置当前矩阵为模型视图矩阵

}

void main(int argc, char** argv)

{

glutInit(&argc, argv);// 初始化glut

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);// 设置显示模式

glutInitWindowSize(500, 500);// 设置窗口大小

glutCreateWindow("colorcube");// 创建窗口

glClearColor(0.0, 0.0, 0.0, 0.0);// 设置清除颜色

//glShadeModel(GL_SMOOTH);

glShadeModel(GL_FLAT);// 设置着色模式

glutReshapeFunc(myReshape);// 注册窗口大小改变回调函数

glutDisplayFunc(display);//注册显示回调函数

//glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

glutMainLoop();// 进入glut事件处理循环

}

2. 修改arraycube.c,实现交互式地移动照相机来观察已经建模好的彩色立方体。即用鼠标或键盘来改变gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx, upy, upz)函数的9个参数,以此来观察立方体。要求:

(1)交互时采用的鼠标和键盘按键自定。

(2)分别在正投影和透视投影下实现题目中的功能。

正投影

#include <stdlib.h>

#ifdef __APPLE__

#include <GLUT/glut.h>

#else

#include <GL/glut.h>

#endif

GLfloat eyex = 1.0, eyey = 1.0, eyez = 1.0; // 照相机位置

GLfloat atx = 0.0, aty = 0.0, atz = 0.0; // 观察点位置

GLfloat upx = 0.0, upy = 1.0, upz = 0.0; // 上方向

// 顶点坐标

GLdouble vertices[8][3] =

{ {-1.0, -1.0, 1.0},

{-1.0,1.0,1.0},

{1.0,1.0,1.0},

{1.0,-1.0,1.0},{-1.0,-1.0,-1.0},

{-1.0,1.0,-1.0}, {1.0,1.0,-1.0}, {1.0,-1.0,-1.0} };

// 颜色值

GLdouble colors[8][3] = { {0.0,0.0,0.0}, {1.0,0.0,0.0},

{1.0,1.0,0.0},{0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0},{0.0,1.0,1.0} };

// 绘制一个四边形,分别设置顶点坐标和颜色

void polygon(int a, int b, int c, int d)

{

/* draw a polygon via list of vertices */

glBegin(GL_QUADS);

glColor3dv(colors[a]);

glVertex3dv(vertices[a]);

glColor3dv(colors[b]);

glVertex3dv(vertices[b]);

glColor3dv(colors[c]);

glVertex3dv(vertices[c]);

glColor3dv(colors[d]);

glVertex3dv(vertices[d]);

glEnd();

}

// 绘制彩色立方体的面

void colorcube()

{

/* map vertices to faces */

polygon(0, 3, 2, 1);

polygon(2, 3, 7, 6);

polygon(0, 4, 7, 3);

polygon(1, 2, 6, 5);

polygon(4, 5, 6, 7);

polygon(0, 1, 5, 4);

}

// 显示回调函数

void display()

{

/* display callback, clear frame buffer and z buffer,/

   and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除颜色缓冲区和深度缓冲区

glMatrixMode(GL_MODELVIEW); //设置当前矩阵为模型视图矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx, upy, upz);// 设置观察矩阵

colorcube();// 绘制彩色立方体

glutSwapBuffers(); // 交换前后缓冲区

}

// 窗口大小改变回调函数

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);// 设置视口大小

glMatrixMode(GL_PROJECTION);// 设置当前矩阵为投影矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,

2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);// 设置正交投影矩阵

else

glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,

2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);// 设置正交投影矩阵

glMatrixMode(GL_MODELVIEW);// 设置当前矩阵为模型视图矩阵

}

// 键盘事件处理函数

void keyboard(unsigned char key, int x, int y)

{

switch (key)

{

case 'w':

eyey += 0.1;

break;

case 's':

eyey -= 0.1;

break;

case 'a':

eyex -= 0.1;

break;

case 'd':

eyex += 0.1;

break;

}

glutPostRedisplay(); // 标记当前窗口需要重新绘制

}

// 鼠标事件处理函数

void mouse(int button, int state, int x, int y)

{

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

{

atx = (2.0 * x - 500) / 500.0;

aty = (500 - 2.0 * y) / 500.0;

glutPostRedisplay();

}

}

void main(int argc, char** argv)

{

glutInit(&argc, argv);// 初始化glut

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);// 设置显示模式

glutInitWindowSize(500, 500);// 设置窗口大小

glutCreateWindow("colorcube");// 创建窗口

glClearColor(0.0, 0.0, 0.0, 0.0);// 设置清除颜色

//glShadeModel(GL_SMOOTH);

glShadeModel(GL_FLAT);// 设置着色模式

glEnable(GL_DEPTH_TEST); // 启用深度测试

glutReshapeFunc(myReshape);// 注册窗口大小改变回调函数

glutDisplayFunc(display);//注册显示回调函数

//glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

glutKeyboardFunc(keyboard); // 注册键盘事件处理函数

glutMouseFunc(mouse); // 注册鼠标事件处理函数

glutMainLoop();// 进入glut事件处理循环

}

透视投影:

#include <stdlib.h>

#ifdef __APPLE__

#include <GLUT/glut.h>

#else

#include <GL/glut.h>

#endif

GLfloat eyex = 0.0, eyey = 0.0, eyez = 5.0; // 照相机位置

GLfloat atx = 0.0, aty = 0.0, atz = 0.0; // 观察点位置

GLfloat upx = 0.0, upy = 1.0, upz = 0.0; // 上方向

// 顶点坐标

GLdouble vertices[8][3] =

{ {-1.0, -1.0, 1.0},

{-1.0,1.0,1.0},

{1.0,1.0,1.0},

{1.0,-1.0,1.0},{-1.0,-1.0,-1.0},

{-1.0,1.0,-1.0}, {1.0,1.0,-1.0}, {1.0,-1.0,-1.0} };

// 颜色值

GLdouble colors[8][3] = { {0.0,0.0,0.0}, {1.0,0.0,0.0},

{1.0,1.0,0.0},{0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0},{0.0,1.0,1.0} };

// 绘制一个四边形,分别设置顶点坐标和颜色

void polygon(int a, int b, int c, int d)

{

/* draw a polygon via list of vertices */

glBegin(GL_QUADS);

glColor3dv(colors[a]);

glVertex3dv(vertices[a]);

glColor3dv(colors[b]);

glVertex3dv(vertices[b]);

glColor3dv(colors[c]);

glVertex3dv(vertices[c]);

glColor3dv(colors[d]);

glVertex3dv(vertices[d]);

glEnd();

}

// 绘制彩色立方体的面

void colorcube()

{

/* map vertices to faces */

polygon(0, 3, 2, 1);

polygon(2, 3, 7, 6);

polygon(0, 4, 7, 3);

polygon(1, 2, 6, 5);

polygon(4, 5, 6, 7);

polygon(0, 1, 5, 4);

}

// 显示回调函数

void display()

{

/* display callback, clear frame buffer and z buffer,/

   and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除颜色缓冲区和深度缓冲区

glMatrixMode(GL_MODELVIEW); //设置当前矩阵为模型视图矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx, upy, upz);// 设置观察矩阵

colorcube();// 绘制彩色立方体

glutSwapBuffers(); // 交换前后缓冲区

}

// 窗口大小改变回调函数

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);// 设置视口大小

glMatrixMode(GL_PROJECTION);// 设置当前矩阵为投影矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);

glMatrixMode(GL_MODELVIEW);// 设置当前矩阵为模型视图矩阵

}

// 键盘事件处理函数

void keyboard(unsigned char key, int x, int y)

{

switch (key)

{

case 'w':

eyey += 0.1;

break;

case 's':

eyey -= 0.1;

break;

case 'a':

eyex -= 0.1;

break;

case 'd':

eyex += 0.1;

break;

}

glutPostRedisplay(); // 标记当前窗口需要重新绘制

}

// 鼠标事件处理函数

void mouse(int button, int state, int x, int y)

{

if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)

{

atx = (2.0 * x - 500) / 500.0;

aty = (500 - 2.0 * y) / 500.0;

glutPostRedisplay();

}

}

void main(int argc, char** argv)

{

glutInit(&argc, argv);// 初始化glut

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);// 设置显示模式

glutInitWindowSize(500, 500);// 设置窗口大小

glutCreateWindow("colorcube");// 创建窗口

glClearColor(0.0, 0.0, 0.0, 0.0);// 设置清除颜色

//glShadeModel(GL_SMOOTH);

glShadeModel(GL_FLAT);// 设置着色模式

glEnable(GL_DEPTH_TEST); // 启用深度测试

glutReshapeFunc(myReshape);// 注册窗口大小改变回调函数

glutDisplayFunc(display);//注册显示回调函数

//glEnable(GL_DEPTH_TEST); /* Enable hidden--surface--removal */

glutKeyboardFunc(keyboard); // 注册键盘事件处理函数

glutMouseFunc(mouse); // 注册鼠标事件处理函数

glutMainLoop();// 进入glut事件处理循环

}

3. 在arraycube.c的基础上编写一个交互式程序,实现立方体的旋转。具体要求如下:

(1)立方体的旋转方式由鼠标和键盘按键来控制:按下鼠标左键,立方体绕x轴连续旋转;按下鼠标左键+ctrl键,立方体绕y轴连续旋转;按下鼠标右键,立方体绕z轴连续旋转。(注意:旋转的不动点在原点,正好是立方体的中心。)

#include <stdlib.h>

#ifdef __APPLE__

#include <GLUT/glut.h>

#else

#include <GL/glut.h>

#endif

GLfloat angleX = 0.0;

GLfloat angleY = 0.0;

GLfloat angleZ = 0.0;

bool leftButtonPressed = false;

bool ctrlPressed = false;

bool rightButtonPressed = false;

// 顶点坐标

GLdouble vertices[8][3] =

{ {-1.0, -1.0, 1.0},

{-1.0,1.0,1.0},

{1.0,1.0,1.0},

{1.0,-1.0,1.0},{-1.0,-1.0,-1.0},

{-1.0,1.0,-1.0}, {1.0,1.0,-1.0}, {1.0,-1.0,-1.0} };

// 颜色值

GLdouble colors[8][3] = { {0.0,0.0,0.0}, {1.0,0.0,0.0},

{1.0,1.0,0.0},{0.0,1.0,0.0}, {0.0,0.0,1.0},

{1.0,0.0,1.0}, {1.0,1.0,1.0},{0.0,1.0,1.0} };

// 绘制一个四边形,分别设置顶点坐标和颜色

void polygon(int a, int b, int c, int d)

{

/* draw a polygon via list of vertices */

glBegin(GL_QUADS);

glColor3dv(colors[a]);

glVertex3dv(vertices[a]);

glColor3dv(colors[b]);

glVertex3dv(vertices[b]);

glColor3dv(colors[c]);

glVertex3dv(vertices[c]);

glColor3dv(colors[d]);

glVertex3dv(vertices[d]);

glEnd();

}

// 绘制彩色立方体的面

void colorcube()

{

/* map vertices to faces */

polygon(0, 3, 2, 1);

polygon(2, 3, 7, 6);

polygon(0, 4, 7, 3);

polygon(1, 2, 6, 5);

polygon(4, 5, 6, 7);

polygon(0, 1, 5, 4);

}

// 显示回调函数

void display()

{

/* display callback, clear frame buffer and z buffer,/

   and draw, swap buffers */

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);// 清除颜色缓冲区和深度缓冲区

glMatrixMode(GL_MODELVIEW); //设置当前矩阵为模型视图矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);// 设置观察矩阵

glRotatef(angleX, 1.0f, 0.0f, 0.0f);

glRotatef(angleY, 0.0f, 1.0f, 0.0f);

glRotatef(angleZ, 0.0f, 0.0f, 1.0f);

colorcube();// 绘制彩色立方体

glutSwapBuffers(); // 交换前后缓冲区

}

// 窗口大小改变回调函数

void myReshape(int w, int h)

{

glViewport(0, 0, w, h);// 设置视口大小

glMatrixMode(GL_PROJECTION);// 设置当前矩阵为投影矩阵

glLoadIdentity();// 重置当前矩阵为单位矩阵

if (w <= h)

glOrtho(-2.0, 2.0, -2.0 * (GLfloat)h / (GLfloat)w,

2.0 * (GLfloat)h / (GLfloat)w, -10.0, 10.0);// 设置正交投影矩阵

else

glOrtho(-2.0 * (GLfloat)w / (GLfloat)h,

2.0 * (GLfloat)w / (GLfloat)h, -2.0, 2.0, -10.0, 10.0);// 设置正交投影矩阵

glMatrixMode(GL_MODELVIEW);// 设置当前矩阵为模型视图矩阵

}

void mouse(int button, int state, int x, int y)

{

if (button == GLUT_LEFT_BUTTON)

{

leftButtonPressed = (state == GLUT_DOWN);

}

else if (button == GLUT_RIGHT_BUTTON)

{

rightButtonPressed = (state == GLUT_DOWN);

}

// Check if Ctrl key is pressed

ctrlPressed = (glutGetModifiers() ==GLUT_ACTIVE_CTRL);

glutPostRedisplay();

}

void updateRotation(int value)

{

const float rotationSpeed = 0.5f;

if (leftButtonPressed)

{

if (ctrlPressed)

{

angleY += rotationSpeed;

}

else

{

angleX += rotationSpeed;

}

}

if (rightButtonPressed)

{

angleZ += rotationSpeed;

}

glutPostRedisplay();

}

void idle()

{

updateRotation(10);

}

void main(int argc, char** argv)

{

glutInit(&argc, argv);// 初始化glut

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);// 设置显示模式

glutInitWindowSize(500, 500);// 设置窗口大小

glutCreateWindow("colorcube");// 创建窗口

glClearColor(0.0, 0.0, 0.0, 0.0);// 设置清除颜色

//glShadeModel(GL_SMOOTH);

glShadeModel(GL_FLAT);// 设置着色模式

glutReshapeFunc(myReshape);// 注册窗口大小改变回调函数

glutDisplayFunc(display);//注册显示回调函数

glutMouseFunc(mouse); // 注册鼠标事件处理函数

glutIdleFunc(idle);

glEnable(GL_DEPTH_TEST);

glutMainLoop();// 进入glut事件处理循环

}

  1. 如果旋转的不动点不在原点,而改为点P(1,1,1),如何实现立方体绕3个坐标轴的旋转?

要实现立方体围绕点P(1,1,1)绕三个坐标轴的旋转,可以采取以下步骤:

将立方体平移到点P(1,1,1)处。这可以通过将每个顶点的坐标减去(1,1,1)来实现。

执行旋转操作。对于围绕X轴的旋转,使用glRotatef(angleX, 1.0f, 0.0f, 0.0f);对于围绕Y轴的旋转,使用glRotatef(angleY, 0.0f, 1.0f, 0.0f);对于围绕Z轴的旋转,使用glRotatef(angleZ, 0.0f, 0.0f, 1.0f)。

将立方体平移回原来的位置。这可以通过将每个顶点的坐标加上(1,1,1)来实现。

void display()

{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

gluLookAt(5.0, 5.0, 5.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0);

glTranslatef(1.0f, 1.0f, 1.0f); // 平移到点P(1,1,1)

glRotatef(angleX, 1.0f, 0.0f, 0.0f); // 绕X轴旋转

glRotatef(angleY, 0.0f, 1.0f, 0.0f); // 绕Y轴旋转

glRotatef(angleZ, 0.0f, 0.0f, 1.0f); // 绕Z轴旋转

glTranslatef(-1.0f, -1.0f, -1.0f); // 平移回原来的位置

colorcube();

glutSwapBuffers();

}

(3)如果要求每按下一次鼠标按键或键盘按键,立方体旋转的角度增加5度,应如何修改程序?

在全局变量中定义表示角度增量的变量,例如float rotationSpeed= 5.0f;。

在updateRotation函数中,并且将旋转角度的增量改为rotationSpeed

void updateRotation(int value)

{

if (leftButtonPressed)

{

if (ctrlPressed)

{

angleY += rotationSpeed;

}

else

{

angleX += rotationSpeed;

}

}

if (rightButtonPressed)

{

angleZ += rotationSpeed;

}

glutPostRedisplay();

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值