Create HouseTextureMapping
This commit is contained in:
1 parent
9f322bccba
commit
de8a8e8d2b
80 files changed
+4942
No files matched your search
@@ -0,0 +1,389 @@
|
||||
// ZBuffer.cpp: implementation of the CZBuffer class.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Test.h"
|
||||
#include "ZBuffer.h"
|
||||
#include "math.h"
|
||||
#define Round(d) int(floor(d+0.5))
|
||||
#ifdef _DEBUG
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[]=__FILE__;
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
CZBuffer::CZBuffer()
|
||||
{
|
||||
P=NULL;
|
||||
N=NULL;
|
||||
T=NULL;
|
||||
pHeadE=NULL;
|
||||
pCurrentB=NULL;
|
||||
pEdge=NULL;
|
||||
pCurrentE=NULL;
|
||||
pHeadB=NULL;
|
||||
zBuffer=NULL;
|
||||
}
|
||||
|
||||
CZBuffer::~CZBuffer()
|
||||
{
|
||||
for(int i=0;i<Width;i++)
|
||||
{
|
||||
delete[] zBuffer[i];
|
||||
zBuffer[i]=NULL;
|
||||
}
|
||||
if(zBuffer!=NULL)
|
||||
{
|
||||
delete zBuffer;
|
||||
zBuffer=NULL;
|
||||
}
|
||||
ClearMemory();
|
||||
}
|
||||
|
||||
void CZBuffer::SetPoint(CPi3 *p,CVector *n,CT2 *t,int m)
|
||||
{
|
||||
P=new CPi3[m];
|
||||
N=new CVector[m];
|
||||
T=new CT2[m];
|
||||
for(int i=0;i<m;i++)
|
||||
{
|
||||
P[i]=p[i];
|
||||
N[i]=n[i];
|
||||
T[i]=t[i];
|
||||
}
|
||||
PNum=m;
|
||||
}
|
||||
|
||||
void CZBuffer::CreateBucket()//创建桶表
|
||||
{
|
||||
int yMin,yMax;
|
||||
yMin=yMax=P[0].y;
|
||||
for(int i=1;i<PNum;i++)//查找多边形所覆盖的最小和最大扫描线
|
||||
{
|
||||
if(P[i].y<yMin)
|
||||
yMin=P[i].y;//扫描线的最小值
|
||||
if(P[i].y>yMax)
|
||||
yMax=P[i].y;//扫描线的最大值
|
||||
}
|
||||
for(int y=yMin;y<=yMax;y++)
|
||||
{
|
||||
if(yMin==y)//建立桶头结点
|
||||
{
|
||||
pHeadB=new CBucket;//建立桶的头结点
|
||||
pCurrentB=pHeadB;//pCurrentB为CBucket当前结点指针
|
||||
pCurrentB->ScanLine=yMin;
|
||||
pCurrentB->pET=NULL;//没有链接边表
|
||||
pCurrentB->pNext=NULL;
|
||||
}
|
||||
else//其他扫描线
|
||||
{
|
||||
pCurrentB->pNext=new CBucket;//建立桶的其他结点
|
||||
pCurrentB=pCurrentB->pNext;
|
||||
pCurrentB->ScanLine=y;
|
||||
pCurrentB->pET=NULL;
|
||||
pCurrentB->pNext=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CZBuffer::CreateEdge()//创建边表
|
||||
{
|
||||
for(int i=0;i<PNum;i++)
|
||||
{
|
||||
pCurrentB=pHeadB;
|
||||
int j=(i+1)%PNum;//边的第二个顶点,P[i]和P[j]构成边
|
||||
if(P[i].y<P[j].y)//边的终点比起点高
|
||||
{
|
||||
pEdge=new CAET;
|
||||
pEdge->x=P[i].x;//计算ET表的值
|
||||
pEdge->yMax=P[j].y;
|
||||
pEdge->k=(P[j].x-P[i].x)/(P[j].y-P[i].y);//代表1/k
|
||||
pEdge->ps=P[i];//绑定顶点和颜色
|
||||
pEdge->pe=P[j];
|
||||
pEdge->ns=N[i];//绑定法矢量
|
||||
pEdge->ne=N[j];
|
||||
pEdge->ts=T[i];//绑定纹理
|
||||
pEdge->te=T[j];
|
||||
pEdge->pNext=NULL;
|
||||
while(pCurrentB->ScanLine!=P[i].y)//在桶内寻找该边的yMin
|
||||
{
|
||||
pCurrentB=pCurrentB->pNext;//移到yMin所在的桶结点
|
||||
}
|
||||
}
|
||||
if(P[j].y<P[i].y)//边的终点比起点低
|
||||
{
|
||||
pEdge=new CAET;
|
||||
pEdge->x=P[j].x;
|
||||
pEdge->yMax=P[i].y;
|
||||
pEdge->k=(P[i].x-P[j].x)/(P[i].y-P[j].y);
|
||||
pEdge->ps=P[i];
|
||||
pEdge->pe=P[j];
|
||||
pEdge->ns=N[i];
|
||||
pEdge->ne=N[j];
|
||||
pEdge->ts=T[i];
|
||||
pEdge->te=T[j];
|
||||
pEdge->pNext=NULL;
|
||||
while(pCurrentB->ScanLine!=P[j].y)
|
||||
{
|
||||
pCurrentB=pCurrentB->pNext;
|
||||
}
|
||||
}
|
||||
if(int(P[j].y)!=P[i].y)
|
||||
{
|
||||
pCurrentE=pCurrentB->pET;
|
||||
if(pCurrentE==NULL)
|
||||
{
|
||||
pCurrentE=pEdge;
|
||||
pCurrentB->pET=pCurrentE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(pCurrentE->pNext!=NULL)
|
||||
{
|
||||
pCurrentE=pCurrentE->pNext;
|
||||
}
|
||||
pCurrentE->pNext=pEdge;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CZBuffer::Phong(CDC *pDC,CP3 ViewPoint,CLighting *pLight,CMaterial *pMaterial,COLORREF **Image)//填充多边形
|
||||
{
|
||||
double z=0.0;//当前扫描线的z
|
||||
double zStep=0.0;//当前扫描线随着x增长的z步长
|
||||
double A,B,C,D;//平面方程Ax+By+Cz+D=0的系数
|
||||
CVector V01(P[0],P[1]),V02(P[0],P[2]);
|
||||
CVector VN=Cross(V01,V02);
|
||||
A=VN.x;B=VN.y;C=VN.z;
|
||||
D=-A*P[0].x-B*P[0].y-C*P[0].z;
|
||||
zStep=-A/C;//计算直线z增量
|
||||
CAET *pT1,*pT2;
|
||||
pHeadE=NULL;
|
||||
for(pCurrentB=pHeadB;pCurrentB!=NULL;pCurrentB=pCurrentB->pNext)
|
||||
{
|
||||
for(pCurrentE=pCurrentB->pET;pCurrentE!=NULL;pCurrentE=pCurrentE->pNext)
|
||||
{
|
||||
pEdge=new CAET;
|
||||
pEdge->x=pCurrentE->x;
|
||||
pEdge->yMax=pCurrentE->yMax;
|
||||
pEdge->k=pCurrentE->k;
|
||||
pEdge->ps=pCurrentE->ps;
|
||||
pEdge->pe=pCurrentE->pe;
|
||||
pEdge->ns=pCurrentE->ns;
|
||||
pEdge->ne=pCurrentE->ne;
|
||||
pEdge->ts=pCurrentE->ts;
|
||||
pEdge->te=pCurrentE->te;
|
||||
pEdge->pNext=NULL;
|
||||
AddEt(pEdge);
|
||||
}
|
||||
ETOrder();
|
||||
pT1=pHeadE;
|
||||
if(pT1==NULL)
|
||||
return;
|
||||
while(pCurrentB->ScanLine>=pT1->yMax)//下闭上开
|
||||
{
|
||||
CAET * pAETTEmp=pT1;
|
||||
pT1=pT1->pNext;
|
||||
delete pAETTEmp;
|
||||
pHeadE=pT1;
|
||||
if(pHeadE==NULL)
|
||||
return;
|
||||
}
|
||||
if(pT1->pNext!=NULL)
|
||||
{
|
||||
pT2=pT1;
|
||||
pT1=pT2->pNext;
|
||||
}
|
||||
while(pT1!=NULL)
|
||||
{
|
||||
if(pCurrentB->ScanLine>=pT1->yMax)//下闭上开
|
||||
{
|
||||
CAET* pAETTemp =pT1;
|
||||
pT2->pNext=pT1->pNext;
|
||||
pT1=pT2->pNext;
|
||||
delete pAETTemp;
|
||||
}
|
||||
else
|
||||
{
|
||||
pT2=pT1;
|
||||
pT1=pT2->pNext;
|
||||
}
|
||||
}
|
||||
CVector na,nb,nf;//na、nb代表边上任意点的法矢量,nf代表面上任意点的法矢量
|
||||
na=Interpolation(pCurrentB->ScanLine,pHeadE->ps.y,pHeadE->pe.y,pHeadE->ns,pHeadE->ne);
|
||||
nb=Interpolation(pCurrentB->ScanLine,pHeadE->pNext->ps.y,pHeadE->pNext->pe.y,pHeadE->pNext->ns,pHeadE->pNext->ne);
|
||||
CT2 ta,tb,tf;//ta和tb代表边上任意点的纹理,tf代表面上任意点的纹理
|
||||
ta=Interpolation(pCurrentB->ScanLine,pHeadE->ps.y,pHeadE->pe.y,pHeadE->ts,pHeadE->te);
|
||||
tb=Interpolation(pCurrentB->ScanLine,pHeadE->pNext->ps.y,pHeadE->pNext->pe.y,pHeadE->pNext->ts,pHeadE->pNext->te);
|
||||
BOOL bInFlag=FALSE;//区间内外测试标志,初始值为假表示区间外部
|
||||
double xb,xe;//扫描线和有效边相交区间的起点和终点坐标
|
||||
for(pT1=pHeadE;pT1!=NULL;pT1=pT1->pNext)
|
||||
{
|
||||
if(FALSE==bInFlag)
|
||||
{
|
||||
xb=pT1->x;
|
||||
z=-(xb*A+pCurrentB->ScanLine*B+D)/C;//z=-(Ax+By+D)/C
|
||||
bInFlag=TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xe=pT1->x;
|
||||
for(double x=xb;x<xe;x++)//左闭右开
|
||||
{
|
||||
nf=Interpolation(x,xb,xe,na,nb);
|
||||
tf=Interpolation(x,xb,xe,ta,tb);
|
||||
COLORREF clr=Image[Round(tf.v)][Round(tf.u)];
|
||||
CRGB Textureclr=CRGB(GetRValue(clr)/255.0,GetGValue(clr)/255.0,GetBValue(clr)/255.0);
|
||||
// pMaterial->SetDiffuse(Textureclr);//用纹理颜色作为材质的漫反射光反射率
|
||||
//pMaterial->SetAmbient(Textureclr);//用纹理颜色作为材质的环境光反射率
|
||||
CRGB c=Textureclr;//pLight->Lighting(ViewPoint,CP3(Round(x),pCurrentB->ScanLine,z),nf,pMaterial);
|
||||
if(z<=zBuffer[Round(x)+Width/2][pCurrentB->ScanLine+Height/2])//如果新采样点的深度小于原采样点的深度
|
||||
{
|
||||
zBuffer[Round(x)+Width/2][pCurrentB->ScanLine+Height/2]=z;//xy坐标与数组下标保持一致
|
||||
pDC->SetPixelV(Round(x),pCurrentB->ScanLine,RGB(c.red*255,c.green*255,c.blue*255));
|
||||
}
|
||||
z+=zStep;
|
||||
}
|
||||
bInFlag=FALSE;
|
||||
}
|
||||
}
|
||||
for(pT1=pHeadE;pT1!=NULL;pT1=pT1->pNext)//边的连续性
|
||||
pT1->x=pT1->x+pT1->k;
|
||||
}
|
||||
}
|
||||
|
||||
void CZBuffer::AddEt(CAET *pNewEdge)//合并ET表
|
||||
{
|
||||
CAET *pCE;
|
||||
pCE=pHeadE;
|
||||
if(pCE==NULL)
|
||||
{
|
||||
pHeadE=pNewEdge;
|
||||
pCE=pHeadE;
|
||||
}
|
||||
else
|
||||
{
|
||||
while(pCE->pNext!=NULL)
|
||||
{
|
||||
pCE=pCE->pNext;
|
||||
}
|
||||
pCE->pNext=pNewEdge;
|
||||
}
|
||||
}
|
||||
|
||||
void CZBuffer::ETOrder()//边表的冒泡排序算法
|
||||
{
|
||||
CAET *pT1,*pT2;
|
||||
int Count=1;
|
||||
pT1=pHeadE;
|
||||
if(pT1==NULL)
|
||||
return;
|
||||
if(pT1->pNext==NULL)//如果该ET表没有再连ET表
|
||||
return;//桶结点只有一条边,不需要排序
|
||||
while(pT1->pNext!=NULL)//统计边结点的个数
|
||||
{
|
||||
Count++;
|
||||
pT1=pT1->pNext;
|
||||
}
|
||||
for(int i=0;i<Count-1;i++)//冒泡排序
|
||||
{
|
||||
CAET **pPre=&pHeadE;
|
||||
pT1=pHeadE;
|
||||
for(int j=0;j<Count-1-i;j++)
|
||||
{
|
||||
pT2=pT1->pNext;
|
||||
|
||||
if ((pT1->x>pT2->x)||((pT1->x==pT2->x)&&(pT1->k>pT2->k)))
|
||||
{
|
||||
pT1->pNext=pT2->pNext;
|
||||
pT2->pNext=pT1;
|
||||
*pPre=pT2;
|
||||
pPre=&(pT2->pNext);//调整位置为下次遍历准备
|
||||
}
|
||||
else
|
||||
{
|
||||
pPre=&(pT1->pNext);
|
||||
pT1=pT1->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRGB CZBuffer::Interpolation(double t,double t1,double t2,CRGB clr1,CRGB clr2)//颜色线性插值
|
||||
{
|
||||
CRGB color;
|
||||
color=(t-t2)/(t1-t2)*clr1+(t-t1)/(t2-t1)*clr2;
|
||||
return color;
|
||||
}
|
||||
|
||||
CVector CZBuffer::Interpolation(double t,double t1,double t2,CVector vec1,CVector vec2)//矢量线性插值
|
||||
{
|
||||
CVector vector;
|
||||
vector=(t-t2)/(t1-t2)*vec1+(t-t1)/(t2-t1)*vec2;
|
||||
return vector;
|
||||
}
|
||||
|
||||
CT2 CZBuffer::Interpolation(double t,double t1,double t2,CT2 tex1,CT2 tex2)//纹理线性插值
|
||||
{
|
||||
CT2 texture;
|
||||
texture=(t-t2)/(t1-t2)*tex1+(t-t1)/(t2-t1)*tex2;
|
||||
return texture;
|
||||
}
|
||||
|
||||
void CZBuffer::InitDeepBuffer(int Width,int Height,double Depth)//初始化深度缓冲
|
||||
{
|
||||
int i;
|
||||
this->Width=Width,this->Height=Height;
|
||||
zBuffer=new double *[Width];
|
||||
for(int i=0;i<Width;i++)
|
||||
zBuffer[i]=new double[Height];
|
||||
for(i=0;i<Width;i++)//初始化深度缓冲
|
||||
for(int j=0;j<Height;j++)
|
||||
zBuffer[i][j]=Depth;
|
||||
}
|
||||
|
||||
void CZBuffer::ClearMemory()
|
||||
{
|
||||
DeleteAETChain(pHeadE);
|
||||
CBucket *pBucket=pHeadB;
|
||||
while (pBucket !=NULL)//针对每一个桶
|
||||
{
|
||||
CBucket * pBucketTemp = pBucket->pNext;
|
||||
DeleteAETChain(pBucket->pET);
|
||||
delete pBucket;
|
||||
pBucket=pBucketTemp;
|
||||
}
|
||||
pHeadB=NULL;
|
||||
pHeadE=NULL;
|
||||
if(P!=NULL)
|
||||
{
|
||||
delete []P;
|
||||
P=NULL;
|
||||
}
|
||||
if(N!=NULL)
|
||||
{
|
||||
delete []N;
|
||||
N=NULL;
|
||||
}
|
||||
if (T!=NULL)
|
||||
{
|
||||
delete []T;
|
||||
T=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CZBuffer::DeleteAETChain(CAET* pAET)
|
||||
{
|
||||
while (pAET!=NULL)
|
||||
{
|
||||
CAET* pAETTemp=pAET->pNext;
|
||||
delete pAET;
|
||||
pAET=pAETTemp;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user