实验六 背向面消隐算法

1.实验目的:

了解背向面消隐的基本原理,利用VC实现三棱锥的消隐处理。

2.实验内容:

(1) 阅读教材P139页了解背向面消隐的基本原理;

(2) 阅读教材P194页了解矢量的点积与叉积;

(3) 运行示范代码,了解背向面消隐的实现。

3.实验代码:

完整代码下载:/Files/opengl/BackfaceCull.rar

核心代码如下:

void CBackfaceCullView::OnDraw(CDC* pDC)

{

CBackfaceCullDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

// TODO: add draw code for native data here

CRect rect;

GetClientRect(&rect);

pDC->SetViewportOrg(rect.Width()/2, rect.Height()/2);

mT.p[3][0] = lx; mT.p[3][1] = ly;mT.p[3][2] = lz;

mRx.p[1][1] = cos(alpha); mRx.p[2][1] = -sin(alpha);mRx.p[1][2] = sin(alpha); mRx.p[2][2] = cos(alpha);

mRy.p[0][0] = cos(phi); mRy.p[0][2] = -sin(phi); mRy.p[2][0] = sin(phi); mRy.p[2][2] = cos(phi);

mP.p[2][2] = 0;

//mP.p[2][3] = -1/d;

//mP.p[2][3] = 0;

mTemp = Multiply(mT, mRy);

mTemp = Multiply(mTemp, mRx);

mA = Multiply(mTemp, mP);

PyramidProject();

DrawPyramid(pDC);

}

void CBackfaceCullView::DrawPyramid(CDC* pDC)

{

int ptIdx[3];

for(int face=0;face<4;face++)

{

int num =fInfo[face].num;//面的总顶点数

for(int i=0;i<num;i++)//循环

{

ptIdx[i] = GetPtIdx(fInfo[face], i);//面的顶点号

}

bool bDraw = true;

if(m_bHide)

{

//计算面的外法向量

/*

| i j k |

|x2-x1 y2-y1 z2-z1 |

|x3-x2 y3-y2 z3-z2 |

*/

double x1 = m_tmpPt[ptIdx[0]].x;

double y1 = m_tmpPt[ptIdx[0]].y;

double z1 = m_tmpPt[ptIdx[0]].z;

double x2 = m_tmpPt[ptIdx[1]].x;

double y2 = m_tmpPt[ptIdx[1]].y;

double z2 = m_tmpPt[ptIdx[1]].z;

double x3 = m_tmpPt[ptIdx[2]].x;

double y3 = m_tmpPt[ptIdx[2]].y;

double z3 = m_tmpPt[ptIdx[2]].z;

double xn,yn,zn,vn;

xn = (y2 - y1)*(z3-z2) - (y3-y2)*(z2-z1);

yn = -(x2-x1)*(z3-z2) + (x3-x2)*(z2-z1);

zn = (x2-x1)*(y3-y2) - (x3-x2)*(y2-y1); //计算每个面的法矢

vn = sqrt(xn*xn + yn*yn + zn*zn);

xn = xn/vn; yn = yn/vn; zn = zn/vn; //视点方向在(0,0,-1)处

if(zn < 0.0) //视线方向与Z轴同向,当法矢的Z方向分量大于0时,与实现方向成小于90度的角,面可见

{

bDraw = false;

}

}

if(bDraw)

{

for(int j=0; j<3; j++)

{

int idx0 = ptIdx[j];

int idx1 = ((j== 2) ? ptIdx[0]:ptIdx[j+1]);

pDC->MoveTo(m_Pt2d[idx0].x, m_Pt2d[idx0].y);

pDC->LineTo(m_Pt2d[idx1].x, m_Pt2d[idx1].y);

}

}

}

}

4.代码说明:

(1)ReadPoint:定义三棱锥的4个顶点,每个顶点用三维坐标表示;

(2)ReadFace:定义三棱锥的4个面的顶点信息,顶点顺序为逆时针以保证该面的法线向外;

(3)对每个面,读出三个顶点,使用(V2-V1)╳(V3-V2)计算外法向量N;

(4)采用正面投影显示三棱锥,即z’=0;视线方向向量S为(0,0,-1);

(5)未消隐处理下,不计算视向量S与法向量N的点积,直接绘制;

(6)消隐处理下,计算视向量S与法向量N的点积为-zn,如果-zn>0即zn<0为背向面,不绘制面;否则绘制;

(7)设置键盘的上下左右键用于调整三棱锥的显示角度;

(8)三棱锥示意图:

clip_image002[9]

原文地址:https://www.cnblogs.com/opengl/p/2450468.html