当前位置:文档之家› 计算机图形学课程设计报告 简单光照

计算机图形学课程设计报告 简单光照

目录目录 (I)一、选题背景....................................................... 错误!未定义书签。

1.1 内容要求 ................................................. 错误!未定义书签。

1.1.1 内容设计 (2)1.1.2 基本要求 (2)二、算法设计....................................................... 错误!未定义书签。

2.1 相关原理 ................................................. 错误!未定义书签。

2.1.1 明暗模型 (3)2.1.2 镜面反射与Phong模型 (3)2.1.3 渲染 (3)2.2 模块划分 (4)三、程序及功能说明 (2)3.1 光照类型选择模块 (4)3.2 材质选择模块 (6)3.3 光照位置选择模块 (8)四、结果分析 (11)4.1 运行截图...... .. (11)五、总结........................................................... 错误!未定义书签。

六、课程设计心得体会....................................... 错误!未定义书签。

参考文献............................................................... 错误!未定义书签。

源程序. (18)三、程序及功能说明3.1 光照类型选择模块1、漫反射光代码if(Chk2){if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}2、环境光代码if(Chk1){ if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,N dr);dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;3、镜面反射光代码if(Chk3){double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,N dr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}3.2 材质选择模块1、金材质代码void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}2、银材质代码void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}3、红宝石材质代码void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}4、绿宝石材质代码void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.gr een;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}3.2 光照位置选择模块1、上右位置代码void CTestView::OnCheck11(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk11){Positionx=300;Positiony=300;Positionz=-300;Chk11=!Chk11;}else{Chk11=!Chk11;}Invalidate(false);UpdateData(false);}2、下右位置代码void CTestView::OnCheck12(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk12){Positionx=300;Positiony=300;Positionz=300;Chk12=!Chk12;}else{Chk12=!Chk12;}Invalidate(false);UpdateData(false);}3、上左位置代码void CTestView::OnCheck9(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk9){Positionx=-300;Positiony=300;Positionz=-300;Chk9=!Chk9;}else{Chk9=!Chk9;}Invalidate(false);UpdateData(false);}4、下左位置代码void CTestView::OnCheck10(){// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk10){Positionx=-300;Positiony=300;Positionz=300;Chk10=!Chk10;}else{Chk10=!Chk10;}Invalidate(false);UpdateData(false);}四、结果分析4.1 运行截图图4-1 左上角光照显示结果图4-2 右下角光照显示结果图4-3 右上角光照显示结果图4-4 左下角源程序#include "stdafx.h"#include "Test.h"#include "TestDoc.h"#include "TestView.h"#include "math.h"//数学头文件#define ROUND(a) int(a+0.5)//四舍五入#define PI 3.1415926//圆周率#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif// CTestViewIMPLEMENT_DYNCREATE(CTestView, CView)BEGIN_MESSAGE_MAP(CTestView, CView) //{{AFX_MSG_MAP(CTestView)ON_WM_ERASEBKGND()ON_COMMAND(IDR_Light, OnLight)ON_BN_CLICKED(IDC_CHECK1, OnCheck1)ON_BN_CLICKED(IDC_CHECK2, OnCheck2)ON_BN_CLICKED(IDC_CHECK3, OnCheck3)ON_BN_CLICKED(IDC_CHECK4, OnCheck4)ON_BN_CLICKED(IDC_CHECK5, OnCheck5)ON_BN_CLICKED(IDC_CHECK6, OnCheck6)ON_BN_CLICKED(IDC_CHECK7, OnCheck7)ON_BN_CLICKED(IDC_CHECK8, OnCheck8)ON_BN_CLICKED(IDC_CHECK9, OnCheck9)ON_BN_CLICKED(IDC_CHECK10, OnCheck10) ON_BN_CLICKED(IDC_CHECK11, OnCheck11) ON_BN_CLICKED(IDC_CHECK12, OnCheck12) //}}AFX_MSG_MAP// Standard printing commandsON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) END_MESSAGE_MAP()/////////////////////////////////////////////////////////////////////////////// CTestView construction/destructionCTestView::CTestView(){// TODO: add construction code hereChk1=Chk2=Chk3=Chk4=Chk5=Chk6=false;Chk7=Chk8=Chk9=Chk10=Chk11=Chk12=false;r=100;//球半径R=300;Fei=90;Thta=90;D=800;//视点参数LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;n=5;//高光指数}CTestView::~CTestView(){}BOOL CTestView::PreCreateWindow(CREATESTRUCT& cs){// TODO: Modify the Window class or styles here by modifying// the CREATESTRUCT csreturn CView::PreCreateWindow(cs);}/////////////////////////////////////////////////////////////////////////////// CTestView drawingvoid CTestView::OnDraw(CDC* pDC){CTestDoc* pDoc = GetDocument();ASSERT_V ALID(pDoc);// TODO: add draw code for native data hereAfxGetMainWnd()->SetWindowText("光照模型:光源");GetMaxX();GetMaxY();InitParameter();ReadPoint();ReadFace();DrawGlobe();}/////////////////////////////////////////////////////////////////////////////// CTestView printingBOOL CTestView::OnPreparePrinting(CPrintInfo* pInfo){// default preparationreturn DoPreparePrinting(pInfo);}void CTestView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add extra initialization before printing}void CTestView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: add cleanup after printing}/////////////////////////////////////////////////////////////////////////////// CTestView diagnostics#ifdef _DEBUGvoid CTestView::AssertValid() const{CView::AssertValid();}void CTestView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CTestDoc* CTestView::GetDocument() // non-debug version is inline{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CTestDoc)));return (CTestDoc*)m_pDocument;}#endif //_DEBUG/////////////////////////////////////////////////////////////////////////////// CTestView message handlersvoid CTestView::GetMaxX()//获得屏幕宽度{CRect Rect;GetClientRect(&Rect);MaxX=Rect.right;}void CTestView::GetMaxY()//获得屏幕高度{CRect Rect;GetClientRect(&Rect);MaxY=Rect.bottom;}void CTestView::ReadPoint()//读入点坐标{double afa,beta;for(int i=0;i<37;i++){afa=i*5*PI/180;for(int j=0;j<72;j++){beta=j*5*PI/180;P[i][j].x=r*sin(afa)*cos(beta);P[i][j].y=r*sin(afa)*sin(beta);P[i][j].z=r*cos(afa);}}}void CTestView::ReadFace()//读入面坐标{for(int i=0;i<36;i++){for(int j=0;j<72;j++){F[i][j].p[0]=P[i][j];F[i][j].p[1]=P[i+1][j];if(j==71){F[i][j].p[2]=P[i+1][0];F[i][j].p[3]=P[i][0];}else{F[i][j].p[2]=P[i+1][j+1];F[i][j].p[3]=P[i][j+1];}}}}void CTestView::DrawGlobe(){CRect Rect;GetClientRect(&Rect);CDC MemDC;CBitmap Bitmap,*OldBitmap;Bitmap.LoadBitmap(IDB_BITMAP2);MemDC.CreateCompatibleDC(GetDC());OldBitmap=MemDC.SelectObject(&Bitmap);MemDC.BitBlt(0,0,Rect.Width(),Rect.Height(),&Picture,0,0,SRCCOPY);for(int i=0;i<36;i++){for(int j=0;j<72;j++){for(int m=0;m<4;m++){P1[m].x=F[i][j].p[m].x;P1[m].y=F[i][j].p[m].y;P1[m].z=F[i][j].p[m].z;Pdown[m].x=F[i+1][j].p[m].x;Pdown[m].y=F[i+1][j].p[m].y;Pdown[m].z=F[i+1][j].p[m].z;if(j==71){Pright[m].x=F[i][0].p[m].x;Pright[m].y=F[i][0].p[m].y;Pright[m].z=F[i][0].p[m].z;Pdownright[m].x=F[i+1][0].p[m].x;Pdownright[m].y=F[i+1][0].p[m].y;Pdownright[m].z=F[i+1][0].p[m].z;}else{Pright[m].x=F[i][j+1].p[m].x;Pright[m].y=F[i][j+1].p[m].y;Pright[m].z=F[i][j+1].p[m].z;Pdownright[m].x=F[i+1][j+1].p[m].x;Pdownright[m].y=F[i+1][j+1].p[m].y;Pdownright[m].z=F[i+1][j+1].p[m].z;}}bool First=true;P3d Pt[3];//四边形划分为两个三角形面片Pt[0]=P1[0];Pt[1]=P1[1];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制上三角形面片First=false;Pt[0]=P1[1];Pt[1]=P1[2];Pt[2]=P1[3];Triangle(&MemDC,Pt,First);//绘制下三角形面片First=true;}}CClientDC dc(this);dc.BitBlt(0,0,Rect.Width(),Rect.Height(),&MemDC,0,0,SRCCOPY);MemDC.SelectObject(OldBitmap);}void CTestView::Triangle(CDC *mdc,P3d *p,bool First)//三角形面片{Vector vP10(P1[0]),vP11(P1[1]),vP12(P1[2]);//三角形平面片点矢量Vector vPd0(Pdown[0]),vPd1(Pdown[1]),vPd2(Pdown[2]);Vector vPr0(Pright[0]),vPr1(Pright[1]),vPr2(Pright[2]);Vector vPdr0(Pdownright[0]),vPdr1(Pdownright[1]),vPdr2(Pdownright[2]);Vector VectorN1=NormalVector(vP10,vP11,vP12);//主面片法矢量Vector VectorNd=NormalVector(vPd0,vPd1,vPd2);//下面片法矢量Vector VectorNr=NormalVector(vPr0,vPr1,vPr2);//右面片法矢量Vector VectorNdr=NormalVector(vPdr0,vPdr1,vPdr2);//下右面片法矢量Vector N1,Nd,Nr,Ndr;N1=VectorN1.Unit();Nd=VectorNd.Unit();Nr=VectorNr.Unit();Ndr=VectorNdr.Unit();Vector LPosition(lightP.position),Lv=LPosition.Unit();MyRGB Ambientc=lightP.ambient;MyRGB Ambientd=lightP.ambient;MyRGB Ambientdr=lightP.ambient;MyRGB Ambientr=lightP.ambient;Vector vP0(p[0]),Uv;Vector VisualP(R*k[5],R*k[6],R*k[4]);//视点矢量球坐标Vector VisualV=VisualP-vP0;//视矢量Uv=VisualV.Unit();if(Chk1)//环境光{if(First){p[0].c=Ambientc;p[1].c=Ambientd;p[2].c=Ambientr;}else{p[0].c=Ambientd;p[1].c=Ambientdr;p[2].c=Ambientr;}}double c0,c1,c2,dist[3];//c0常数衰减因子,c1线性衰减因子,c2二次衰减因子,dist定点与光源的距离double f[3];c0=0.65;c1=0.00002;c2=0.000001;for(int i=0;i<3;i++){dist[i]=sqrt((p[i].x-Positionx)*(p[i].x-Positionx)+(p[i].y-Positiony)*(p[i].y-Positiony)+(p[i].z-Positionz)*(p[i].z-Positionz));f[i]=1.0/(c0+c1*dist[i]+c2*dist[i]*dist[i]);f[i]=Min(f[i]);}double dCosc,dCosd,dCosr,dCosdr;dCosc=Dot(Lv,N1);dCosd=Dot(Lv,Nd);dCosr=Dot(Lv,Nr);dCosdr=Dot(Lv,Ndr); dCosc=(dCosc<0.0f)?0.0f:dCosc;dCosd=(dCosd<0.0f)?0.0f:dCosd;dCosr=(dCosr<0.0f)?0.0f:dCosr;dCosdr=(dCosdr<0.0f)?0.0f:dCosdr;MyRGB Diffusec=lightP.diffuse*dCosc;MyRGB Diffused=lightP.diffuse*dCosd;MyRGB Diffuser=lightP.diffuse*dCosr;MyRGB Diffusedr=lightP.diffuse*dCosdr;if(Chk2)//漫反射光{if(First){p[0].c=Ambientc+Diffusec*f[0];p[1].c=Ambientd+Diffused*f[1];p[2].c=Ambientr+Diffuser*f[2];}else{p[0].c=Ambientd+Diffused*f[0];p[1].c=Ambientdr+Diffusedr*f[1];p[2].c=Ambientr+Diffuser*f[2];}}if(Chk3)//镜面反射光{double sCosc,sCosd,sCosdr,sCosr;Vector Hvector,Hv;Hvector=(LPosition+VisualV)*0.5;//平分矢量Hv=Hvector.Unit();sCosc=Dot(Hv,N1);sCosd=Dot(Hv,Nd);sCosr=Dot(Hv,Nr);sCosdr=Dot(Hv,Ndr);for(int i=0;i<n;i++)//计算n次方{sCosc*=sCosc;sCosd*=sCosd;sCosr*=sCosr;sCosdr*=sCosdr;}sCosc=(dCosc<0.0f)?0.0f:sCosc;sCosd=(dCosd<0.0f)?0.0f:sCosd;sCosr=(dCosr<0.0f)?0.0f:sCosr;sCosdr=(dCosdr<0.0f)?0.0f:sCosdr;MyRGB Specularc=lightP.specular*sCosc;MyRGB Speculard=lightP.specular*sCosd;MyRGB Specularr=lightP.specular*sCosr;MyRGB Speculardr=lightP.specular*sCosdr;if(First){p[0].c=Ambientc+Diffusec*f[0]+Specularc*f[0];p[1].c=Ambientd+Diffused*f[1]+Speculard*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}else{p[0].c=Ambientd+Diffused*f[0]+Speculard*f[0];p[1].c=Ambientdr+Diffusedr*f[1]+Speculardr*f[1];p[2].c=Ambientr+Diffuser*f[2]+Specularr*f[2];}}for(int k=0;k<3;k++){Project(p[k]);Point[k].x=ScreenP.x;Point[k].y=ScreenP.y;Point[k].c=ScreenP.c;}if(Dot(Uv,N1)>=0)//根据数量积正负消隐{CreatBucket();//初始化桶Et();//用于建立边表SphereFill(mdc);//进行填充}}void CTestView::Project(P3d &P)//透视变换{ViewP.x=k[1]*P.x-k[3]*P.y;//观察坐标系的三维坐标ViewP.y=-k[7]*P.x-k[8]*P.y+k[2]*P.z;ViewP.z=-k[5]*P.x-k[6]*P.y-k[4]*P.z+R;ScreenP.x=D*ViewP.x/ViewP.z;//屏幕坐标系的二维坐标ScreenP.y=ROUND(D*ViewP.y/ViewP.z);ScreenP.c=P.c;}void CTestView::InitParameter()//透视变换常数{k[1]=sin(PI*Thta/180);k[2]=sin(PI*Fei/180);k[3]=cos(PI*Thta/180);k[4]=cos(PI*Fei/180);k[5]=k[3]*k[2];k[6]=k[1]*k[2];k[7]=k[3]*k[4];k[8]=k[1]*k[4];}//*****************有效边表算法开始***********************void CTestView::SphereFill(CDC* mdc)//下闭上开填充{HeadE=NULL;for(CurrentB=HeadB;CurrentB!=NULL;CurrentB=CurrentB->next)//访问所有桶结点{for(CurrentE=CurrentB->p;CurrentE!=NULL;CurrentE=CurrentE->next)//访问桶中排序前的边结点{Edge *TEdge=new Edge;TEdge->k=CurrentE->k;TEdge->x=CurrentE->x;TEdge->yMax=CurrentE->yMax;TEdge->x1=CurrentE->x1;TEdge->y1=CurrentE->y1;TEdge->c1=CurrentE->c1;TEdge->x2=CurrentE->x2;TEdge->y2=CurrentE->y2;TEdge->c2=CurrentE->c2;TEdge->next=NULL;AddAet(TEdge);//将该边插入临时Aet表}AetOrder();//使得Aet表按照x递增的顺序存放T1=HeadE;//根据ymax抛弃扫描完的边结点if(T1==NULL){return;}while(CurrentB->ScanLine>=T1->yMax)//放弃该结点,Aet表指针后移{T1=T1->next;HeadE=T1;if(HeadE==NULL){return;}}if(T1->next!=NULL){T2=T1;T1=T2->next;}while(T1!=NULL){if(CurrentB->ScanLine>=T1->yMax)//跳过一个结点{T2->next=T1->next;T1->next=NULL;T1=T2->next;}else{T2=T1;T1=T2->next;}}MyRGB Is,It,Ip;if(CurrentE!=NULL)//扫描线上两边共线{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->c2,Head E->c1);}else{Is=Interpolation(CurrentB->ScanLine,HeadE->y1,HeadE->y2,HeadE->c1,HeadE->c2);It=Interpolation(CurrentB->ScanLine,HeadE->next->y2,HeadE->next->y1,HeadE->next->c2 ,HeadE->next->c1);}BOOL In=false;//设置一个BOOL变量In,初始值为假int xb,xe;//扫描线区间的起点和终点for(T1=HeadE;T1!=NULL;T1=T1->next)//填充扫描线和多边形相交的区间{if(In==false){xb=ROUND(T1->x)-1;In=true;//每访问一个结点,把In值取反一次}else//如果In值为真,则填充从当前结点的x值开始到下一结点的x值结束的区间{xe=ROUND(T1->x);for(int x=xb;x<=xe;x++){Ip=Interpolation(x,xb,xe,Is,It);mdc->SetPixel(MaxX/2+x,MaxY/2+CurrentB->ScanLine,RGB((BYTE)(Ip.red*255),(BYTE )(Ip.green*255),(BYTE)(Ip.blue*255)));}In=false;}for(T1=HeadE;T1!=NULL;T1=T1->next)//边连贯性{T1->x=T1->x+T1->k;//x=x+1/k}}delete HeadB;delete CurrentB;delete CurrentE;delete HeadE;}MyRGB CTestView::Interpolation(int m,int m1,int m2,MyRGB &c1,MyRGB &c2)//边界插值{MyRGB I;I.red=double(m-m2)/(m1-m2)*c1.red+double(m1-m)/(m1-m2)*c2.red;I.green=double(m-m2)/(m1-m2)*c1.green+double(m1-m)/(m1-m2)*c2.green;I.blue=double(m-m2)/(m1-m2)*c1.blue+double(m1-m)/(m1-m2)*c2.blue;return I;}void CTestView::CreatBucket()//初始化桶结点{int ScanMin,ScanMax;//确定扫描线的最小值和最大值ScanMax=ScanMin=Point[0].y;for(int i=1;i<Number;i++){if(Point[i].y<ScanMin){ScanMin=Point[i].y;//扫描线的最小值}if(Point[i].y>ScanMax){ScanMax=Point[i].y;//扫描线的最大值}for(i=ScanMin;i<=ScanMax;i++)//建立桶结点{if(ScanMin==i){HeadB=new Bucket;//建立桶的头结点CurrentB=HeadB;//CurrentB为Bucket当前结点指针CurrentB->ScanLine=ScanMin;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}else//建立桶的其它结点{CurrentB->next=new Bucket;//新建一个桶结点CurrentB=CurrentB->next;//使CurrentB指向新建的桶结点CurrentB->ScanLine=i;CurrentB->p=NULL;//没有连接边链表CurrentB->next=NULL;}}}void CTestView::Et()//构造边表{for(int i=0;i<Number;i++)//访问每个顶点{CurrentB=HeadB;//从桶链表的头结点开始循环int j=i+1;//边的第二个顶点,Point[i]和Point[j]构成边if(j==Number) j=0;//保证多边形的闭合if(Point[j].y>Point[i].y)//边在扫描线的上方{while(CurrentB->ScanLine!=Point[i].y)//在桶内寻找该边的yMin{CurrentB=CurrentB->next;//在桶内寻找该边的yMin}E[i].x=Point[i].x;//计算Aet表的值E[i].yMax=Point[j].y;E[i].k=(Point[j].x-Point[i].x)/(Point[j].y-Point[i].y);//代表1/kE[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;//获得桶上链接边表的地址if(CurrentE==NULL)//当前桶结点上没有链接边结点{CurrentE=&E[i];//赋边的起始地址CurrentB->p=CurrentE;//第一个边结点直接连接到对应的桶中}else{while(CurrentE->next!=NULL)//如果当前边已连有边结点{CurrentE=CurrentE->next;//移动指针到当前边的最后一个边结点}CurrentE->next=&E[i];//把当前边接上去}}if(Point[j].y<Point[i].y)//边在扫描线的下方{while(CurrentB->ScanLine!=Point[j].y){CurrentB=CurrentB->next;}E[i].x=Point[j].x;E[i].yMax=Point[i].y;E[i].k=(Point[i].x-Point[j].x)/(Point[i].y-Point[j].y);E[i].x1=Point[i].x;E[i].y1=Point[i].y;E[i].c1=Point[i].c;E[i].x2=Point[j].x;E[i].y2=Point[j].y;E[i].c2=Point[j].c;E[i].next=NULL;CurrentE=CurrentB->p;if(CurrentE==NULL){CurrentE=&E[i];CurrentB->p=CurrentE;}else{while(CurrentE->next!=NULL){CurrentE=CurrentE->next;}CurrentE->next=&E[i];}}}CurrentB=NULL;CurrentE=NULL;}void CTestView::AddAet(Edge *NewEdge)//边插入Aet表{T1=HeadE;if(T1==NULL)//Aet表为空,将Aet表置为TEdge{T1=NewEdge;HeadE=T1;}else{while(T1->next!=NULL)//Aet表不为空,将TEdge连在该边之后{T1=T1->next;}T1->next=NewEdge;}}void CTestView::AetOrder()//对Aet表进行排序{T1=HeadE;if(T1==NULL){return;}if(T1->next==NULL)//如果该Aet表没有再连Aet表{return;//桶结点只有一条边,不需要排序}else{if(T1->next->x<T1->x)//Aet表按x值排序{T2=T1->next;T1->next=T2->next;T2->next=T1;HeadE=T2;}T2=HeadE;T1=HeadE->next;while(T1->next!=NULL)//继续两两比较相连的Aet表的x值,进行排序{if(T1->next->x<T1->x){T2->next=T1->next;T1->next=T1->next->next;T2->next->next=T1;T2=T2->next;}else{T2=T1;T1=T1->next;}}}}BOOL CTestView::OnEraseBkgnd(CDC* pDC)//设置背景色函数{// TODO: Add your message handler code here and/or call defaultCRect Rect;pDC->GetClipBox(&Rect);pDC->FillSolidRect(Rect,RGB(0,0,0));return true;}void CTestView::OnLight(){// TODO: Add your command handler code hereMessageBox("请选择光源!","提示");}void CTestView::OnCheck1()//环境光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk1){ lightP.ambient=LightA*MaterialA;Chk1=!Chk1;}else{Chk1=!Chk1;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck2()//漫反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk2){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.diffuse=LightD*MaterialD;//Lambert公式Chk2=!Chk2;}else{Chk2=!Chk2;}Invalidate(false);UpdateData(false);void CTestView::OnCheck3()//镜面反射光{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk3){lightP.position.x=Positionx;lightP.position.y=Positiony;lightP.position.z=Positionz;//光源位置lightP.specular=LightS*MaterialS;//Phong公式Chk3=!Chk3;}else{Chk3=!Chk3;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck4()//金{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk4){n=5;//聚光指数MaterialA.red=0.247;MaterialA.green=0.2;MaterialA.blue=0.075;MaterialD.red=0.752;MaterialD.green=0.606;MaterialD.blue=0.226;MaterialS.red=0.628;MaterialS.green=0.556;MaterialS.blue=0.366;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;Chk4=!Chk4;}else{Chk4=!Chk4;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck5()//银{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk5){n=6;MaterialA.red=0.192;MaterialA.green=0.192;MaterialA.blue=0.192;MaterialD.red=0.508;MaterialD.green=0.508;MaterialD.blue=0.508;MaterialS.red=0.508;MaterialS.green=0.508;MaterialS.blue=0.508;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk5=!Chk5;}else{Chk5=!Chk5;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck6()//绿宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk6){n=3;MaterialA.red=0.022;MaterialA.green=0.175;MaterialA.blue=0.023;MaterialD.red=0.076;MaterialD.green=0.614;MaterialD.blue=0.075;MaterialS.red=0.633;MaterialS.green=0.728;MaterialS.blue=0.633;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk6=!Chk6;}else{Chk6=!Chk6;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck7()//红宝石{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk7){n=3;MaterialA.red=0.175;MaterialA.green=0.012;MaterialA.blue=0.012;MaterialD.red=0.614;MaterialD.green=0.041;MaterialD.blue=0.041;MaterialS.red=0.728;MaterialS.green=0.527;MaterialS.blue=0.527;LightA.red=1.0f;LightA.green=1.0f;LightA.blue=1.0f;LightD.red=1.0f;LightD.green=1.0f;LightD.blue=1.0f;LightS.red=1.0-LightA.red*MaterialA.red-LightD.red*MaterialD.red;//光源颜色LightS.green=1.0-LightA.green*MaterialA.green-LightD.green*MaterialD.green;LightS.blue=1.0-LightA.blue*MaterialA.blue-LightD.blue*MaterialD.blue;Chk7=!Chk7;}else{Chk7=!Chk7;}Invalidate(false);UpdateData(false);}void CTestView::OnCheck8()//星球{// TODO: Add your control notification handler code hereUpdateData(true);if(!Chk8){n=4;MaterialA.red=0.2f;MaterialA.green=0.2f;MaterialA.blue=0.2f;MaterialD.red=0.8f;MaterialD.green=0.8f;MaterialD.blue=0.8f;MaterialS.red=1.0f;MaterialS.green=1.0f;MaterialS.blue=1.0f;LightA.red=1.0f;LightA.green=0.0f;LightA.blue=0.0f;。

相关主题