计算机图形学课程设计圆柱面图像纹理映射算法.docx
《计算机图形学课程设计圆柱面图像纹理映射算法.docx》由会员分享,可在线阅读,更多相关《计算机图形学课程设计圆柱面图像纹理映射算法.docx(14页珍藏版)》请在冰点文库上搜索。
计算机图形学课程设计圆柱面图像纹理映射算法
计算机图形学课程设计--圆柱面图像纹理映射算法
《计算机图形学》
课程学习报告
项目题目:
圆柱面图像纹理映射算法
1、项目描述....................................................................................................................................1
1.1圆柱面的建立和二维图像纹理的绑定..............................................................................1
1.2坐标系的建立......................................................................................................................1
二、项目需求....................................................................................................................................1
三、项目设计....................................................................................................................................3
3.1.8时间函数....................................................................................................................9
3.1.9动画控制函数............................................................................................................10
四、项目效果..................................................................................................................................10
5、项目总结..................................................................................................................................11
6、参考文献..................................................................................................................................12
1、项目描述
1.1、圆柱的建立和二维图像纹理的绑定
以屏幕客户区中心为体心建立圆柱面的几何模型。
读入二维位图图像纹理,将纹理绑定到圆柱上。
使用材质慢反射率设置纹理颜色,光源颜色设置为白色。
使用Phong明暗处理绘制光照纹理圆柱面动画
1.2、坐标系的建立
1>、自定义屏幕三维左手坐标,原点位于客户区中心,x轴水平向右为正,y轴垂直向上为正,z轴指向屏幕内部,
2>、建立三维用户右手坐标系{O;x,y,z},原点O位于客户区中心,x轴水平向右,y垂直向上,z轴指向读者。
2、项目需求
2.1、几何构造的原理
圆柱面采用平面四边形小面逼近,需要根据周向相邻2个小面的法矢量计算平均法矢量。
对于索引号(i,j)的顶点,其相邻顶点的索引号如图所示。
图中箭头所示为每个小面的边矢量,俩个边矢量的叉积得到小面的法矢量Ni。
小面的平均法矢量N的计算公式为N=
圆柱面平均法矢量的计算
2.2、动画的设计
实现动画的函数
voidCMy123054212View:
:
OnPlay()
{
//TODO:
Addyourcommandhandlercodehere
bPlay=bPlay?
FALSE:
TRUE;
if(bPlay)//设置定时器
SetTimer(1,150,NULL);
Else
KillTimer
(1);
}
设定动画时间
voidCTestView:
:
OnTimer(UINTnIDEvent)//动画时间函数
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
Beta=5;
tran.RotateY(Beta);
Invalidate(FALSE);
CView:
:
OnTimer(nIDEvent);
}
2.3、纹理的设计
2.3.1纹理映射的原理
使用MFC的资源标签页加载二维图像纹理,DDB位图的标识取为IDB_TEXTURE。
将纹理读入二维数组中,将纹理图像绑定到圆柱面的侧面网格顶点上。
将图像纹理的颜色值作为材质漫反射率和环境光反射率,镜面反射光设置为白光,使用Phong明暗处理绘制光照纹理圆柱面。
2.3.2纹理的定义
在CTestView类内添加成员函数ReadVertex(),将纹理绑定到圆柱面侧面的顶点上,CT2类定义了纹理坐标的(u,v)。
由于底面和顶面采用三角形网格逼近,所以使用CT2类定义了Texture4和Texture3纹理数组。
圆柱的侧面使用周向平均法矢量计算光照。
填充底面顶面的三角形面片时,进行了特殊处理。
然后添加ReadImage()读入纹理。
3、项目设计
3.1、窗口设计以及各项功能的实现
3.1.1窗口设计函数
BOOLCMy123054212App:
:
InitInstance()
{//Theoneandonlywindowhasbeeninitialized,soshowandupdateit.
m_pMainWnd->ShowWindow(SW_MAXIMIZE);
m_pMainWnd->SetWindowText("1234054212刘美艳");
m_pMainWnd->UpdateWindow();
returnTRUE;
}
3.1.2、点表函数
voidCMy123054212View:
:
ReadVertex()//点表
{
doubler=144;//圆柱底面半径
h=500;//圆柱的高
cTheta=10;//周向夹角
cNum=10;//纵向间距
N1=360/cTheta;//N1周向网格数
N2=Round(h/cNum);//N2纵向网格数
V=newCP3[N1*(N2+1)+2];//顶点动态数组
T=newCT2[N1*(N2+1)+2];//纹理动态数组
N=newCVector[N1*(N2+1)+2];//法矢量动态数组
doublecTheta1,cNum1;
V[0].x=0;V[0].y=0;V[0].z=0;//底面中心
T[0].u=0;T[0].v=0;//闲置
for(inti=0;i{
cNum1=i*cNum;
for(intj=0;j{
cTheta1=j*cTheta*PI/180;
V[i*N1+j+1].x=r*cos(cTheta1);
V[i*N1+j+1].y=cNum1;
V[i*N1+j+1].z=r*sin(cTheta1);
T[i*N1+j+1].u=(2*PI-cTheta1)/(2*PI)*(bmp.bmWidth-1);//u(0->1)
T[i*N1+j+1].v=V[i*N1+j+1].y/h*(bmp.bmHeight-1);//v(0->1)
}
}
V[N1*(N2+1)+1].x=0;V[N1*(N2+1)+1].y=h;V[N1*(N2+1)+1].z=0;//顶面中心T[N1*(N2+1)+1].u=0;T[N1*(N2+1)+1].v=0;//闲置
}
3.1.3、面表函数
voidCMy123054212View:
:
ReadFace()//面表
{
//设置二维动态数组
F=newCFace*[N2+2];//纵向
for(intn=0;nF[n]=newCFace[N1];//周向
for(intj=0;j{
inttempj=j+1;
if(N1==tempj)tempj=0;//面片的首尾连接
intBottomIndex[3];//底部三角形面片索引号数组
BottomIndex[0]=0;
BottomIndex[1]=j+1;
BottomIndex[2]=tempj+1;
F[0][j].SetNum(3);
for(intk=0;kF[0][j].vI[k]=BottomIndex[k];
}
for(inti=1;i{
for(intj=0;j{
inttempi=i+1;
inttempj=j+1;
if(N1==tempj)tempj=0;
intBodyIndex[4];//圆柱体四边形面片索引号数组
BodyIndex[0]=(i-1)*N1+j+1;
BodyIndex[1]=(tempi-1)*N1+j+1;
BodyIndex[2]=(tempi-1)*N1+tempj+1;
BodyIndex[3]=(i-1)*N1+tempj+1;
F[i][j].SetNum(4);
for(intk=0;kF[i][j].vI[k]=BodyIndex[k];
}
}
for(j=0;j{
inttempj=j+1;
if(N1==tempj)tempj=0;
intTopIndex[3];//顶部三角形面片索引号数组
TopIndex[0]=N1*i+1;
TopIndex[1]=N1*(i-1)+tempj+1;
TopIndex[2]=N1*(i-1)+j+1;
F[N2+1][j].SetNum(3);
for(intk=0;kF[N2+1][j].vI[k]=TopIndex[k];
}
}
3.1.4、绘制圆柱函数
voidCMy123054212View:
:
DrawObject(CDC*pDC)//绘制圆柱面
{
CalNormal();
CZBuffer*zbuf=newCZBuffer;//申请内存
zbuf->InitDeepBuffer(800,800,1000);//初始化深度缓冲器
CPi3Point3[3];//底面与顶面三角形顶点数组
CT2Texture3[3];//底面与顶面三角形纹理数组
CVectorNormal3[3];//底面与顶面三角形法矢量数组
CPi3Point4[4];//侧面四边形顶点数组
CT2Texture4[4];//侧面四边形纹理数组
CVectorNormal4[4];//侧面四边形法矢量数组
for(inti=0;i{
for(intj=0;j{
CVectorViewVector(V[F[i][j].vI[0]],ViewPoint);//面的视矢量
ViewVector=ViewVector.Normalize();//单位化视矢量
F[i][j].SetFaceNormal(V[F[i][j].vI[0]],V[F[i][j].vI[1]],V[F[i][j].vI[2]]);//计算小面片法矢量
F[i][j].fNormal.Normalize();//单位化法矢量
if(Dot(ViewVector,F[i][j].fNormal)>=0)
{
if(3==F[i][j].vN)//处理三角形面片
{
for(intm=0;m{
PerProject(V[F[i][j].v
I[m]]);
Point3[m]=ScreenP;
Normal3[m]=F[i][j].fNormal;
}
doubletempj=j+1;//对三角形面片进行特殊处理
Texture3[0].u=cTheta*(j+0.5)/360.0;Texture3[0].v=0.0;
Texture3[1].u=cTheta*(j+0.5)/360.0;Texture3[1].v=0.0;
Texture3[2].u=cTheta*tempj/360.0;Texture3[2].v=0.0;
zbuf->SetPoint(Point3,Normal3,Texture3,3);//初始化
zbuf->CreateBucket();//创建桶表
zbuf->CreateEdge();//创建边表
zbuf->Phong(pDC,ViewPoint,pLight,pMaterial,Image);//填充三角形
zbuf->ClearMemory();
}
else//处理四边形面片
{
for(intm=0;m{
PerProject(V[F[i][j].vI[m]]);
Point4[m]=ScreenP;
Normal4[m]=N[F[i][j].vI[m]];
Texture4[m]=T[F[i][j].vI[m]];
}
if(N1-1==j)//消除图像纹理的接缝
{
Texture4[2].u=0.0;
Texture4[3].u=0.0;
}
zbuf->SetPoint(Point4,Normal4,Texture4,4);//初始化
zbuf->CreateBucket();//创建桶表
zbuf->CreateEdge();//创建边表
zbuf->Phong(pDC,ViewPoint,pLight,pMaterial,Image);//填充四边形
zbuf->ClearMemory();
}
}
}
}
deletezbuf;
}
3.1.5、透视变换函数
voidCMy123054212View:
:
PerProject(CP3P)//透视变换
{
CP3ViewP;
ViewP.x=P.x*k[3]-P.z*k[1];//观察坐标系三维坐标
ViewP.y=-P.x*k[8]+P.y*k[2]-P.z*k[7];
ViewP.z=-P.x*k[6]-P.y*k[4]-P.z*k[5]+R;
ViewP.c=P.c;
ScreenP.x=d*ViewP.x/ViewP.z;//屏幕坐标系三维坐标
ScreenP.y=Round(d*ViewP.y/ViewP.z);
ScreenP.z=Far*(1-Near/ViewP.z)/(Far-Near);
ScreenP.c=ViewP.c;
}
3.1.6、读入纹理
voidCMy123054212View:
:
ReadImage()//读入纹理
{
CBitmapNewBitmap;
NewBitmap.LoadBitmap(IDB_TEXTURE);//调入DDB位图
NewBitmap.GetBitmap(&bmp);//将CBitmap的信息保存到Bitmap结构体中
intnbytesize=bmp.bmWidthBytes*bmp.bmHeight;
im=newBYTE[nbytesize];
NewBitmap.GetBitmapBits(nbytesize,(LPVOID)im);
Image=newCOLORREF*[bmp.bmHeight];
for(intn1=0;n1Image[n1]=newCOLORREF[bmp.bmWidth];
for(n1=0;n1{
for(intn2=0;n2{
intpos=n1*bmp.bmWidthBytes+4*n2;//颜色分量位置
n1=bmp.bmHeight-1-n1;//位图从左下角向右上角
Image[n1][n2]=RGB(im[pos+2],im[pos+1],im[pos]);
}
}
delete[]im;
}
3.1.7、背景函数
BOOLCMy123054212View:
:
OnEraseBkgnd(CDC*pDC)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
returnTRUE;
}
3.1.8、时间函数
voidCMy123054212View:
:
OnTimer(UINTnIDEvent)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
Beta=5;
tran.RotateY(Beta);
Invalidate(FALSE);
CView:
:
OnTimer(nIDEvent);
}
3.1.9、动画控制函数
voidCMy123054212View:
:
OnUpdatePlay(CCmdUI*pCmdUI)
{
//TODO:
AddyourcommandupdateUIhandlercodehere
if(bPlay)
{
pCmdUI->SetCheck(TRUE);
pCmdUI->SetText("停止");
}
else
{
pCmdUI->SetCheck(FALSE);
pCmdUI->SetText("开始");
}
}
4、项目效果
4.1构造图形分析以及坐标系变换的效果
5、项目总结
本项目将一幅位图映射到圆柱面上,并进行了光照计算。
由于圆柱面侧面的展开图是长方形,如果取得图像大小为侧面展开图的大小,则圆柱面上的像素与图像上的像素有一一对应关系。
本项目在点表中进行图像纹理绑定。
对于单幅图像映射,一般在点表中绑定;对于多幅图像映射,一般在面表中绑定。
侧面四边形顶点的法矢量取为周向2个表面的平均法矢量。
圆柱面试闭合的二次曲面,这要求对图像纹理闭合处进行特殊处理,处理方法见DrawObject()函数。
六、参考文献
计算机图形学实践教程(第二版孔令德)
计算机图形学基础教程(第二版孔令德)