计算机图形学实验报告2.docx

上传人:b****6 文档编号:4725068 上传时间:2022-12-08 格式:DOCX 页数:27 大小:1.79MB
下载 相关 举报
计算机图形学实验报告2.docx_第1页
第1页 / 共27页
计算机图形学实验报告2.docx_第2页
第2页 / 共27页
计算机图形学实验报告2.docx_第3页
第3页 / 共27页
计算机图形学实验报告2.docx_第4页
第4页 / 共27页
计算机图形学实验报告2.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

计算机图形学实验报告2.docx

《计算机图形学实验报告2.docx》由会员分享,可在线阅读,更多相关《计算机图形学实验报告2.docx(27页珍藏版)》请在冰豆网上搜索。

计算机图形学实验报告2.docx

计算机图形学实验报告2

计算机图形学实验报告

实验二、三维网格模型光顺

一、实验目的与基本要求:

(1)掌握Obj文件的读入;

(2)利用给定的数据结构类,建立读入网格模型数据结构;

(3)利用OpenGL类库,对三维模型进行绘制;

(4)利用OpenGL类库,增加采用鼠标交互方式对三维模型进行旋转、放缩、平移等操作;

(5)实现Laplacian方法的三维模型光顺操作,并观察三维模型光顺过程;

二、实验设备(环境)及要求

1.操作系统:

WindowsXP或Windows7

2.编程环境:

MicrosoftVisualStudio2010,OpenGL库函数

3.界面框架:

Win32,MFC,QT选择其中一种

三、实验内容与步骤

实验分为以下几个步骤:

(1)掌握Obj文件的读入顶点和面的个数;

(2)建立数组存储点的坐标及面上的点数;

(3)存储顶点的邻接面数,并记录每个顶点周围的邻接点

(4)计算每个面的法向

利用OpenGL类库,增加采用鼠标交互方式对三维模型进行旋转、放缩、平移等操作;

(5)利用面法向及顶点坐标进行绘制几何体

(6)实现鼠标对物体旋转、平移、缩放的算法

(7)实现Laplacian方法的三维模型光顺操作,并观察三维模型光顺过程;

4、实现过程说明及成果展示:

(1)掌握Obj文件的读入顶点和面的个数;

由于obj文件的存储形式是

vx1x2x3;

fv1v2v3;

这种形式,所以在记录点和面的数量时,只需按行读取,然后再判断首字母是v/f即可

实现代码如下:

(2)建立数组存储点的坐标及面上的点数;

数组的大小由点数和面数决定,点数组和面数组均由0开始记录,故后面再用面对应点的时候,由于面上点是从1开始记录,故需要减1然后使用,代码如下:

(3)存储顶点的邻接面数,并记录每个顶点周围的邻接点

记录点邻接面的是新建一个数组,在读面的时候,将该面的序号存入对应点的数组中,然后再在每个面上取一点,记录到点的邻接点数组中,在每个面上取得的点为向外右手方向的下一个点,实现代码如下:

(4)计算每个面的法向

计算面的法向方式为面上右手方向上的两向量的叉乘得到,即

所用代码为:

(8)利用面法向及顶点坐标进行绘制几何体

用法向绘制的方式是

先用glNormal3fv(v)指出面的法向;再用glVertex3f传入面上点的坐标;由于我将glNormal3fv(v)中写在算法向所以我直接对此直接调用即可,代码如下:

(9)实现鼠标对物体旋转、平移、缩放的算法

平移:

利用Transform函数和键盘事件来改变参数,w,s,a,d分别控制绘制的kitty猫的上下左右的移动:

实现代码如下:

旋转:

利用gllookat();函数设定了观察角度,并用鼠标事件改变参数,用实现观察视角的变化实现物体的旋转,代码如下:

缩放:

运用glScalef方法和键盘事件改变参数,实现物体的放大和缩小,代码如下:

(10)实现Laplacian方法的三维模型光顺操作,并观察三维模型光顺过程;

Laplacian方法的原理是利用目标点与其所有邻接点平均后的点的差向量,对目标点的坐标进行变换的过程,具体方法是:

①建立每个点的邻接顶点数组,存储每个点的邻接点

②对每个顶点的邻接点进行求平均,即将邻接点的坐标求和后除以邻接点个数,从而得到邻接平均点

③得到优化向量

优化向量=邻接平均点-目标点

④设定优化度参数λ,得到优化后的新坐标

新坐标=目标点+λ*优化向量

在程序中,对于第num个顶点,我设定的变量为

目标点vArr

邻接平均点v0

优化向量l

新坐标数组vNewArr

具体代码如下:

 

5、结果展示及说明

计算面法向后直接绘制(未光顺):

光顺进行一次后

光顺多次后

利用点绘制结果为

旋转后

缩放后

平移后

6、心得体会

(1)计算面法向时法向量的方向没有运用右手方向,导致有的面法向向里,从而出现雪花

(2)在运用Laplacian算法进行求邻接平均点时未初始化邻接平均点数组,导致平均点的累加

从而出现越光顺越粗糙的现象

(3)在obj文件中面对应顶点数和顶点数组的标号相差1.在运用的时候需减1,面从1开始记顶点,顶点数组从0开始记顶点

7、实验代码

#defineGLUT_DISABLE_ATEXIT_HACK

#include

#include

#include

#include

#include

#include

#include

#include

#include

usingnamespacestd;

 

intv_num=0;//记录点的数量

intf_num=0;//记录面的数量

intvn_num=0;//记录法向量的数量

intvt_num=0;

GLfloat**vArr;//存放点的二维数组

GLfloat**vNewArr;//存放点的二维数组

int**fvArr;//存放面顶点的二维数组

GLfloat**fnArr;//存放面法向量的二维数组

int**ftArr;

int**vfArr;//存放顶点临接的面数的数组

int**nextVArr;//存放下一个临界顶点的数组

GLfloat**vnArr;//存放点法向量的二维数组

strings1,s2,s3,s4;

GLfloatf2,f3,f4;

intnum1,num2,num3;

typedefGLfloatpoint3[3];

point3x,y,l;//平面上的两个向量x,y和拉普拉斯向量l

staticGLfloattheta[]={0.0,0.0,0.0};

staticGLintaxis=2;

staticGLdoubleviewer[]={0.0,0.0,5.0};/*initialviewerlocation*/

staticGLdoubleTran[]={0.0,0.0,0.0};

staticGLdoublesca=1.0;

voidgetLineNum(stringaddrstr)//获取点和面的数量

{

ifstreaminfile(addrstr.c_str());//打开指定文件

if(!

infile){

cout<<"openerror!

"<

exit

(1);

}

stringsline;//每一行

inti=0,j=0;

while(getline(infile,sline))//从指定文件逐行读取

{

if(sline[0]=='v')

{

v_num++;

}

if(sline[0]=='f')

{

f_num++;

}

}

}

intreadfile(stringaddrstr)//将文件内容读到数组中去

{

//getLineNum(addrstr);

//new二维数组

vArr=newGLfloat*[v_num];

for(inti=0;i

{

vArr[i]=newGLfloat[3];

}

vNewArr=newGLfloat*[v_num];

for(inti=0;i

{

vNewArr[i]=newGLfloat[3];

}

vnArr=newGLfloat*[vn_num];

for(inti=0;i

{

vnArr[i]=newGLfloat[3];

}

vfArr=newint*[v_num];

for(inti=0;i

{

vfArr[i]=newint[10];

for(intj=0;j<10;j++){

vfArr[i][j]=-1;

}

}

nextVArr=newint*[v_num];

for(inti=0;i

{

nextVArr[i]=newint[10];

for(intj=0;j<10;j++){

nextVArr[i][j]=-1;

}

}

fvArr=newint*[f_num];

fnArr=newGLfloat*[f_num];

ftArr=newint*[f_num];

for(inti=0;i

{

fvArr[i]=newint[3];

fnArr[i]=newGLfloat[3];

ftArr[i]=newint[10];

}

ifstreaminfile(addrstr.c_str());

if(!

infile){

cout<<"openerror!

"<

exit

(1);

}

stringsline;//每一行

intii=0,jj=0,kk=0,mm=0;

while(getline(infile,sline))

{

if(sline[0]=='v')//存储点

{

istringstreamsin(sline);

sin>>s1>>f2>>f3>>f4;

vArr[ii][0]=f2;

vArr[ii][1]=f3;

vArr[ii][2]=f4;

ii++;

}

if(sline[0]=='f')//存储面

{

istringstreamin(sline);

GLfloata;

in>>s1>>num1>>num2>>num3;//去掉f

fvArr[kk][0]=num1;

fvArr[kk][1]=num2;

fvArr[kk][2]=num3;

for(inti=0;i<10;i++){

if(vfArr[num1-1][i]==-1){

vfArr[num1-1][i]=kk;

nextVArr[num1-1][i]=num2;

break;

}

}

for(intj=0;j<10;j++){

if(vfArr[num2-1][j]==-1){

vfArr[num2-1][j]=kk;

nextVArr[num2-1][j]=num3;

break;

}

}

for(inti=0;i<10;i++){

if(vfArr[num3-1][i]==-1){

vfArr[num3-1][i]=kk;

nextVArr[num3-1][i]=num1;

break;

}

}

kk++;

}

}

return0;

}

//计算面法向

voidnomal(point3p){

/*矢量的归一化*/

//doublesqrt();

floatd=0.0;

inti;

for(i=0;i<3;i++)

d+=p[i]*p[i];

d=sqrt(d);

if(d>0.0)

for(i=0;i<3;i++)

p[i]/=d;

}

voidgetFaceNormal(point3A,point3B,point3C){

x[0]=C[0]-A[0];

x[1]=C[1]-A[1];

x[2]=C[2]-A[2];

y[0]=A[0]-B[0];

y[1]=A[1]-B[1];

y[2]=A[2]-B[2];

point3v;

v[0]=x[1]*y[2]-x[2]*y[1];

v[1]=x[2]*y[0]-x[0]*y[2];

v[2]=x[0]*y[1]-x[1]*y[0];

nomal(v);

glNormal3fv(v);

}

 

voidLaplacian(){

for(intnum=0;num

intm=0;

//求得点的邻接面数

for(inti=0;i<10;i++){

if(nextVArr[num][i]!

=-1){

m++;

}

else{

break;

}

}

point3v0;

for(inti=0;i<3;i++){

v0[i]=0;

}

for(inti=0;i

v0[0]+=vArr[nextVArr[num][i]-1][0];

v0[1]+=vArr[nextVArr[num][i]-1][1];

v0[2]+=vArr[nextVArr[num][i]-1][2];

}

if(m!

=0){

for(inti=0;i<3;i++)

v0[i]/=m;

}

l[0]=v0[0]-vArr[num][0];

l[1]=v0[1]-vArr[num][1];

l[2]=v0[2]-vArr[num][2];

vNewArr[num][0]=vArr[num][0]+l[0]*0.3;

vNewArr[num][1]=vArr[num][1]+l[1]*0.3;

vNewArr[num][2]=vArr[num][2]+l[2]*0.3;

}

for(inti=0;i

vArr[i][0]=vNewArr[i][0];

vArr[i][1]=vNewArr[i][1];

vArr[i][2]=vNewArr[i][2];

}

}

voidinit(void)

{

getLineNum("H:

\\kitten_noisy.obj");

readfile("H:

\\kitten_noisy.obj");

doubleviewer[]={0.0,0.0,8.0};/*initialviewerlocation*/

 

GLfloatmat_specular[]={1.0,1.0,1.0,1.0};

GLfloatmat_shininess[]={50.0};//材料的镜面指数,其值越大越精细

GLfloatlight_position[]={1.0,1.0f,1.0,0.0};

GLfloatwhite_light[]={1.0,1.0,1.0,1.0};

GLfloatlmodel_ambient[]={0.1,0.1,0.1,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,lmodel_ambient);//环境光源

//glEnable(glMaterialf);

glEnable(GL_LIGHTING);//启动光照

glEnable(GL_LIGHT0);//启用0度光源

glEnable(GL_DEPTH_TEST);//启动深度测试

/*

glShadeModel(GL_SMOOTH);//EnableSmoothShading

glClearColor(0.0f,0.0f,0.0f,0.5f);//黑色背景

glClearDepth(1.0f);//深度缓冲区设置

glEnable(GL_DEPTH_TEST);//允许深度测试

glDepthFunc(GL_LEQUAL);//定义深度测试类型

glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);//ReallyNicePerspectiveCalculation

*/

}

 

voiddisplay(void)

{

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

gluLookAt(viewer[0],viewer[1],viewer[2],0.0,0.0,0.0,0.0,1.0,0.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);

glTranslatef(Tran[0],Tran[1],Tran[2]);

glScalef(sca,sca,sca);

//glPolygonMode(GL_FRONT_AND_BACK,GLU_FILL);

glBegin(GL_TRIANGLES);

//getFaceNormals();

for(inti=0;i

{

getFaceNormal(vArr[fvArr[i][0]-1],vArr[fvArr[i][1]-1],vArr[fvArr[i][2]-1]);

glVertex3f(vArr[fvArr[i][0]-1][0],vArr[fvArr[i][0]-1][1],vArr[fvArr[i][0]-1][2]);

glVertex3f(vArr[fvArr[i][1]-1][0],vArr[fvArr[i][1]-1][1],vArr[fvArr[i][1]-1][2]);

glVertex3f(vArr[fvArr[i][2]-1][0],vArr[fvArr[i][2]-1][1],vArr[fvArr[i][2]-1][2]);

}

glEnd();

/*

glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);

glBegin(GL_POINTS);

glColor3f(1.0,1.0,1.0);

for(inti=0;i

glVertex3fv(vArr[i]);

glNormal3fv(fnArr[i]);

}

glEnd();

*/

glFlush();//强制绘图

glutSwapBuffers();

}

voidreshape(intw,inth)

{

glViewport(0,0,(GLsizei)w,(GLsizei)h);//视口设置

glMatrixMode(GL_PROJECTION);

glLoadIdentity();

if(w<=h)//描绘了两种不同情况下的平行修剪空间

glOrtho(-0.6,0.6,-0.6*(GLfloat)h/(GLfloat)w,0.6*(GLfloat)h/(GLfloat)w,-10.0,10.0);

else

glOrtho(-0.6*(GLfloat)w/(GLfloat)h,0.6*(GLfloat)w/(GLfloat)h,-0.6,0.6,-10.0,10.0);

glMatrixMode(GL_MODELVIEW);

}

#defineGLUT_WHEEL_UP3//定义滚轮操作

#defineGLUT_WHEEL_DOWN4

voidmouse(intbtn,intstate,intx,inty)

{

if(btn==GLUT_LEFT_BUTTON&&state==GLUT_DOWN){

Laplacian();

}

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

if(btn==GLUT_RIGHT_BUTTON&&state==GLUT_DOWN)axis=1;

theta[axis]+=2.0;

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

display();

}

voidkeys(unsignedcharkey,intx,inty){

if(key=='a')

Tran[0]-=0.2;

i

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1