文章目录
TIT 计算机图形学 期末课设-青花瓷坛的实体模型
前言
- 实验中用到了很多知识点,这里只讲解其中的一部分,仅供参考.详细讲解可以看孔老师的视频课,具体学习程序中的类
- 参考视频计算机图形学全套算法讲解和C++编码实现(共23讲配套源码),计算机图形学案例视频讲解以及主页相关算法。孔老师是我的代课老师,孔教授有十多年教学经验,视频课很不错,所有的源程序都基于他写的函数,并非小张写的。所有源程序都基于C+编译
- 参考教材《计算机图形学-理论与实践项目化教程》 孔令德著,大家多多支持哇
- 实验源码很多,没有传CSDN因为小张认为源码并不是我开的,只是拿老师的程序做了一些东西,拿这个赚积分和马内未免有点!这里直接放了青花瓷源程序。孔老师的视频课讲的很清楚,大家去B站就可以看啦!
一、项目描述
使用双三次贝塞尔曲线绘制青花瓷坛的线框模型,通过增加光照、材质、纹理,实现线框模型变为实体模型,达到模拟三维青花瓷坛的效果
二、项目设计
1.原理
映射原理: 双三次Bezier曲面的各处都具有了(u,v)值。将纹理uv与曲面uv同时规范化到[0,1]区间内,当查找到曲面纹理时,先将曲面uv放大到和纹理位图一样大小的尺寸,然后获取对应纹理图像上的颜色作为曲面上该点的漫反射率系数
2.背面剔除算法原理:
视矢量与小平面法矢量的点积大于等于零(n·v>=0),cosα>0,表面可见
1.使用四边形网格的顶点计算面矢量并归一化
2.使用四边形网格的第一顶点与视点,计算矢量并归一化
3.计算法矢量与视矢量的点积,如果其值大于等于零,则绘制该网格,否则剔除该网格
3.球体图像纹理映射原理
3.1读入位图
纹理来自于位图,将位图作为资源导入,位图由DIB格式自动转换为DDB格式,每行存储4个字节的颜色数据,将位图转储到一维颜色数组中,就可以根据曲面网格点与位图去查询位图像素点的颜色,并将其作为材质的漫反射率和环境反射率,从而实现了将位图绑定到物体表面上
4.算法步骤
1.将图像纹理加载到资源标签页中,将位图数据保存到一维数组中
2.定义revolution回转类,读入顶点表和表面表,圆环面全部细分为四边形网格
3.将位图绑定到回转体的顶点上
4.根据光源的位置,数量,视点的位置,材质属性,构造三维光照场景
5.使用画家算法,剔除回转体的不可见网格
6.使用三维透视投影算法,将回转体三维多边形投影为屏幕三维四边形
7.根据网格点的法矢量,插值计算小面内每一点的法矢量,将纹理作为该点的材质,调用光照模型计算小面内该点的光强
8.使用定时器改变圆环的转角生成旋转动画
2.相关算法
PhongShader算法: 对顶点的法矢量进行插值,得到小面内每一点的法矢量。对小面内的每一点都调用光照模型计算光强。计算光强需要四个参数,视点位置、当前点三维坐标、当前点法矢量、当前点的材质属性。如果当前点的材质的漫反射率取自一幅图像的相应点,这就为该物体添加了纹理。
向量线性插值计算:
v(t)=(tEnd-t)/(tEnd-tStart)*vStart+(t-tStart)/(tEnd-tStart)*vEnd;
t表示第一个向量的x(y)方向单位向量,tStart表示第一个点的x(y)方向单位向量,tEnd表示第二个点的x(y)方向单位向量,vStart起点的法向量,vEnd表示第二个点的法向量。
计算光强公式:
I=Ie +Id+Is =kaIa+f(d)[KdIpmax(N·L,0)+ksIpmax(N·H)n]
计算物体表面上任意一点P的光强I时,必须确定物体表面的单位矢量L、单位中分矢量H、单位法矢量N以及材质的漫反射率kd。当光源位置和视点位置不变时,光矢量L和中分矢量H是一个定值。影响光强的只有漫反射率kd和单位法矢量N。
Zbuffer算法:通过使用处理深度缓冲器,若当前点的深度值小于缓冲器中的深度值,则说明当前点离视点近,使用SetPixelV函数绘制当前点,否则放弃当前点。
当前像素点的深度值:z(x,y)=-z(x,y)=- A x + B y + D C \frac{Ax+By+D}{C} CAx+By+D,C≠0,C≠0;
A,B,C代表法向量的坐标
3.模型
三、部分代码
1.导入位图,格式为bmp
2.Texture类
class CTexture
{
public:
CTexture(void);
virtual~CTexture(void);
void PrepareBitmap(UINT nIDResource);//准备位图
void DeleteObject(void);//释放位图
public:
BYTE* image;//存储位图一维数组
BITMAP bmp;//BITMAP结构体变量
};
CTexture::CTexture(void)//数组初始化为空
{
image = NULL;
}
CTexture::~CTexture(void)
{
}
void CTexture::PrepareBitmap(UINT nIDResource)//准备位图
{
CBitmap NewBitmap;//DDB
NewBitmap.LoadBitmap(nIDResource);//从资源视图中读入位图存储到Newbitmap中
NewBitmap.GetBitmap(&bmp);//将CBitmap的信息保存到Bitmap结构体中,目的是为了得到图像的高度和宽度
int nbytesize = bmp.bmWidthBytes * bmp.bmHeight;//计算位图字节数
image = new BYTE[nbytesize];
NewBitmap.GetBitmapBits(nbytesize, (LPVOID)image);//将位图数据赋值到一维数组image中
}
void CTexture::DeleteObject(void)//释放位图
{
if(NULL != image)
delete []image;
}
3.在贝塞尔曲线类中绑定纹理对象
void CBezierPatch::Tessellation(CMesh Mesh)//细分曲面函数
{
double M[4][4];//系数矩阵M
M[0][0] = -1, M[0][1] = 3, M[0][2] = -3, M[0][3] = 1;
M[1][0] = 3, M[1][1] = -6, M[1][2] = 3, M[1][3] = 0;
M[2][0] = -3, M[2][1] = 3, M[2][2] = 0, M[2][3] = 0;
M[3][0] = 1, M[3][1] = 0, M[3][2] = 0, M[3][3]