2024年4月1日发(作者:)
实验5 OpenGL模型视图变换
一、实验目的:
理解掌握OpenGL程序的模型视图变换。
二、实验内容:
(1)阅读实验原理,运行示范实验代码,理解掌握OpenGL程序的模型视图变换;
(2)根据示范代码,尝试完成实验作业;
三、实验原理:
在代码中,视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投
影变换和视口变换。
y()程序中绘图函数潜在的重复性强调了:在指定的视图变换之前,应该使用
glLoadIdentity()函数把当前矩阵设置为单位矩阵。
2.在载入单位矩阵之后,使用gluLookAt()函数指定视图变换。如果程序没有调用
gluLookAt(),那么照相机会设定为一个默认的位置和方向。在默认的情况下,照相机位于
原点,指向Z轴负方向,朝上向量为(0,1,0)。
3.一般而言,display()函数包括:视图变换 + 模型变换 + 绘制图形的函数(如
glutWireCube())。display()会在窗口被移动或者原来先遮住这个窗口的东西被一开时,被
重复调用,并经过适当变换,保证绘制的图形是按照希望的方式进行绘制。
4.在调用glFrustum()设置投影变换之前,在reshape()函数中有一些准备工作:视口
变换 + 投影变换 + 模型视图变换。由于投影变换,视口变换共同决定了场景是如何映射
到计算机的屏幕上的,而且它们都与屏幕的宽度,高度密切相关,因此应该放在reshape()
中。reshape()会在窗口初次创建,移动或改变时被调用。
OpenGL中矩阵坐标之间的关系:物理坐标*模型视图矩阵*投影矩阵*透视除法*规范
化设备坐标——〉窗口坐标
(1)视图变换函数gluLookAt(0.0,0.0,5.0,0.0,0.0,0.0,0.0,1.0,0.0,)设
置照相机的位置。把照相机放在(0,0,5),镜头瞄准(0,0,0),朝上向量定为(0,
1,0)朝上向量为照相机指定了一个唯一的方向。如果没有调用gluLookAt,照相机就设
定一个默认的位置和方向,在默认情况下,照相机位于原点,指向Z轴的负方向,朝上向
量为(0,1,0)glLoadIdentity()函数把当前矩阵设置为单位矩阵。
(2)使用模型变换的目的是设置模型的位置和方向
(3)投影变换,指定投影变换类似于为照相机选择镜头,可以认为这种变换的目的是
确定视野,并因此确定哪些物体位于视野之内以及他们能够被看到的程度。
除了考虑视野之外,投影变换确定物体如何投影到屏幕上,OpenGL提供了两种基本
类型的投影,1、透视投影:远大近小;2、正投影:不影响相对大小,一般用于建筑和CAD
应用程序中
(4)视口变换视口变换指定一个图象在屏幕上所占的区域
(5)绘制场景
四、实验代码:
#include
#include
static int year = 0, day = 0;
void init(void)
{
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel (GL_FLAT);
}
void display(void)
{
glClear (GL_COLOR_BUFFER_BIT);
glColor3f (1.0, 1.0, 1.0);
glPushMatrix();
glutWireSphere(1.0, 20, 16); /* draw sun */
glRotatef ((GLfloat) year, 0.0, 1.0, 0.0);
glTranslatef (2.0, 0.0, 0.0);
glRotatef ((GLfloat) day, 0.0, 1.0, 0.0);
glutWireSphere(0.2, 10, 8); /* draw smaller planet */
glPopMatrix();
glutSwapBuffers();
}
void reshape (int w, int h)
{
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void keyboard (unsigned char key, int x, int y)
{
switch (key) {
case 'd':
day = (day + 10) % 360;
glutPostRedisplay();
break;
case 'D':
day = (day - 10) % 360;
glutPostRedisplay();
break;
case 'y':
year = (year + 5) % 360;
glutPostRedisplay();
break;
case 'Y':
year = (year - 5) % 360;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize (500, 500);
glutInitWindowPosition (100, 100);
glutCreateWindow (argv[0]);
init ();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
五、结果截屏:
实验六:Bezier曲线生成
一、实验目的:
了解曲线的生成原理,掌握几种常见的曲线生成算法,利用VC+OpenGL实现Bezier
曲线生成算法。
二、实验内容:
(1) 结合示范代码了解曲线生成原理与算法实现,尤其是Bezier曲线;
(2) 调试、编译、修改示范程序。
三、实验原理:
Bezier曲线是通过一组多边形折线的顶点来定义的。如果折线的顶点固定不变,则由
其定义的Bezier曲线是唯一的。在折线的各顶点中,只有第一点和最后一点在曲线上且作
为曲线的起始处和终止处,其他的点用于控制曲线的形状及阶次。曲线的形状趋向于多边
形折线的形状,要修改曲线,只要修改折线的各顶点就可以了。因此,多边形折线又称Bezier
曲线的控制多边形,其顶点称为控制点。
三次Bezier曲线,有四个控制点,其数学表示如下:
四、实验代码:
#include
#include
#include
#include
using namespace std;
struct Point {
int x, y;
};
Point pt[4], bz[11];
vector
bool bDraw;
int nInput;
void CalcBZPoints()
{
float a0,a1,a2,a3,b0,b1,b2,b3;
a0=pt[0].x;
a1=-3*pt[0].x+3*pt[1].x;
a2=3*pt[0].x-6*pt[1].x+3*pt[2].x;
a3=-pt[0].x+3*pt[1].x-3*pt[2].x+pt[3].x;
b0=pt[0].y;
b1=-3*pt[0].y+3*pt[1].y;
b2=3*pt[0].y-6*pt[1].y+3*pt[2].y;
b3=-pt[0].y+3*pt[1].y-3*pt[2].y+pt[3].y;
float t = 0;
float dt = 0.01;
for(int i = 0; t<1.1; t+=0.1, i++)
{
bz[i].x = a0+a1*t+a2*t*t+a3*t*t*t;
bz[i].y = b0+b1*t+b2*t*t+b3*t*t*t;
}
}
void ControlPoint(vector
{
glPointSize(2);
for(int i=0; i<(); i++)
{
glBegin (GL_POINTS);
glColor3f (1.0f, 0.0f, 0.0f); glVertex2i (vpt[i].x,vpt[i].y);
glEnd ();
}
}
void PolylineGL(Point *pt, int num)
{
glBegin (GL_LINE_STRIP);
for(int i=0;i { glColor3f (1.0f, 1.0f, 1.0f); glVertex2i (pt[i].x,pt[i].y); } glEnd (); } void myDisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f (1.0f, 1.0f, 1.0f); if (() > 0) { ControlPoint(vpt); } if(bDraw) { PolylineGL(pt, 4); CalcBZPoints(); PolylineGL(bz, 11); } glFlush(); } void Init() { glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_SMOOTH); printf("Please Click left button of mouse to input control point of Bezier Curve!n"); } void Reshape(int w, int h) { glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, (GLdouble) w, 0.0, (GLdouble) h); } void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { if (nInput == 0) { pt[0].x = x; pt[0].y = 480 - y; nInput = 1; (); _back(pt[0]); bDraw = false; glutPostRedisplay();// } else if (nInput == 1) { pt[1].x = x; pt[1].y = 480 - y; _back(pt[1]); nInput = 2; glutPostRedisplay();// } else if (nInput == 2) { pt[2].x = x; pt[2].y = 480 - y; _back(pt[2]); nInput = 3; glutPostRedisplay();// } else if (nInput == 3) { pt[3].x = x; pt[3].y = 480 - y; bDraw = true; _back(pt[3]); nInput = 0; glutPostRedisplay();// } } break; default: break; } } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(640, 480); glutCreateWindow("Hello World!"); Init(); glutDisplayFunc(myDisplay); glutReshapeFunc(Reshape); glutMouseFunc(mouse); glutMainLoop(); return 0; } 五、结果截屏: 实验7 OpenGL光照 一.实验目的: 了解掌握OpenGL程序的光照与材质,能正确使用光源与材质函数设置所需的绘制效 果。 二.实验内容: (1)下载并运行Nate Robin教学程序包中的lightmaterial程序,试验不同的光照 与材质系数; (2)运行示范代码1,了解光照与材质函数使用。 三.实验原理: 为在场景中增加光照,需要执行以下步骤: (1) 设置一个或多个光源,设定它的有关属性; (2) 选择一种光照模型; (3) 设置物体的材料属性。 四、实验代码: #include #include // Initialize material property, light source, lighting model, and depth buffer. void init(void) { GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat mat_shininess[] = { 50.0 }; GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 }; GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 }; GLfloat Light_Model_Ambient[] = { 0.2 , 0.2 , 0.2 , 1.0 }; // glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_SMOOTH); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); glLightfv(GL_LIGHT0, GL_POSITION, light_position); glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light); glLightfv(GL_LIGHT0, GL_SPECULAR, white_light); glLightModelfv( GL_LIGHT_MODEL_AMBIENT , Light_Model_Ambient ); // glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); } void display(void) { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //glutSolidSphere (1.0, 20, 16); glutSolidTeapot(0.5); glFlush (); } void reshape (int w, int h) { glViewport (0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode (GL_PROJECTION); glLoadIdentity(); if (w <= h) glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w, 1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0); else glOrtho (-1.5*(GLfloat)w/(GLfloat)h, 1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize (500, 500); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; } 五、结果截屏: 实验8 OpenGL交互 一、实验目的: 理解掌握一个OpenGL程序的常见交互方法。 二、实验内容: (1) 运行示范实验代码1,掌握程序鼠标交互方法,尝试为其添加键盘与菜单控制, 实现同样功能; (2)运行示范实验代码2,掌握程序鼠标坐标获取与绘图方法,尝试为其添加绘制直 线功能; (3)结合上述两步,能否实现通过鼠标右键菜单切换实现一个简单的绘图程序,可以 绘制直线、三角形、正方形等常见图形? 三、实验原理: 要想在OpenGL中处理鼠标事件非常的方便,GLUT已经为我们的注册好了函数,只 要我们提供一个方法。使用函数glutMouseFunc,就可以帮我们注册我们的函数,这样当 发生鼠标事件时就会自动调用我们的方法。 函数的原型是: void glutMouseFunc(void(*func)(int button,int state,int x,int y)); 参数:func:处理鼠标click事件的函数的函数名。 从上面可以看到,处理鼠标单击事件的函数,一定有4个参数。第一个参数表明哪个 鼠标键被按下或松开,这个变量可以是下面的三个值中的一个: GLUT_LEFT_BUTTON GLUT_MIDDLE_BUTTON GLUT_RIGHT_BUTTON 第二个参数表明,函数被调用发生时,鼠标的状态,也就是是被按下,或松开,可能 取值如下: GLUT_DOWN GLUT_UP 当函数被调用时,state的值是GLUT_DOWN,那么程序可能会假定将会有个 GLUT_UP事件,甚至鼠标移动到窗口外面,也如此。然而,如果程序调用glutMouseFunc 传递NULL作为参数,那么GLUT将不会改变鼠标的状态。剩下的两个参数(x,y)提供了 鼠标当前的窗口坐标(以左上角为原点)。 四、实验代码: #include #include #include #define DEGREES_TO_RADIANS 3.14159/180.0 static GLfloat spin = 0.0; GLfloat x = 0.0; GLfloat y = 0.0; GLfloat size = 50.0; GLfloat angle = 2.0; GLsizei wh = 500, ww = 500; void square() { glBegin(GL_QUADS); glVertex2f(x,y); glVertex2f(-y,x); glVertex2f(-x,-y); glVertex2f(y,-x); glEnd(); } void spinDisplay(void) { spin = spin + 2.0; if (spin > 360.0) spin = spin - 360.0; x=125.0 * cos(DEGREES_TO_RADIANS*spin); y=125.0 * sin(DEGREES_TO_RADIANS*spin); glutPostRedisplay(); } void mydisplay() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); square(); glutSwapBuffers(); } void init() { glClearColor (0.0, 0.0, 0.0, 1.0); } void myreshape(GLint w, GLint h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(-w/2, w/2, -h/2, h/2, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); ww = w; wh = h; } void mymouse(GLint button, GLint state, GLint wx, GLint wy) { if(button ==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) exit(0); if(button ==GLUT_LEFT_BUTTON && state == GLUT_DOWN) glutIdleFunc(spinDisplay); if(button== GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) glutIdleFunc(NULL); } void main(int argc, char** argv) { glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize(500,500); glutInitWindowPosition(0,0); glutCreateWindow("double"); init(); glutDisplayFunc(mydisplay); glutReshapeFunc(myreshape); glutMouseFunc(mymouse); glutIdleFunc(spinDisplay); glutMainLoop(); } 五、结果示例:


发布评论