完整word版计算机图形学实验报告docx.docx

上传人:b****6 文档编号:7490765 上传时间:2023-01-24 格式:DOCX 页数:23 大小:20.99KB
下载 相关 举报
完整word版计算机图形学实验报告docx.docx_第1页
第1页 / 共23页
完整word版计算机图形学实验报告docx.docx_第2页
第2页 / 共23页
完整word版计算机图形学实验报告docx.docx_第3页
第3页 / 共23页
完整word版计算机图形学实验报告docx.docx_第4页
第4页 / 共23页
完整word版计算机图形学实验报告docx.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

完整word版计算机图形学实验报告docx.docx

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

完整word版计算机图形学实验报告docx.docx

完整word版计算机图形学实验报告docx

 

一、实验目的

1、掌握中点Bresenham直线扫描转换算法的思想。

 

2掌握边标志算法或有效边表算法进行多边形填充的基本设计思想。

 

3掌握透视投影变换的数学原理和三维坐标系中几何图形到二维图形的观察

流程。

4掌握三维形体在计算机中的构造及表示方法

 

二、实验环境

Windows系统,VC6.0。

 

三、实验步骤

 

1、给定两个点的坐标P0(x0,y0),P1(x1,y1),使用中点Bresenham直线扫描

 

转换算法画出连接两点的直线。

实验基本步骤

首先、使用MFCAppWizard(exe)向导生成一个单文档视图程序框架。

 

其次、使用中点Bresenham直线扫描转换算法实现自己的画线函数,函数原型可表示如下:

voidDrawLine(CDC*pDC,intp0x,intp0y,intp1x,intp1y);

在函数中,可通过调用CDC成员函数SetPixel来画出扫描转换过程中的每个点。

COLORREFSetPixel(intx,inty,COLORREFcrColor);

再次、找到文档视图程序框架视图类的OnDraw成员函数,调用DrawLine

函数画出不同斜率情况的直线,如下图:

 

最后、程序直至正确画出直。

2、定多形的点的坐P0(x0,y0),P1(x1,y1),P2(x2,y2),P3(x3,y3),P4(x4,y4)⋯

使用志算法或有效表算法行多形填充。

 

基本步

首先、使用MFCAppWizard(exe)向生成一个文档程序框架。

其次、志算法或有效表算法函数,如下:

voidFillPolygon(CDC*pDC,intpx[],intpy[],intptnumb);

px:

数用来表示每个点的x坐

py:

数用来表示每个点的y坐

ptnumb:

表示点个数

注意函数FillPolygon可以直接通窗口的DC(描述符)来行

多形填充,不需要使用冲存。

(志算法)首先用画函数勾画出多

形,再每条描,从左至右依次判断当前像素的色是否勾画的界色,

是就开始填充后面的像素直至再碰到界像素。

注意点要做特殊理。

通用GDI画点函数SetPixel来画出填充程中的每个点。

需要画可

以使用CDC的画函数MoveTo和LineTo行制,也可以使用一的画

直函数。

CPointMoveTo(intx,inty);

BOOLLineTo(intx,inty);

志算法算法需要取某个点的当前色,可以使用CDC的成函

COLORREFGetPixel(intx,inty);

再次、找到文档程序框架的OnDraw成函数,用FillPolygon函数画出填充的多形,如下:

voidCTestView:

:

OnDraw(CDC*pDC)

{

CTestcoodtransDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

 

//TODO:

adddrawcodefornativedatahere

//绘制之前先把整个窗口涂上背景色(白色)以便于下面的填充

RECTRt;

GetClientRect(&Rt);

pDC->FillSolidRect(&Rt,RGB(255,255,255));

 

intptx[]={10,100,200,150,80};

intpty[]={10,50,80,120,70};

FillPolygon(pDC,ptx,pty,5);

}

 

截图如下

 

3.在世界坐标系中定义一个立方体(由6个面组成),并给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角θ,俯仰角φ和姿态角α,另外再给定投影面离观察点的距离D,在屏幕上画出立方体的透视投影图形。

 

实验基本步骤

首先、使用MFCAppWizard(exe)向导生成一个单文档视图程序框架。

其次、由给定观察点在世界坐标系中的位置(a,b,c)以及观察坐标系的方位角

θ,俯仰角φ和姿态角α求出观察变换矩阵Tv.

再次、将立方体的每一个面的顶点坐标与变换矩阵Tv相乘得到观察坐标系

中的坐标,再由式

(1)求得二维投影坐标。

并用直线连接这些二维投影坐标点

形成每一个面在投影面的图形,依次将立方体的6个面画出即可。

 

核心代码如下:

voidCTestView:

:

OnDraw(CDC*pDC)

{

CTestDoc*pDoc=GetDocument();

ASSERT_VALID(pDoc);

//TODO:

adddrawcodefornativedatahereCRectRect;

GetClientRect(&Rect);

intMaxX=Rect.right;

intMaxY=Rect.bottom;

 

pDC->SetMapMode(MM_ANISOTROPIC);

pDC->SetWindowExt(1,1);

pDC->SetViewportExt(1,-1);

pDC->SetViewportOrg(MaxX/2,MaxY/2);//设置视点原点在屏幕中心

DrawObject(pDC);

}

 

voidCTestView:

:

ReadPoint()//读入8个顶点坐标

{

//每一行代表正方体每个顶点的x,y,z坐标

inta=200;//正方体边长

P[1][1]=-a/2;P[1][2]=-a/2;P[1][3]=-a/2;

P[2][1]=-a/2;P[2][2]=a/2;P[2][3]=-a/2;

P[3][1]=-a/2;P[3][2]=a/2;P[3][3]=a/2;

P[4][1]=-a/2;P[4][2]=-a/2;P[4][3]=a/2;

P[5][1]=a/2;P[5][2]=-a/2;P[5][3]=-a/2;

P[6][1]=a/2;P[6][2]=a/2;P[6][3]=-a/2;

P[7][1]=a/2;P[7][2]=a/2;P[7][3]=a/2;

P[8][1]=a/2;P[8][2]=-a/2;P[8][3]=a/2;

 

}

 

voidCTestView:

:

ReadFace()//读入6个面坐标

{

//第一列为每个面的边数;其余列为面的顶点编号

F[1][0]=4;F[1][1]=1;F[1][2]=2;F[1][3]=3;F[1][4]=4;

F[2][0]=4;F[2][1]=1;F[2][2]=4;F[2][3]=8;F[2][4]=5;

F[3][0]=4;F[3][1]=5;F[3][2]=6;F[3][3]=7;F[3][4]=8;

F[4][0]=4;F[4][1]=6;F[4][2]=2;F[4][3]=3;F[4][4]=7;

F[5][0]=4;F[5][1]=8;F[5][2]=7;F[5][3]=3;F[5][4]=4;

F[6][0]=4;F[6][1]=5;F[6][2]=6;F[6][3]=2;F[6][4]=1;

}

 

voidCTestView:

:

DrawObject(CDC*pDC)//绘制立方体

{

intTotalEdge,PointNumber;

intxt,yt,zt,x,y,z;//边的点坐标

CPenMyPen,*OldPen;

doublex2d,y2d;//屏幕坐标系的二维坐标点

 

MyPen.CreatePen(PS_SOLID,3,RGB(0,0,0));

OldPen=pDC->SelectObject(&MyPen);

for(face=1;face<=6;face++)

{

TotalEdge=F[face][0];//面的总边数

for(intedge=1;edge<=TotalEdge;edge++)//边循环

{

PointNumber=F[face][edge];//面的顶点号

x=P[PointNumber][1];//每个顶点的x,y,z坐标

y=P[PointNumber][2];

 

z=P[PointNumber][3];

Project(x2d,y2d,x,y,z);

if(edge==1)//保存起点用于闭合

{

pDC->MoveTo(ROUND(x2d),ROUND(y2d));

xt=x;yt=y;zt=z;

}

else

{

pDC->LineTo(ROUND(x2d),ROUND(y2d));

}

 

}

Project(x2d,y2d,xt,yt,zt);

pDC->LineTo(ROUND(x2d),ROUND(y2d));//封闭边

}

pDC->SelectObject(OldPen);

MyPen.DeleteObject();

}

 

voidCTestView:

:

Project(double&x2d,double&y2d,intx,inty,intz)//透视变换

{

doublex0,y0,z0;

//用户坐标变换为观察坐标系三维坐标,即用户坐标系坐标乘观察坐标变

换矩阵(x,y,z,1)*Tv

x0=x*Proj[0][0]+y*Proj[1][0]+z*Proj[2][0]+Proj[3][0];

y0=x*Proj[0][1]+y*Proj[1][1]+z*Proj[2][1]+Proj[3][1];

z0=x*Proj[0][2]+y*Proj[1][2]+z*Proj[2][2]+Proj[3][2];

 

//观察坐标系三维坐标透视变换为屏幕坐标系二维坐标,即(xv,yv,zv,1)*Ts,

再转化为非其次坐标

x2d=D*x0/z0;

y2d=D*y0/z0;

}

 

voidCTestView:

:

InitParameter()//初始化观察坐标变换矩阵

{

doublecosTheta=cos(PI*Theta/180);

doublesinTheta=sin(PI*Theta/180);

doublecosPhi=cos(PI*Phi/180);

doublesinPhi=sin(PI*Phi/180);

doublecosAlpha=cos(PI*Alpha/180);

doublesinAlpha=sin(PI*Alpha/180);

Proj[0][0]=cosTheta*cosAlpha+sinTheta*cosPhi*sinAlpha;

Proj[0][1]=cosTheta*sinAlpha-cosPhi*sinTheta*cosAlpha;

Proj[0][2]=-sinPhi*sinTheta;

Proj[0][3]=0;

 

Proj[1][0]=-sinPhi*sinAlpha;

Proj[1][1]=sinPhi*cosAlpha;

Proj[1][2]=-cosPhi;

Proj[1][3]=0;

 

Proj[2][0]=-sinTheta*cosAlpha+cosTheta*cosPhi*sinAlpha;

Proj[2][1]=-sinTheta*sinAlpha-cosPhi*cosTheta*cosAlpha;

Proj[2][2]=-sinPhi*cosTheta;

Proj[2][3]=0;

 

Proj[3][0]=

 

-(a*cosTheta-c*sinTheta)*cosAlpha-(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*si

nAlpha;

Proj[3][1]=

-(a*cosTheta-c*sinTheta)*sinAlpha+(-b*sinPhi+(a*sinTheta+c*cosTheta)*cosPhi)*cosAlpha;

Proj[3][2]=b*cosPhi+(a*sinTheta+c*cosTheta)*sinPhi;Proj[3][3]=1;

}

 

voidCTestView:

:

OnCustom()

{

//TODO:

AddyourcommandhandlercodehereAfxGetMainWnd()->SetWindowText("透视变换-任意观察坐标系透视");

 

//任意设定观察点

a=200;

b=0;

c=500;

//观察角度

Theta=20;

Phi=90;

Alpha=10;

//视距

D=800;

 

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

 

voidCTestView:

:

OnMENUOne()//一点透视

{

//TODO:

AddyourcommandhandlercodehereAfxGetMainWnd()->SetWindowText("透视变换-一点透视");Theta=0;

Phi=90;

Alpha=0;

 

//采用球面坐标设定观察点

doubleR=700.0;

a=R*sin(PI*Phi/180)*sin(PI*Theta/180);

b=R*cos(PI*Phi/180);

c=R*sin(PI*Phi/180)*cos(PI*Theta/180);

D=1000;//视距

 

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

 

voidCTestView:

:

OnMENUTwo()//二点透视

{

//TODO:

AddyourcommandhandlercodehereAfxGetMainWnd()->SetWindowText("透视变换-二点透视");Theta=30;

Phi=90;

Alpha=0;

 

//采用球面坐标设定观察点

doubleR=700.0;

a=R*sin(PI*Phi/180)*sin(PI*Theta/180);

b=R*cos(PI*Phi/180);

c=R*sin(PI*Phi/180)*cos(PI*Theta/180);

D=1000;//视距

 

InitParameter();

ReadPoint();

ReadFace();

RedrawWindow();

}

 

voidCTestView:

:

OnMENUThree()//三点透视

{

//TODO:

AddyourcommandhandlercodehereAfxGetMainWnd()->SetWindowText("透视变换-三点透视");Theta=45;

Phi=45;

Alpha=0;

 

//采用球面坐标设定观察点

doubleR=700.0;

a=R*sin(PI*Phi/180)*sin(PI*Theta/180);

b=R*cos(PI*Phi/180);

c=R*sin(PI*Phi/180)*cos(PI*Theta/180);

D=1000;//视距

 

InitParameter();

ReadPoint();

 

ReadFace();

RedrawWindow();

}

 

实验截图

 

4、迭代剖分法生成球面。

首先、使用MFCAppWizard(exe)向导生成一个单文档视图程序框架。

其次、初始化生成正八面体的顶点表,和面表。

再次、对面表里的每一个三角形进行剖分,一个三角形变成四个三角形。

产生的新的顶点加入到顶点表,同时将产生的新三角形加入到面表里,并从面表

里删除原来的三角形。

迭代多次后即得一个逼近于球面的多面体。

最后、对面表里的每一个三角形进行透视投影,在屏幕上画出透视投影图,调试程序直至正确。

 

实验核心代码如下:

voidCTestView:

:

GenerateSphereFace()//生成球面表

{

//首先生成一个正八面体

inta=200;

P[0][0]=0;P[0][1]=a;P[0][2]=0;

P[1][0]=0;P[1][1]=-a;P[1][2]=0;

P[2][0]=a;P[2][1]=0;P[2][2]=0;

P[3][0]=0;P[3][1]=0;P[3][2]=-a;

P[4][0]=-a;P[4][1]=0;P[4][2]=0;

P[5][0]=0;P[5][1]=0;P[5][2]=a;

intptNum=6;

 

faceNum=8;

F[0][0]=3;F[0][1]=0;F[0][2]=4;F[0][3]=5;

F[1][0]=3;F[1][1]=0;F[1][2]=5;F[1][3]=2;

F[2][0]=3;F[2][1]=0;F[2][2]=2;F[2][3]=3;

F[3][0]=3;F[3][1]=0;F[3][2]=3;F[3][3]=4;

F[4][0]=3;F[4][1]=1;F[4][2]=5;F[4][3]=4;

F[5][0]=3;F[5][1]=1;F[5][2]=2;F[5][3]=5;

F[6][0]=3;F[6][1]=1;F[6][2]=3;F[6][3]=2;

F[7][0]=3;F[7][1]=1;F[7][2]=4;F[7][3]=3;

 

//分割迭代

for(inttimes=0;times<3;times++)

{

inti,iNum=faceNum;

for(i=0;i

{//一个三角形分割为四个三角形

//

*

*

//

=>

*

*

//

*

*

*

*

*

//先求中点坐标,并添加到点表

intpt1=F[i][1];

intpt2=F[i][2];

intpt3=F[i][3];

 

intmid12=ptNum++;

doublemx=(P[pt1][0]+P[pt2][0])/2;

doublemy=(P[pt1][1]+P[pt2][1])/2;

doublemz=(P[pt1][2]+P[pt2][2])/2;

P[mid12][0]=a/sqrt(mx*mx+my*my+mz*mz)*mx;//坐标规范化P[mid12][1]=a/sqrt(mx*mx+my*my+mz*mz)*my;

 

P[mid12][2]=a/sqrt(mx*mx+my*my+mz*mz)*mz;

 

intmid23=ptNum++;

mx=(P[pt3][0]+P[pt2][0])/2;

my=(P[pt3][1]+P[pt2][1])/2;

mz=(P[pt3][2]+P[pt2][2])/2;

P[mid23][0]=a/sqrt(mx*mx+my*my+mz*mz)*mx;

P[mid23][1]=a/sqrt(mx*mx+my*my+mz*mz)*my;

P[mid23][2]=a/sqrt(mx*mx+my*my+mz*mz)*mz;

 

intmid13=ptNum++;

mx=(P[pt1][0]+P[pt3][0])/2;

my=(P[pt1][1]+P[pt3][1])/2;

mz=(P[pt1][2]+P[pt3][2])/2;

P[mid13][0]=a/sqrt(mx*mx+my*my+mz*mz)*mx;

P[mid13][1]=a/sqrt(mx*mx+my*my+mz*mz)*my;

P[mid13][2]=a/sqrt(mx*mx+my*my+mz*mz)*mz;

 

//被分割的三角形改为其中一个小的三角形,新建另外三个小的三角

F[i][2]=mid12;

F[i][3]=mid13;

 

F[faceNum][0]=3;

F[faceNum][1]=mid12;

F[faceNum][2]=pt2;

F[faceNum][3]=mid23;

faceNum++;

 

F[faceNum][0]=3;

F[faceNum][1]=mid13;

F[faceNum][2]=mid23;

F[faceNum][3]=pt3;

faceNum++;

 

F[faceNum][0]=3;

F[faceNum][1]=mid12;

F[faceNum][2]=mid23;

F[faceNum][3]=mid13;

faceNum++;

}

}

}

 

voidCTestView:

:

GenerateEllipsoidFace()//生成椭球面表

{

inta=200,b=100,c=100;

P[0][0]=0;P[0][1]=b;P[0][2]=0;

P[1][0]=0;P[1][1]=-b;P[1][2]=0;

P[2][0]=a;P[2][1]=0;P[2][2]=0;

P[3][0]=0;P[3][1]=0;P[3][2]=-c;

P[4][0]=-a;P[4][1]=0;P[4][2]=0;

P[5][0]=0;P[5][1]=0;P[5][2]=c;

intptNum=6;

 

faceNum=8;

F[0][0]=3;F[0][1]=0;F[0][2]=4;F[0][3]=5;

F[1][0]=3;F[1][1]=0;F[1][2]=5;F[1][3]=2;

F[2][0]=3;F[2][1]=0;F[2][2]=2;F[2][3]=3;

F[3][0]=3;F[3][1]=0;F[3][2]=3;F[3][3]=4;

F[4][0]=3;F[4][1]=1;F[4][2]=5;F[4][3]=4;

F[5][0]=3;F[5][1]=1;F[5][2]=2;F[5][3]=5;

F[6][0]=3;F[6][1]=1;F[6][2]=3;F[6][3]=2;

F[7][0]=3;F[7][1]=1;F[7][2]=4;F[7][3]=3;

 

//分割迭

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

当前位置:首页 > 法律文书 > 调解书

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

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