《计算机图形学》实验 4

一、实验目的:

1) 三维物体的构建;
2) 三视图的生成

二、实验内容

共有三道题目。请根据给定的实验结果样例,结合参考程序设计程序,实现样例的显示效果,把程序代码和实验截图拷贝到实验报告中。
注意:每张图的名字要设置为“图例名+姓名”。
题目 1:
设计程序在三维空间绘制立方体。
1) 生成一个正方体,每个面的颜色不同;
2) 可以通过键盘操作,实现三维观察;

效果:
在这里插入图片描述

代码:

#include <GL/glut.h>
#include <math.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#define PI 3.1416
GLfloat xRot = 0;
GLfloat yRot = 0;
GLfloat zRot = 0;
void Init(void)
{
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glColor3f(1.0f, 1.0f, 0.0f);
	// 把着色模式设置为单调着色
	glShadeModel(GL_FLAT); //glShadeModel(GL_SMOOTH);
	 // 把顺时针环绕的多边形设为正面,这与默认是相反的
	glFrontFace(GL_CW);
	glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
}
void SpecialKeys(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)
		xRot -= 5.0f;
	if (key == GLUT_KEY_DOWN)
		xRot += 5.0f;
	if (key == GLUT_KEY_LEFT)
		yRot -= 5.0f;
	if (key == GLUT_KEY_RIGHT)
		yRot += 5.0f;
	if (key > 356.0f)
		xRot = 0.0f;
	if (key < -1.0f)
		xRot = 355.0f;
	if (key > 356.0f)
		yRot = 0.0f;
	if (key < -1.0f)
		yRot = 355.0f;
	if (key == GLUT_KEY_F1) //绕着 z 轴旋转
		zRot += 5.0f;
	// 使用新的坐标重新绘制场景
	glutPostRedisplay();
}
void RenderScene()
{
	// 存储坐标和角度
	GLfloat x, y, z, angle, x1, y1;
	// 用于三角形颜色的交替设置
	int iPivot = 1;
	// 用默认颜色设置背景色,并清除深度缓冲区(必须的,因为 3D 空间有视景深度)
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//打开剔除功能(背面剔除,它用于消除一个表面的背面)
	//glEnable(GL_CULL_FACE);
	// 打开深度测试,如果不打开深度测试,3D 锥体的显示就会与现实情况不符合
	glEnable(GL_DEPTH_TEST);
	// 保存矩阵状态并旋转
	glPushMatrix();
	glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(yRot, 0.0f, 1.0f, 0.0f);
	glRotatef(zRot, 0.0f, 0.0f, 1.0f);
	
	//立方体正面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(1.0f, 1.0f, 1.0f);
	glVertex3f(-0.5, -0.5, 0.5);
	glVertex3f(0.5, -0.5, 0.5);
	glVertex3f(0.5, 0.5, 0.5);
	glVertex3f(-0.5, 0.5, 0.5);
	glVertex3f(-0.5, -0.5, 0.5);
	glEnd();

	//立方体后面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.5f, 1.0f, 0.5f);
	glVertex3f(-0.5, -0.5, -0.5);
	glVertex3f(0.5, -0.5, -0.5);
	glVertex3f(0.5, 0.5, -0.5);
	glVertex3f(-0.5, 0.5, -0.5);
	glVertex3f(-0.5, -0.5, -0.5);
	glEnd();

	//立方体左面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.3f, 0.3f, 0.8f);
	glVertex3f(-0.5, -0.5, -0.5);
	glVertex3f(-0.5, -0.5, 0.5);  
	glVertex3f(-0.5, 0.5, 0.5);
	glVertex3f(-0.5, 0.5, -0.5);
	glVertex3f(-0.5, -0.5, -0.5);
	glEnd();

	//立方体右面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.8f, 0.3f, 0.3f);
	glVertex3f(0.5, -0.5, -0.5);
	glVertex3f(0.5, -0.5, 0.5);
	glVertex3f(0.5, 0.5, 0.5);
	glVertex3f(0.5, 0.5, -0.5);
	glVertex3f(0.5, -0.5, -0.5);
	glEnd();

	//立方体上面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(1.0f, 1.0f, 0.0f);
	glVertex3f(0.5, 0.5, -0.5);
	glVertex3f(-0.5, 0.5, -0.5);
	glVertex3f(-0.5, 0.5, 0.5);
	glVertex3f(0.5, 0.5, 0.5);
	glVertex3f(0.5, 0.5, -0.5);
	glEnd();

	//立方体下面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.0f, 1.0f, 1.0f);
	glVertex3f(-0.5, -0.5, -0.5);
	glVertex3f(0.5, -0.5, -0.5);
	glVertex3f(0.5, -0.5, 0.5);
	glVertex3f(-0.5, -0.5, 0.5);
	glVertex3f(-0.5, -0.5, -0.5);
	glEnd();

	glPopMatrix();
	glutSwapBuffers();
}
int main(int argv, char* argc[]) {
	glutInit(&argv, argc);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(400, 300);
	glutCreateWindow("三维空间绘制立方体 陈彬彬 ");
	glutDisplayFunc(RenderScene);
	glutSpecialFunc(SpecialKeys);
	Init();
	glutMainLoop();
}

题目 2:
设计程序在三维空间绘制三棱柱。
1) 生成一个三棱柱;
2) 可以通过键盘操作,实现三维观察;

效果:
在这里插入图片描述

代码:

#include <GL/glut.h>
#include <math.h>
#pragma comment(linker,"/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
#define PI 3.1416
GLfloat xRot = 0;
GLfloat yRot = 0;
GLfloat zRot = 0;
void Init(void)
{
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
	glColor3f(1.0f, 1.0f, 0.0f);
	// 把着色模式设置为单调着色
	glShadeModel(GL_FLAT); //glShadeModel(GL_SMOOTH);
	 // 把顺时针环绕的多边形设为正面,这与默认是相反的
	glFrontFace(GL_CW);
	glOrtho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);
}
void SpecialKeys(int key, int x, int y)
{
	if (key == GLUT_KEY_UP)
		xRot -= 5.0f;
	if (key == GLUT_KEY_DOWN)
		xRot += 5.0f;
	if (key == GLUT_KEY_LEFT)
		yRot -= 5.0f;
	if (key == GLUT_KEY_RIGHT)
		yRot += 5.0f;
	if (key > 356.0f)
		xRot = 0.0f;
	if (key < -1.0f)
		xRot = 355.0f;
	if (key > 356.0f)
		yRot = 0.0f;
	if (key < -1.0f)
		yRot = 355.0f;
	if (key == GLUT_KEY_F1) //绕着 z 轴旋转
		zRot += 5.0f;
	// 使用新的坐标重新绘制场景
	glutPostRedisplay();
}
void RenderScene()
{
	// 存储坐标和角度
	GLfloat x, y, z, angle, x1, y1;
	// 用于三角形颜色的交替设置
	int iPivot = 1;
	// 用默认颜色设置背景色,并清除深度缓冲区(必须的,因为 3D 空间有视景深度)
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	//打开剔除功能(背面剔除,它用于消除一个表面的背面)
	//glEnable(GL_CULL_FACE);
	// 打开深度测试,如果不打开深度测试,3D 锥体的显示就会与现实情况不符合
	glEnable(GL_DEPTH_TEST);
	// 保存矩阵状态并旋转
	glPushMatrix();
	glRotatef(xRot, 1.0f, 0.0f, 0.0f);
	glRotatef(yRot, 0.0f, 1.0f, 0.0f);
	glRotatef(zRot, 0.0f, 0.0f, 1.0f);
	
	//三棱柱正面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(1.0, 1.0, 1.0);
	glVertex3f(0.0, 0.0, 0.5);    //左上角
	glVertex3f(-0.5, -0.5, 0.5);  //左下角
	glVertex3f(-0.5, -0.5, 0.5);  //右上角
	glVertex3f(0.5, -0.5, 0.5);   //右下角
	glEnd();

	//三棱柱后面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.5, 1.0, 0.5);
	glVertex3f(-0.5, -0.5, -0.5); //后面的右下角
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(0.0, 0.0, -0.5);   //后面的左上角
	glEnd();

	//三棱柱左面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.3, 0.3, 0.8);
	glVertex3f(-0.5, -0.5, 0.5);  //正面的左下角
	glVertex3f(0.0, 0.0, 0.5);    //顶点
	glVertex3f(0.0, 0.0, -0.5);   //右面的顶点
	glVertex3f(-0.5,-0.5, -0.5);  //后面的右下角
	glEnd();

	//三棱柱右面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.8, 0.3, 0.3);
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(0.5, -0.5, 0.5);   //正面的右下角
	glVertex3f(0.0, 0.0, 0.5);    //左面的顶点
	glVertex3f(0.0, 0.0, -0.5);   //顶点
	glEnd();

	//三棱柱下面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.0, 1.0, 1.0);
	glVertex3f(-0.5, -0.5, -0.5);
	glVertex3f(-0.5, -0.5, 0.5);  //正面的左下角
	glVertex3f(0.5, -0.5, 0.5);   //正面的右下角
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(-0.5, -0.5, -0.5); //后面的右下角
	glEnd();

	glPopMatrix();
	glutSwapBuffers();
}
int main(int argv, char* argc[]) {
	glutInit(&argv, argc);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(400, 300);
	glutCreateWindow("三棱柱 陈彬彬 ");
	glutDisplayFunc(RenderScene);
	glutSpecialFunc(SpecialKeys);
	Init();
	glutMainLoop();
}

点的顺序错误造成的绘制错误:
在这里插入图片描述
题目 3:
设计程序在实现上题中三棱柱的三视图。
本题中显示的三视图:

效果:
在这里插入图片描述在这里插入图片描述

代码:

#include <GL/glut.h>
void axis(double length)
{
	glColor3f(1.0f, 1.0f, 1.0f);
	glPushMatrix();
	glBegin(GL_LINES);
	glVertex3d(0.0, 0.0, 0.0);
	glVertex3d(0.0, 0.0, length);
	glEnd();
	//将当前操作点移到指定位置
	glTranslated(0.0, 0.0, length - 0.2);
	glColor3f(1.0, 0.0, 0.0);
	glutWireCone(0.04, 0.3, 8, 8);
	glPopMatrix();
}
void RenderScene()
{
	glEnable(GL_DEPTH_TEST);

	//三棱柱正面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(1.0, 1.0, 1.0);
	glVertex3f(0.0, 0.0, 0.5);    //左上角
	glVertex3f(-0.5, -0.5, 0.5);  //左下角
	glVertex3f(-0.5, -0.5, 0.5);  //右上角
	glVertex3f(0.5, -0.5, 0.5);   //右下角
	glEnd();

	//三棱柱后面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.5, 1.0, 0.5);
	glVertex3f(-0.5, -0.5, -0.5); //后面的右下角
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(0.0, 0.0, -0.5);   //后面的左上角
	glEnd();

	//三棱柱左面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.3, 0.3, 0.8);
	glVertex3f(-0.5, -0.5, 0.5);  //正面的左下角
	glVertex3f(0.0, 0.0, 0.5);    //顶点
	glVertex3f(0.0, 0.0, -0.5);   //右面的顶点
	glVertex3f(-0.5,-0.5, -0.5);  //后面的右下角
	glEnd();

	//三棱柱右面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.8, 0.3, 0.3);
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(0.5, -0.5, 0.5);   //正面的右下角
	glVertex3f(0.0, 0.0, 0.5);    //左面的顶点
	glVertex3f(0.0, 0.0, -0.5);   //顶点
	glEnd();


	//三棱柱下面
	glBegin(GL_TRIANGLE_FAN);
	glColor3f(0.0, 1.0, 1.0);
	glVertex3f(-0.5, -0.5, -0.5);
	glVertex3f(-0.5, -0.5, 0.5);  //正面的左下角
	glVertex3f(0.5, -0.5, 0.5);   //正面的右下角
	glVertex3f(0.5, -0.5, -0.5);  //后面的左下角
	glVertex3f(-0.5, -0.5, -0.5); //后面的右下角
	glEnd();

	glPopMatrix();
	glutSwapBuffers();
}
void paint(void) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glPointSize(1.0f);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-3.0, 3.0, -3.0, 3.0, -3, 3);
	//gluLookAt(0, 0, 2, 0, 0, 0, 0, 1, 0);//正视图
	//gluLookAt(2, 0, 0, 0, 0, 0, 0, 1, 0);//侧视图
	gluLookAt(0, 2, 0, 0, 0, 0, 1, 0, 0);//俯视图
	//画坐标系
	axis(2.0);
	glPushMatrix();
	glRotated(90.0, 0, 1.0, 0);//绕 y 轴正方向旋转 90 度

	axis(2.0);
	glPopMatrix();
	glPushMatrix();
	glRotated(-90, 1, 0, 0);//绕 x 轴负方向旋转

	axis(2.0);
	glPopMatrix();
	glRotated(90, 0, 1, 0);
	RenderScene();//三棱柱立体图形
	glFlush();
}
int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(200, 200);
	glutCreateWindow("三棱柱俯视图 陈彬彬");
	glutDisplayFunc(paint);
	glutMainLoop();
}

四、主要函数说明:

  1. glShadeModel(GLenum mode)
    函数功能:上色

(1)mode 指明使用哪种着色技术,可以取值 GL_FLATGL_SMOOTH。默认取值是 GL_SMOOTH。
(2)采用恒定着色时(即 GL_FLAT),使用图元中某个顶点的颜色来渲染整个图元。
(3)在使用光滑着色时(即GL_SMOOTH),独立的处理图元中各个顶点的颜色。
(4)对于线段图元,线段上各点 的颜色将根据两个顶点的颜色通过差值得到,结果就是渐变色。
(5)若使用 GL_FLAT,假设几何图形由 n 个三角形构成,则只会使用顶点颜色数组中最后 n 个颜色进行着色。

  1. gluLookAt()
void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,
 GLdouble centerx,GLdouble centery,GLdouble centerz,
 GLdouble upx,GLdouble upy,GLdouble upz);
  • 第一组 eyex,eyey,eyez 相机在世界坐标的位置
  • 第二组 centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置
  • 第三组 upx,upy,upz 相机向上的方向在世界坐标中的方向

解释:

  • 第一组:相机的位置即是眼睛的位置,就相当于你的头在一个三维坐标中的具体坐标。
  • 第二组:你眼睛要看的物体的坐标。
  • 第三组:你的头的方向,头朝上还是朝下,朝左还是朝右。

对第三组的示例解释:

(1)如果 upx=0,upz=0,upy=1,那么说明头是在坐标系中就是在 y 轴的正向位置,人是站立的, 头朝上;
(2)如果upy=-1,那么说明头是在坐标系中就是在 y 轴的负向位置,相当于人是倒立的,头朝 下。
(3)如果upx=1,upz=0,upy=0,那么说明头是在坐标系中就是在 x 轴的正向位置,相当于我们看 的是物体的右边;
(4)如果upx=-1,那么说明头是在坐标系中就是在 x 轴的负向位置,就相当于看的是 物体的左边。
(5)如果upx=0,upz=1,upy=0,那么说明头是在坐标系中就是在 z 轴的正向位置,相当于我们看 的是屏幕朝我们的方向(z轴正向朝外);
(6)如果 upz=-1,那么说明头是在坐标系中就是在 z 轴的负 向位置,相当于我们看的是屏幕向里的方向。

  • glutSwapBuffers()
    glutSwapBuffers 函数是 OpenGL 中 GLUT 工具包中用于实现双缓冲技术的一个重要函数。该函数的功能是交换两个缓冲区指针。
  • 通常, 我们所看到的窗体、文字、图像,从根本上来说都是“画”出来的。比如,制作一个简单的五子棋,我们可能先要绘制棋盘,然后绘制棋子,我们可能还要绘制一些提示信息。
  • 虽然这些绘制操作有一定的先后顺序,通常情况下,操作系统的这些绘制速度非常的快,使人眼误认为这些绘制操作是同时完成的。
  • 但当我们进行复杂的绘图操作时,画面便可能有明显的闪烁。解决这个问题的关键在于使绘制的东西同时 出现在屏幕上。

所谓双缓冲技术, 是指使用两个缓冲区: 前台缓冲和后台缓冲

  • 前台缓冲即我们看到的屏幕,
  • 后台缓冲则在内存当中,对我们来说是不可见的。
  • 每次的所有绘图操作都在后台缓冲中进行,当绘制完成时,把 绘制的最终结果复制到屏幕上, 这样, 我们看到所有 GDI元素同时出现在屏幕上,从而解决了频繁刷新导致的画面闪烁问题。

注意:

  • 使用 glutSwapBuffers()函数的时候,主程序中的 glutInitDisplayMode()函数需要设置为

glutInitDisplayMode(GLUT_RGB | GLUT_ DOUBLE );

  • 使 用 glFlush() 函 数 的 时 候 主 程 序 中 的 glutInitDisplayMode() 函 数 需 要 设 置 为

glutInitDisplayMode(GLUT_RGB | GLUT_ SINGLE | GLUT_DEPTH);

  • List item

glOrtho()

glOrtho 是创建一个正交平行的视景体。 一般用于物体不会因为离屏幕的远近而产生大小的变换的情况。
glOrtho(left, right, bottom, top, near, far)

  • left 表示视景体左面的坐标,right 表示右面的坐标,bottom 表 示下面的,top 表示上面的。

这个函数简单理解起来,就是一个物体摆在那里,你怎么去截取他。这里,我们先抛开 glViewport 函数不看。先单独理解 glOrtho 的功能。

  • 假设有一个球体,半径为 1,圆心在(0, 0, 0),
  • 那么,我们设定 glOrtho(-1.5, 1.5, -1.5, 1.5, -10,10); 就表示用一个宽高都是 3 的框框把这个球体整个都装了进来。
  • 如果设定 glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽是 1.5, 高是 3的框框把整个球体的右面装进来;
  • 如果设定 glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10);就表示用一个宽和高都是 1.5的框框把球体的右上角装了进来。
    在这里插入图片描述

“老年人常思既往,少年人常思将来。惟思既往也,故生留恋心;惟思将来也,故生希望心。惟留恋也,故保守;惟希望也,故进取。惟保守也,故永旧;惟进取也,故日新。”

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: CSDN是一个知名的技术社区平台,而山东大计算机图形实验则是该计算机专业的一门实践性课程。 在计算机图形实验中,生将有机会习和应用计算机图形的基本原理、算法和技术,以及图像处理和 三维图形的渲染等相关知识。通过这门实验课程,生可以深入了解计算机图形的概念、理论和应用,提升自己的实践能力和解决问题的能力。 CSDN作为一个技术社区平台,与山东大计算机图形实验也存在一定的关联。通过在CSDN上发表和分享个人在计算机图形实验中的经验、习心得和技术总结,生们可以扩展自己的影响力,与其他专业人士进行交流和合作,获取更多实践经验和习资源。 同时,CSDN还提供了丰富的技术文档、资讯、教程等资源,通过在CSDN上搜索相关的计算机图形实验资料,生们能够快速获取到最新的行业动态和术发展,帮助他们更好地理解和应用计算机图形的知识。 总之,CSDN和山东大计算机图形实验相互促进,共同为生的习和成长提供支持和帮助。通过积极利用CSDN的资源和平台,生们可以在实践中不断提升自己的技能,为今后的习和工作打下坚实的基础。 ### 回答2: csdn是一个知识分享平台,而山东大计算机图形实验是该计算机系开设的一门实践课程。这门实验课程旨在教授生有关计算机图形的基本理论和实际操作的知识。 在山东大计算机图形实验中,生将习如何使用计算机图形的技术和工具来创建和处理图像、动画和虚拟现实等内容。课程涵盖了计算机图形的基本概念、算法和应用。生将通过编程和实践项目来加深对这些概念和技术的理解。 在实验课程中,生将习使用常见的图形库和软件工具,如OpenGL、CUDA等。通过使用这些工具,他们将能够实现各种图形技术,如三维渲染、光影处理、动画制作等。此外,他们还将习如何应用图形知识来解决实际问题,如计算机辅助设计、医图像处理等。 在教过程中,教师将为生提供必要的理论知识,并指导他们完成实践项目。生将通过小组合作和个人努力来完成各种编程任务和项目。课程结束时,生将具备良好的计算机图形技能,并能够独立进行图形相关的项目和研究。 通过参加山东大计算机图形实验生将能够深入了解图形的基本原理和应用,掌握常用的图形工具和技术,培养解决实际问题的能力。这门实验课程将为生的术和职业发展提供强有力的支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年游四方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值