# 图形学实验三:基于 OpenGL 的图形学编程初探
# 原 OpenGL 示例代码简单绘制图形:
# cube.cpp
#include <windows.h> | |
#include <glut.h> | |
void init(void) | |
{ | |
glClearColor (0.0, 0.0, 0.0, 0.0); | |
glShadeModel (GL_FLAT); | |
} | |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
Anything you want to display on the screen, draw it here. * * | |
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | |
* Clear the screen. Set the current color to white. | |
* Draw the wire frame cube. | |
*/ | |
void display(void) | |
{ | |
glClear(GL_COLOR_BUFFER_BIT); | |
glColor3f (1.0, 1.0, 1.0); | |
glLoadIdentity (); /* clear the matrix */ | |
//--------------- you can define your own transformation----------- | |
glTranslatef (1.0, 0.0, -5.0); | |
glScalef (1.0, 1.0, 2.0); | |
//---------------- you can draw something else here----------- | |
glutWireCube (1.0); /* draw the cube */ | |
glFlush(); | |
} | |
/* Called when the window is first opened and whenever | |
* the window is reconfigured (moved or resized). | |
*/ | |
void reshape (int w, int h) | |
{ | |
/* define the projection */ | |
glMatrixMode (GL_PROJECTION); | |
glLoadIdentity (); | |
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); | |
glMatrixMode (GL_MODELVIEW); /* back to modelview matrix */ | |
glViewport (0, 0, w, h); /* define the viewport */ | |
} | |
/* Main Loop | |
* Open window with initial window size, title bar, | |
* RGBA display mode, and handle input events. | |
*/ | |
int main(int argc, char** argv) | |
{ | |
glutInit(&argc, argv); | |
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); | |
//define size and the relative positon of the applicaiton window on the display | |
glutInitWindowSize (500, 500); | |
glutInitWindowPosition (100, 100); | |
//init the defined window with "argv[1]" as topic showed on the top the window | |
glutCreateWindow (argv[0]); | |
// opengl setup | |
init (); | |
//define callbacks | |
glutDisplayFunc(display); | |
glutReshapeFunc(reshape); | |
//enter the loop for display | |
glutMainLoop(); | |
return 0; | |
} |
# lines.cpp
/* | |
* lines.c | |
* This program demonstrates different line stipples and widths. | |
*/ | |
#include <windows.h> | |
#include <GL/gl.h> | |
#include <GL/glu.h> | |
#include <glut.h> | |
#define drawOneLine(x1,y1,x2,y2) glBegin(GL_LINES); \ | |
glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd(); | |
void myinit (void) { | |
/* background to be cleared to black */ | |
glClearColor (0.0, 0.0, 0.0, 0.0); | |
glShadeModel (GL_FLAT); | |
} | |
void display(void) | |
{ | |
int i; | |
glClear (GL_COLOR_BUFFER_BIT); | |
/* draw all lines in white */ | |
glColor3f (1.0, 1.0, 1.0); | |
/* in 1st row, 3 lines drawn, each with a different stipple */ | |
glEnable (GL_LINE_STIPPLE); | |
glLineStipple (1, 0x0101); /* dotted */ | |
drawOneLine (50.0, 125.0, 150.0, 125.0); | |
glLineStipple (1, 0x00FF); /* dashed */ | |
drawOneLine (150.0, 125.0, 250.0, 125.0); | |
glLineStipple (1, 0x1C47); /* dash/dot/dash */ | |
drawOneLine (250.0, 125.0, 350.0, 125.0); | |
/* in 2nd row, 3 wide lines drawn, each with different stipple */ | |
glLineWidth (5.0); | |
glLineStipple (1, 0x0101); | |
drawOneLine (50.0, 100.0, 150.0, 100.0); | |
glLineStipple (1, 0x00FF); | |
drawOneLine (150.0, 100.0, 250.0, 100.0); | |
glLineStipple (1, 0x1C47); | |
drawOneLine (250.0, 100.0, 350.0, 100.0); | |
glLineWidth (1.0); | |
/* in 3rd row, 6 lines drawn, with dash/dot/dash stipple, */ | |
/* as part of a single connect line strip */ | |
glLineStipple (1, 0x1C47); | |
glBegin (GL_LINE_STRIP); | |
for (i = 0; i < 7; i++) | |
glVertex2f (50.0 + ((GLfloat) i * 50.0), 75.0); | |
glEnd (); | |
/* in 4th row, 6 independent lines drawn, */ | |
/* with dash/dot/dash stipple */ | |
for (i = 0; i < 6; i++) { | |
drawOneLine (50.0 + ((GLfloat) i * 50.0), | |
50.0, 50.0 + ((GLfloat)(i+1) * 50.0), 50.0); | |
} | |
/* in 5th row, 1 line drawn, with dash/dot/dash stipple */ | |
/* and repeat factor of 5 */ | |
glLineStipple (5, 0x1C47); | |
drawOneLine (50.0, 25.0, 350.0, 25.0); | |
glFlush (); | |
} | |
/* Called when the window is first opened and whenever | |
* the window is reconfigured (moved or resized). | |
*/ | |
void myReshape(int w, int h) | |
{ | |
glViewport(0, 0, w, h); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
gluOrtho2D (0.0, 400.0, 0.0, 150.0); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
} | |
/* Main Loop | |
* Open window with initial window size, title bar, | |
* RGBA display mode, and handle input events. | |
*/ | |
int main(int argc, char** argv) | |
{ | |
glutInit(&argc, argv); | |
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); | |
//define size and the relative positon of the applicaiton window on the display | |
glutInitWindowSize (400, 150); | |
glutInitWindowPosition (0, 0); | |
//init the defined window with "argv[1]" as topic showed on the top the window | |
glutCreateWindow (argv[0]); | |
// opengl setup | |
myinit (); | |
//define callbacks | |
glutReshapeFunc(myReshape); | |
glutDisplayFunc(display); | |
//enter the loop for display | |
glutMainLoop(); | |
return 0; | |
} |
# aim.cpp
/* | |
* aim.c | |
* This program calculates the fovy (field of view angle | |
* in the y direction), by using trigonometry, given the | |
* size of an object and its size. | |
*/ | |
#include <windows.h> | |
#include <stdio.h> | |
#include <math.h> | |
#include <glut.h> | |
void myinit (void) { | |
glShadeModel (GL_FLAT); | |
} | |
/* Clear the screen. Set the current color to white. | |
* Draw the wire frame cube and sphere. | |
*/ | |
void display (void) | |
{ | |
glClear(GL_COLOR_BUFFER_BIT); | |
glColor3f (1.0, 1.0, 1.0); | |
//about front and back facing facets and facet cullig | |
// glCullFace(GL_BACK); | |
// glCullFace(GL_FRONT); | |
glEnable(GL_CULL_FACE); | |
glLoadIdentity (); | |
/* glTranslatef() as viewing transformation */ | |
glTranslatef(-1.5f,0.0f,-15.0f); | |
glBegin(GL_TRIANGLES); // Drawing Using Triangles | |
glVertex3f( 1.2f, 1.0f, 0.0f); // Top | |
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left | |
glVertex3f( 1.0f,-1.0f, 5.0f); // Bottom Right | |
glEnd(); | |
//definition of front facing polygon | |
glFrontFace(GL_CW); | |
glTranslatef(3.0f,0.0f,0.0f); | |
glBegin(GL_QUADS); // Draw A Quad | |
glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left | |
glVertex3f( 1.0f, 1.0f, 2.0f); // Top Right | |
glVertex3f( 1.2f,-1.0f, -1.0f); // Bottom Right | |
glVertex3f(-0.5f,-1.2f, 1.0f); // Bottom Left | |
glEnd(); // Done Drawing The Quad | |
glFlush(); | |
} | |
#define PI 3.1415926535 | |
/* atan2 () is a system math routine which calculates | |
* the arctangent of an angle, given length of the | |
* opposite and adjacent sides of a right triangle. | |
* atan2 () is not an OpenGL routine. | |
*/ | |
GLdouble calculateAngle (double size, double distance) | |
{ | |
GLdouble radtheta, degtheta; | |
radtheta = 2.0 * atan2 (size/2.0, distance); | |
degtheta = (180.0 * radtheta) / PI; | |
printf ("degtheta is %lf\n", degtheta); | |
return ((GLdouble) degtheta); | |
} | |
/* Called when the window is first opened and whenever | |
* the window is reconfigured (moved or resized). | |
*/ | |
void myReshape(int w, int h) | |
{ | |
GLdouble theta; | |
glViewport(0, 0, w, h); | |
glMatrixMode(GL_PROJECTION); | |
glLoadIdentity(); | |
theta = calculateAngle (2.0, 5.0); | |
gluPerspective(theta, (GLfloat) w/(GLfloat) h, 1.0, 20.0); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
} | |
/* Main Loop | |
* Open window with initial window size, title bar, | |
* RGBA display mode, and handle input events. | |
*/ | |
void main(int argc, char** argv) | |
{ | |
glutInit(&argc, argv); | |
glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); | |
//define size and the relative positon of the applicaiton window on the display | |
glutInitWindowSize (500, 500); | |
glutInitWindowPosition (100, 100); | |
//init the defined window with "argv[1]" as topic showed on the top the window | |
glutCreateWindow (argv[0]); | |
// opengl setup | |
myinit (); | |
//define callbacks | |
glutReshapeFunc(myReshape); | |
glutDisplayFunc(display); | |
//enter the loop for display | |
glutMainLoop(); | |
} |
# 实验报告
# 实验内容
- 解压 GlutLib.zip 文件,并按照 “glut 库安装.txt” 中的说明,安装 glut 库。
- 阅读文档 CreateProject.txt,建立自己的工程文件。
- 基于给定的源代码 cube.c 等分别建立工程文件,并编译执行。
- 仔细阅读程序注释,了解利用 OpenGL 进行计算机图形学编程的框架。
- 基于 aim.cpp、lines.cpp 两个源文件分别建立工程文件,调试通过并执行。
- 通过对给定代码进行局部修改,进一步了解部分函数的意义。
- 选作:基于 glut 和 OpenGL 实现用橡皮筋交互定义矩形的功能。
# 实验目的
- 掌握如何建立包含 OpenGL 库函数的工程文件;
- 熟悉如何利用 glut 进行 OpenGL 应用程序的窗口及输入、输出管理等;
- 熟悉 OpenGL 的函数。
# 实验要求
- 通过对给定程序的试运行,解释以下几个函数的作用及各参数的意义:
glTranslatef(float x, float y, float z);
glVertex3f(float x, float y, float z);
glColor3f (float a, float b, float c);
glLineWidth (float a);
glutInitWindowSize (int a,int b);
glutInitWindowPosition (int a,int b);- 分析以下两个函数的区别:
glVertex3f(float x, float y, float z);
glVertex2f(float x, float y);- 说明如何利用 glut 进行 OpenGL 应用程序的窗口及输入、输出管理。
- 分别展示对三个代码的修改,以及执行结果,对比与原来代码执行结果的不同,并说明原因(展示 2-3 个即可)。
# 实验结果
通过对给定程序的试运行,解释以下几个函数的作用及各参数的意义:
glTranslatef(float x, float y, float z);
作用:平移变换函数,
参数意义:x,y,z 表示 x y z 轴glVertex3f(float x, float y, float z);
作用:绘制三维顶点坐标,
参数意义:三维坐标的 x y z 值glColor3f (float a, float b, float c);
作用:颜色设置函数
参数意义:a b c 表示 RGB 值glLineWidth (float a);
作用:设置线段宽度,
参数意义: a 表示宽度值glutInitWindowSize (int a,int b);
作用:设置窗口大小
参数意义: a b 表示窗口长宽值glutInitWindowPosition (int a,int b);
作用:设置窗口位置
参数意义: a,b 表示窗口左上角相对于桌面的坐标分析以下两个函数的区别:
glVertex3f(float x, float y, float z);
glVertex2f(float x, float y);
回答:glVertex3f
表示三维的坐标,glVertex2f
表示二维坐标,二维平面中glVertex3f
把三维坐标映射到二维坐标系。由于屏幕是二维的,每个屏幕上的点对应于三维空间中的一条直线。反投影时提供的 z 坐标就是决定到底需要这直线上的哪一个点。说明如何利用 glut 进行 OpenGL 应用程序的窗口及输入、输出管理。
回答:
(1)鼠标的输入输出管理:
使用函数glutMouseFunc()
就可以检测鼠标的输入,函数为void glutMouseFunc(void(*func)(int button,int state,int x,int y));
参数func
:处理鼠标click
事件的函数的函数名。
第一个参数可能是以下几个中的一个:GLUT_LEFT_BUTTON //鼠标左键 GLUT_MIDDLE_BUTTON //鼠标中键 GLUT_RIGHT_BUTTON //鼠标右键 // 下面两个是重构的OpenGL库函数中带的值,表示滚轮上下滚动的状态 GLUT_WHEEL_UP GLUT_WHEEL_DOWN 第二个参数可能是以下几个中的一个: GLUT_DOWN GLUT_UP //表示鼠标键的按下与放开。
(2)键盘的输入输出管理
使用函数glutKeyboardFunc ()
就可以检测键盘的输入,函数为:void glutKeyboardFunc(void(*func)(unsigned char key,int x,int y));
参数:func
: 处理普通按键消息的函数的名称。如果传递NULL
,则表示GLUT
忽略普通按键消息。
第一个形参表示按下的键的 ASCII 码,另外两个表示键盘按下时鼠标的位置。
(3)glut 的窗口管理函数:glutCreateWindow(); glutCreateSubWindow(); glutHideWindow(); glutShowWindow(); glutSetWindowTitle(); glutPostRedisplay(); glutSwapBuffers(); glutFullScreen(); glutPositionWindow(); glutReshapeWindow(); glutSetWindow(); glutGetWindow(); glutPopWindow(); glutPushWindow(); glutDestroyWindow(); glutIconifyWindow(); glutSetCursor();
(4)输出管理
glutDisplayFunc()
的使用方式是glutDisplayFunc(display);
void display(void)
函数为绘图函数。glutDisplayFunc(&display)
在程序运行时是自动调用的,即程序会自动调用display
函数重绘窗口。调用的时机有以下几种:
1. 窗口内容绘制
2. 窗口大小改变
3. 窗口重绘
当然,这个函数不会单独出现,比如 :glutReshapeFunc(reshape);
函数先控制窗口大小改变时的操作。分别展示对三个代码的修改,以及执行结果,对比与原来代码执行结果的不同,并说明原因(展示 2-3 个即可)。
回答:
(1)cube.sln
原输出:修改数据:
glTranslatef (0.0, 0.0, -5.0);
glScalef (1.0, 2.0, 1.0);
改成:
glTranslatef (1.0, 0.0, -5.0);
glScalef (1.0, 1.0, 2.0);
结果输出:原因:
glTranslatef (0.0, 0.0, -5.0); 将 X 轴平移了 1,glScalef (1.0, 2.0, 1.0); 将 y 轴缩放为原来的 1/2 ,z 轴伸长为原来的 2 倍,得到结果。
(2)aim.sln
原输出:
修改数据:
glVertex3f( 0.0f, 1.0f, 0.0f); // Top | |
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left | |
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right | |
… | |
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left | |
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right | |
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right | |
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left |
改成:
glVertex3f( 1.2f, 1.0f, 0.0f); // Top | |
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left | |
glVertex3f( 1.0f,-1.0f, 5.0f); // Bottom Right | |
… | |
glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left | |
glVertex3f( 1.0f, 1.0f, 2.0f); // Top Right | |
glVertex3f( 1.2f,-1.0f, -1.0f); // Bottom Right | |
glVertex3f(-0.5f,-1.2f, 1.0f); // Bottom Left |
结果输出:
原因:glVertex3f()
函数是绘制三个顶点坐标,原函数分别绘制三个顶点和四个顶点,绘制出标准的三角形和矩形,在原来的顶点坐标进行修改,实现不同形状三角形和四边形的绘制。