计算机图形学实验报告2

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机图形学实验报告

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

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

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

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

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

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

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

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

1. 操作系统:Windows XP 或Windows 7

2. 编程环境:Microsoft Visual Studio 2010,OpenGL 库函数

3. 界面框架:Win32,MFC,QT选择其中一种

三、实验内容与步骤

实验分为以下几个步骤:

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

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

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

(4)计算每个面的法向

利用OpenGL类库,增加采用鼠标交互方式对三维模型进行旋转、放缩、平移等操作;(5)利用面法向及顶点坐标进行绘制几何体

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

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

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

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

由于obj文件的存储形式是

v x1 x2 x3;

f v1 v2 v3;

这种形式,所以在记录点和面的数量时,只需按行读取,然后再判断首字母是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

具体代码如下:

五、结果展示及说明

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

光顺进行一次后

光顺多次后

利用点绘制结果为

旋转后

缩放后

平移后

六、心得体会

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

(2)在运用Laplacian算法进行求邻接平均点时未初始化邻接平均点数组,导致平均点的累加从而出现越光顺越粗糙的现象

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

七、实验代码

#define GLUT_DISABLE_ATEXIT_HACK

#include

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

int v_num = 0; //记录点的数量

int f_num = 0; //记录面的数量

int vn_num = 0;//记录法向量的数量

int vt_num = 0;

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

相关文档
最新文档