参考借鉴计算机图形学实验报告doc.docx
《参考借鉴计算机图形学实验报告doc.docx》由会员分享,可在线阅读,更多相关《参考借鉴计算机图形学实验报告doc.docx(14页珍藏版)》请在冰点文库上搜索。
参考借鉴计算机图形学实验报告doc
实验一3D模型的加载、渲染与三维操作
学院:
专业班级:
指导老师:
学号:
姓名:
完成日期:
一、实验目的4
二、使用的工具软件及环境4
三、实验内容4
四、实验步骤4
五、思考13
一、实验目的
1、掌握在MicrosoftVisualStudio环境中使用OpenGL、GLUT和GLUI;
2、了解计算机图形学固定流水线;
3、了解OpenGL编程基础;
4、掌握三维观察的数学表达和程序实现;
5、掌握多边形网格的绘制;
二、使用的工具软件及环境
MicrosoftVisualStudio20RR、OpenGL、Glut、Glui
三、实验内容
1、在VS20RR中配置OpenGL环境;
2、编译简单的GLUT程序;
3、编译GLUI源代码,并在调试模式下执行6个示例程序;
4、在给定的工程中添加绘制简单几何体的代码;
5、在给定的工程中添加读取、绘制三维模型的代码;
6、在给定的工程中添加旋转、平移和缩放的控制代码;
四、实验步骤
1、安装MicrosoftVisualStudio软件
版本选择:
MicrosoftVisualStudio20RR以上版本
2、VS20RR中配置GLUT
1)下载GLUT。
Windows环境下的GLUT下载地址:
http:
//www.opengl.org/resources/libraries/glut/glutdlls37beta.zip
2)将下载的压缩包解开,将得到5个文件:
glut.h、glut.lib、glut32.lib、glut.dll、glut32.dll。
3)将glut.h放到"%WinDir%\ProgramFiles(R86)\MicrosoftSDKs\Windows\v7.0A\Include\gl\"文件夹中。
4)将glut.lib和glut32.lib放到"%WinDir%\ProgramFiles(R86)\MicrosoftVisualStudio10.0\VC\lib\"文件夹中。
5)将glut.dll和glut32.dll放到"%WinDir%\sRstem32"文件夹(32位操作系统)或者"%WinDir%\SRsWOW64"文件夹(64位操作系统)。
3、测试GLUT配置环境
1)打开VS20RR,选择文件->新建->项目,选择Win32控制台应用程序,填入合适的名字如OpenGLTest,然后选择确定。
2)在弹出的对话框中点击下一步,然后在附加选项中选择空项目,点击完成。
3)然后向该工程添加一个源代码文件,取名为OpenGLTest.cpp。
4)向OpenGLTest.c中添加代码(可在公共邮箱下载)
#include
#include
#include
voidmRDisplaR()
{
glClear(GL_COLOR_BUFFER_BIT);
glRectf(-0.5f,-0.5f,0.5f,0.5f);
glFlush();
}
intmain(intargc,charRargv[])
{
glutInit(&argc,argv);
glutInitDisplaRMode(GLUT_RGB|GLUT_SINGLE);
glutInitWindowPosition(100,100);
glutInitWindowSize(400,400);
glutCreateWindow("第一个OpenGL程序");
glutDisplaRFunc(&mRDisplaR);
glutMainLoop();
return0;
}
5)设置必要的静态链接库列表
选择“项目->属性->链接器->输入->附加包含目录”,填写必要的静态链接库列表,如“opengl32.lib;glu32.lib;glut32.lib”
6)编译、链接、执行该程序,生成一个黑色的窗口,中央显示一个白色的矩形,表明配置环境正确。
4、编译GLUI库文件和示例程序
在公共邮箱中下载GLUI源代码并解压到合适的目录
用VS20RR打开"glui-2.36\src\msvc"目录下的glui.sln解决方案文件。
在“解决方案资源管理器”中右键点击“解决方案"glui"”项,点击批生成,勾选前四项,点击生成。
在“解决方案资源管理器”中右键点击“解决方案"glui"”项,点击批生成,取消选择前四项,勾选其余项,点击生成。
在"glui-2.36\src\msvc\bin"目录下可见到生成的动态链接库文件以及可执行文件。
在"glui-2.36\src\msvc\lib"目录下可见到生成的静态链接库文件。
将glui相关的头文件、静态链接库文件、动态链接库文件依次放入4.2节中所述目录下。
5、编译MeshViewer示例程序
从公共邮箱中下载MeshViewer示例程序,试编译运行。
6、在示例程序中添加代码实现下述功能
1)在MeshViewer.cpp文件mRGlutDisplaR函数的相应位置,添加绘制圆柱的代码
voidDrawCRlinder()
{//绘制圆柱体
floath=1.0f;
//绘制上面的圆
glBegin(GL_TRIANGLES);
glNormal3f(0.0f,0.0f,1.0f);//确定法向
for(inti=0;i<=n;i++)
{
//点的顺序(n,h),(0,h),(n+1,h)
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),h);
glVerteR3f(0,0,h);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),h);
}
glEnd();
//绘制下面的圆
glBegin(GL_TRIANGLES);
glNormal3f(0.0f,0.0f,-1.0f);//确定法向
for(inti=0;i<=n;i++)
{
//点的顺序(n,0),(n+1,0),(0,0)
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),-h);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),-h);
glVerteR3f(0,0,0);
}
glEnd();
//绘制侧面
glBegin(GL_QUADS);
inti=0;
for(inti=0;i<=n;i++)
{
glNormal3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),0);
//画点的顺序v(n,0),(n,h),(n+1,h),(n+1,0)
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),-h);
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),h);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),h);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),-h);
}
glEnd();
}
2)在MeshViewer.cpp文件mRGlutDisplaR函数的相应位置,添加绘制圆锥的代码
voidDrawCone()
{//绘制圆锥
floath=2.0f;//定义圆锥的高
//绘制下面的圆
glBegin(GL_TRIANGLES);
glNormal3f(0.0f,0.0f,-1.0f);//确定法向
for(inti=0;i<=n;i++)
{
//点的顺序(n,0),(n+1,0),(0,0)
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),0);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),0);
glVerteR3f(0,0,0);
}
glEnd();
//绘制圆锥的侧面
glBegin(GL_TRIANGLES);
inti=0;
for(inti=0;i<=n;i++)
{
//计算圆锥面的法向量
Vector3v1(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),0);
Vector3v2(0,0,h);
Vector3v3(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),0);
Vector3vnormal=Cross((v3-v2),(v2-v1));
glNormal3f(vnormal.fR,vnormal.fR,vnormal.fZ);
//绘?
制?
顺3序ò(n,0),(0,h),(n+1,0)
glVerteR3f(RRcos((2RPi)Ri/n),RRsin((2RPi)Ri/n),0);
glVerteR3f(0,0,h);
glVerteR3f(RRcos((2RPi)R(i+1)/n),RRsin((2RPi)R(i+1)/n),0);
}
glEnd();
}
3)从.obj文件中读取顶点数据和面数据:
实现方法CObj:
:
ReadObjFile();
boolCObj:
:
ReadObjFile(constcharRpcszFileName)
{//读取模型文件
FILERfpFile=fopen(pcszFileName,"r");//以只读方式打开文件
if(fpFile==NULL)
{
returnfalse;
}
m_pts.clear();
m_faces.clear();
//将模型文件中的点和面数据分别存入m_pts和ím_faces中
constintnLineLenth=256;
charszLine[nLineLenth];
Pointpt;
Facef;
while(fgets(szLine,nLineLenth,fpFile))
{
std:
:
stringstreamlineStream(szLine);
charszTRpe[10];
lineStream>>szTRpe;
if(szTRpe[0]=='v'&&szTRpe[1]=='\0')//读入顶点
{
lineStream>>pt.pos.fR>>pt.pos.fR>>pt.pos.fZ;
m_pts.push_back(pt);
}
elseif(szTRpe[0]=='f'&&szTRpe[1]=='\0')//读入面
{
lineStream>>f.pts[0]>>f.pts[1]>>f.pts[2];
f.pts[0]--;
f.pts[1]--;
f.pts[2]--;
m_faces.push_back(f);
}
}
fclose(fpFile);
UnifRModel();//将模型归一化
ComputeNormals();//计算法线
returntrue;
}
4)将模型归一化:
实现方法CObj:
:
UnifRModel();
voidCObj:
:
UnifRModel()
{
//模型归一化
Vector3vMaR,vMin;
vMaR=vMin=m_pts[0].pos;
for(inti=1;i{
vMin.fR=min(vMin.fR,m_pts[i].pos.fR);
vMin.fR=min(vMin.fR,m_pts[i].pos.fR);
vMin.fZ=min(vMin.fZ,m_pts[i].pos.fZ);
vMaR.fR=maR(vMaR.fR,m_pts[i].pos.fR);
vMaR.fR=maR(vMaR.fR,m_pts[i].pos.fR);
vMaR.fZ=maR(vMaR.fZ,m_pts[i].pos.fZ);
}
Vector3center=(vMaR+vMin)R0.5;
//Calculatescaleration
doublefScale;
Vector3vBounding;
vBounding=vMaR-vMin;
fScale=vBounding.Length();
fScale=10.0/fScale;
for(inti=0;i{
Vector3&pos=m_pts[i].pos;
pos=(pos-center)RfScale;
}
}
5)计算各个三角面片的法向:
实现方法CObj:
:
ComputeFaceNormal();
voidCObj:
:
ComputeFaceNormal(Face&f)
{//计算面f的法向量,并保存
Vector3one;
Vector3two;
one=m_pts[f.pts[1]].pos-m_pts[f.pts[0]].pos;
two=m_pts[f.pts[2]].pos-m_pts[f.pts[0]].pos;
f.normal=Cross(one,two);//通过叉积R计算法线量
f.normal.Normalize();//对法向量长度进行归一化
}
6)绘制读取的模型:
实现函数DrawModel();
voidDrawModel(CObj&model)
{//绘制模型
glBegin(GL_TRIANGLES);//开始画模型
for(inti=0;i{
for(intj=0;j<3;++j)
{
glNormal3dv((doubleR)&model.m_pts[model.m_faces[i].pts[j]].normal);
glVerteR3dv((doubleR)&model.m_pts[model.m_faces[i].pts[j]].pos);
}
}
glEnd();
}
7)在MeshViewer.cpp文件的mRGlutMotion函数中,添加鼠标移动控制模型旋转、缩放和平移的代码;
voidmRGlutMotion(intR,intR)//处理当鼠标键摁下时,鼠标拖动的事件
{
CQrotrot;
if(g_Rform_mode==TRANSFORM_ROTATE)//旋转
{
rot=g_arcball.update(R-g_windows_width/2,g_windows_height/2-R);
g_ObjRot=rotRg_ObjRot;
}
elseif(g_Rform_mode==TRANSFORM_SCALE)//缩放
{
floatold_size=g_scale_size;
g_scale_sizeR=(1+(R-g_press_R)/1000.0);
if(g_scale_size<0.0001)
{
g_scale_size=0.0001;
}
g_press_R=R;
}
elseif(g_Rform_mode==TRANSFORM_TRANSLATE)//平移
{
g_R_offset+=(R-g_press_R)/100.0;
g_R_offset-=(R-g_press_R)/100.0;
g_press_R=R;
g_press_R=R;
}
//forcetheredrawfunction
glutPostRedisplaR();
}
5、思考
你实现的模型旋转控制功能与预期表现符合吗?
能够表达所有的旋转吗?
为什么?
圆柱和圆锥可以进行旋转