当前位置:文档之家› 实验八 3D编程基础

实验八 3D编程基础

实验八 3D编程基础
实验八 3D编程基础

# include

实验八 3D编程基础

一、实验目的

1.熟悉3D基本编程

2.熟悉视点观察函数的设置和使用

3.熟悉投影变换函数的设置和使用

4.熟悉基本3D图元的绘制

二、实验要求:

按照实验内容做实验,保留所作步骤效果截图或演示程序,当场检查,现场计分

三、实验环境

硬件要求:

PC机,主流配置,最好为独立显卡,显存512M以上。

软件环境:

操作系统:Windows XP。

语言开发工具:Microsoft Visual studio 2008,Visual C++。

程序框架:

win32应用程序

四、实验内容

要求:实验所有步骤所生成的效果截图拷贝到实验报告文档里备查,并附上相应的代码。 WORD文档命名方式:学号姓名-实验序号-实验名称。

内容:

1)读懂一下3D物体程序,并结合讲义理解一些新的绘制函数和投影变换函数的含义。:3D Cube2.cpp 为正交投影下的旋转3D立方体,按下鼠标可实现不同方向的旋转。分析3D编程代码与程序结构。

图8-1 旋转立方体效果图

2)构思绘制Teapot_Torus.cpp 茶壶和圆环造型

在紧挨着茶壶下方添加一个平行的圆环,茶壶和圆环不停绕中心轴旋转,观看显示效果。

图8-2 旋转茶壶和圆环效果图

以下操作需要记录不同效果图和修改的相应参数:

1.让静止的立方体绕Z轴不停旋转

2.修改不同视点,目标点不变,观看显示效果

3. 修改目标点,视点不动,观看显示效果

4. 视点与目标点同时修改,观看显示效果

5. 视点与目标点不变,修改观察体大小,观看显示效果

6. 将正交投影观察体改为透视投影观察体,并设置其大小,观察显示效果

7. 将立方体替换为茶壶,观看显示效果

8. 将立方体替换为圆环,观看显示效果

3)编写或改写程序,构造自己的3D物体场景造型

五、函数参考

1.视点设置函数

void gluLookAt(GLdouble eyex, GLdouble eyey,GLdouble eyez,GLdouble atx,GLdouble aty,GLdouble atz,GLdouble upx,GLdouble upy,GLdouble upz)

给出矩阵作用于当前矩阵,定义相机位置和方向

视点:eyex, eyey, eyez

目标点:atx,aty,atz

相机向上方向:upx,upy,upz

如果不引用该函数,则eyex=0,eyey=0,eyez=0,atx=0,aty=0,atz=-1,Upx=0,upy=1,upz=0此函数放在display函数中调用

参考坐标系:世界坐标系

2.正交投影变换设置函数

. void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far),建立正交投影矩阵,定义一个正平行观察体。距离从相机位置处测量。right>left,top>bottom,far>near

OpenGL中不提供对观察平面的选择功能。近裁减平面永远和观察平面重合。

如果OpenGL不提供投影函数,默认调用为:glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0)

3.透视投影变换设置函数

void gluPerspective(GLdouble fov,GLdouble aspect, GLdouble near,GLdouble far),定义一个透视矩阵作用于当前矩阵

fov-近裁剪平面与远裁剪平面的连线与视点的角度,也称视场角(field-of-view angle)

aspect-投影平面的宽与高之比

near,far-近裁剪平面和远裁剪平面离相机(视点)的距离

4.三维基本图形绘制函数

1)立方体绘制函数

void glutWireCube(GLdouble size) //线框模式

void glutSolidCube(GLdouble size) //实体模式

功能:绘制一个边长为size的线框的或实心立方体,立方体的中心位于原点

2)小球绘制函数

2.1).void glutWireSphere(GLdouble Radius, Glint slices,Glint stacks) //线框模式

void glutSolidSphere(GLdouble Radius, Glint slices,Glint stacks); //实体模式

功能:绘制一个半径为Radius的线框的的或实心小球,小球的中心点位于原点,slices: 为小球的经线数目,stacks为小球的纬线数目

2.2) gluSphere(GLUquadricObj *obj,GLdouble radius,GLint slices,GLint stacks);

用法:

GLUquadricObj *sphere; //定义二次曲面对象

sphere=gluNewQuadric(); //生成二次去面对像

gluSphere(sphere,8,50,50); //半径8,球心在原点,经线和纬

线数目为50的小球

3)茶壶绘制函数

void glutWireTeapot(GLdouble size); //线框模式

void glutSolidTeapot(GLdouble size); //实体模式

功能:绘制一个半径为size的线框的或实心茶壶,茶壶的中心位于原点

参数说明:参数size为茶壶的近似半径,以size为半径的球体可完全包容这个茶壶。

4)圆环绘制函数

.void glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,Glint slices,Glint stacks);

//线框模式

void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,Glint slices,Glint stacks); //实体模式

功能:绘制一个半径为size的线框的的或实心圆环体,圆环体的中心位于原点,圆环的内径和外径由参数innerRadius, outerRadius指定

参数说明:

innerRadius: 圆环体的内径

outerRadius: 圆环体的外径

slices: 圆环体的经线数目

stacks: 圆环体的纬线数目

5)正八面体绘制函数

?void glutWireOctahedron(void); //线框模式

?void glutSolidOctahedron(void); //实体模式

?功能:绘制一个线框的或实心的正八面体,其中心位于原点,半径为1。

6)正十二面体绘制函数

?void glutWireDodehedron(void); //线框模式

?void glutSolidDodehedron(void); //实体模式

?功能:绘制一个线框的或实心的正十二面体,其中心位于原点,半径为3的平方根。

7)正二十面体绘制函数

?void glutWireIcosahedron(void); //线框模式

?void glutSolidIcosahedron(void); //实体模式

?功能:绘制一个线框的或实心的正二十面体,其中心位于原点,半径为1。

8)正四面体绘制函数

?void glutWireTetrahedron(void); //线框模式

?void glutSolidTetrahedron(void); //实体模式

?功能:绘制一个线框的或实心的正四面体,其中心位于原点,半径为3的平方根

9)裁剪平面函数

?void glClipPlane(GLenum plane, const GLdouble *equation)

?定义一个附加的裁减平面

?plane: 指出要定义的附加裁减平面名称,取值为GL_CLIP_PLANEi, i=0~5

?equation: 之向由平面方程Ax+By+Cz+D=0的4个系数A、B、C、D构成的数组,

以定义一个裁减平面

?调用此函数,先启用:glEnable(GL_CLIP_PLANEi);

?需要时用glDisable(GL_CLIP_PLANEi)关闭某裁减平面

5、图形变换函数参考:

1、glTranslatef(x,y,z)函数,x,y,z分别代表x,y,z方向的平移量,对于

2D图形,z=0。

2、glRotatef(Q,x,y,z)函数,Q为逆时针方向旋转的角度度数(0~360),

(x,y,z)为旋转轴的方向矢量,(x,y,z)=(0,0,1)时代表沿Z

轴方向旋转;(x,y,z)=(1,0,0)代表沿x轴方向旋转;(x,y,z)=

(0,1,0)代表沿y轴方向旋转。

3、glScalef(x,y,z)函数,x,y,z分别表示x,y,z方向的比例因子。对于2D

图形,z=0。比例因子取-1时,产生对称变换。

6、图形变换函数代码示例

1)某图形沿水平方向垂直方向分别平移Tx,Ty段距离

清屏

glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型变换模式,表示在世界坐标系下glLoadIdentity(); //将当前矩阵设置为单位矩阵

glTranslatef(Tx,Ty,0);

DrawSomeShape();

刷新

2)某图形绕任意点(cx,cy)旋转ALPHA

清屏

glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型变换模式,表示在世界坐标系下glLoadIdentity(); //将当前矩阵设置为单位矩阵

glTranslatef(cx,cy,0); //平移回去

glRotatef(ALPHA,0,0,1); //绕原点旋转ALPHA角度

glTranslatef(-cx,-cy,0); //平移回原点

DrawSomeShape();

刷新

3)某图形绕任意点(cx,cy)缩放Sx,Sy比例因子

清屏

glMatrixMode(GL_MODELVIEW); //设置矩阵模式为模型变换模式,表示在世界坐标系下glLoadIdentity(); //将当前矩阵设置为单位矩阵

glTranslatef(cx,cy,0); //平移回去

glScalef(Sx,Sy,1); //绕原点水平缩放系数Sx,垂直缩放系数Sy

glTranslatef(-cx,-cy,0); //平移回原点

DrawSomeShape();

刷新

7、void glPushMatrix(void)函数

功能:把当前操作矩阵压入矩阵堆栈,记住当前所在的位置。

复制活动栈顶的当前矩阵并将其存入第二个栈位置

8、void glPopMatrix(void)函数

功能:当前操作矩阵出栈,它下面的矩阵作为当前矩阵,返回到以前所在的位置。

破坏栈顶矩阵,栈的第二个矩阵成为当前矩阵。如果要弹出栈顶,栈内至少要有2个矩阵,否则就会出错。

9、void glutIdleFunc((*f) (void)) //注册闲置响应函数

用于后台处理,当其他的事情处于挂起时,就可以执行函数f。

如果将函数的参数设为NULL或0,将取消该函数的执行。

该函数调用放在主程序main()中,通常利用它可实现简单动画。

10、void myidle() //闲置响应回调函数

{

//当时间空闲时系统要做的事情

}

六、思考题:

1.修改目标点与视点,显示结果有何不同?

2.视点与目标点不变,修改观察体大小,显示结果有什么规律?

3.正交投影与透视投影有何不同?

七、课后加分题

1.如何编写程序从不同角度观看物体模型?如按A键,视点越来越远?按S键视

点越来越近?如何切换俯视?侧视?或正视?

要求代码添加注释,编写的工程文件打包:学号姓名-3D基础加分题.rar 上传到课程作业加分题中

八、附属程序:

1.3D_Cube.cpp 静止立方体程序

1)win32程序框架

#include"stdafx.h"

#include

void reshape(int w,int h);

void init();

void display();

int APIENTRY _tWinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPTSTR lpCmdLine,

int nCmdShow)

{

UNREFERENCED_PARAMETER(hPrevInstance);

UNREFERENCED_PARAMETER(lpCmdLine);

char *argv[] = {"hello ", " "};

int argc = 2; // must/should match the number of strings in argv

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

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //设置显示模式;(缓冲,颜色类型)

glutInitWindowSize(500, 500);

glutInitWindowPosition(1024 / 2 - 250, 768 / 2 - 250);

glutCreateWindow("3D Basic"); //创建窗口,标题为“…”;

glutReshapeFunc(reshape);

init();

glutDisplayFunc(display); //用于绘制当前窗口;

glutMainLoop(); //表示开始运行程序,用于程序的结尾;

return 0;

}

void reshape(int w,int h)

{ glViewport(0,0,w,h);

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

glOrtho(-1,1,-1,1,0.1,2.5); //定义三维观察体

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void init()

{ glClearColor(0.0,0.0,0.0,0.0);

glLineWidth(3);

//glColor3f(1.0,1.0,1.0);

}

void display()

{ glClear(GL_COLOR_BUFFER_BIT); //清屏

glMatrixMode(GL_MODELVIEW); //矩阵模式设置

glLoadIdentity(); //清空矩阵堆栈

gluLookAt(1.4,1.0,0.8,0.0,0.0,0.0,0.0,1.0,0.0); //设置视点

// gluLookAt(1,1.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0);

glColor3f(1,0,0);

// glutWireCube(0.5)

glutSolidCube(0.5); //绘制立方体,立方体中心在坐标原点

glColor3f(0,0,1);

glutWireCube(0.5); //绘制线框立方体,体现边框效果

glutSwapBuffers();

}

2.3D Cube2.exe 旋转立方体参考程序

#include"math.h"

#include

int flag=0;

//GLfloat

vertices[][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}};

GLfloat

vertices[][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}};

GLfloat colors[][3]={{1.0,0.0,0.0},{0.0,1.0,1.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},{0.0,1.0,1.0},{1.0,1.0,1.0}};

void init()

{

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

glEnable(GL_DEPTH_TEST);

glLineWidth(3);

}

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

{

/* draw a polygon via list of vertices */

if (flag==0)

glBegin(GL_POLYGON);

glColor3fv(colors[a]);

glVertex3fv(vertices[a]);

glColor3fv(colors[b]);

glVertex3fv(vertices[b]);

glColor3fv(colors[c]);

glVertex3fv(vertices[c]);

glColor3fv(colors[d]);

glVertex3fv(vertices[d]);

glEnd();

}

else

{

glColor3f(0,0,0);

glBegin(GL_POLYGON);

glVertex3fv(vertices[a]);

glVertex3fv(vertices[b]);

glVertex3fv(vertices[c]);

glVertex3fv(vertices[d]);

glEnd();

}

}

void colorcube(void)

{

/* 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);

}

static GLfloat theta[]={0.0,0.0,0.0}; static GLint axis=2;

void display()

{

// glClear(GL_COLOR_BUFFER_BIT);

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(3,3,3,0,0,0,0,1,0);

glRotatef(theta[0],1.0,0.0,0.0);

glRotatef(theta[1],0.0,1.0,0.0);

glRotatef(theta[2],0.0,0.0,1.0);

glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

flag=0;

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

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

flag=1;

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

glutSwapBuffers();

}

void spinCube()

{

theta[axis]+=0.0;

if (theta[axis]>360.0) theta[axis]-=360.0;

glutPostRedisplay();

}

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

{

if (btn==GLUT_LEFT_BUTTON && state==GLUT_DOWN) axis=0; if (btn==GLUT_MIDDLE_BUTTON && state==GLUT_DOWN) axis=1;

if (btn==GLUT_RIGHT_BUTTON && state==GLUT_DOWN) axis=2; }

void reshape(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,1.0,20.0);

else

glOrtho(-2.0*(GLfloat)w/(GLfloat)h,2.0*(GLfloat)w/(GLfloat)h,-2.0,2.0,1.0,20.0);

//gluPerspective(120,w/h,1,60); //定义透视投影投影观察体

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

}

void main(int argc, char** argv)

{

glutInit(&argc,argv);

// glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DETH);

glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH);

glutInitWindowSize(800,800);

glutCreateWindow("colorcube");

init();

glutReshapeFunc(reshape);

glutDisplayFunc(display);

glutIdleFunc(spinCube);

glutMouseFunc(mouse);

glutMainLoop();

}

相关主题
相关文档 最新文档