• 实验六 背向面消隐算法


    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]

  • 相关阅读:
    57. Insert Interval
    287. Find the Duplicate Number
    52. N-Queens II
    51. N-Queens
    151. Reverse Words in a String
    29. Divide Two Integers
    [POJ2104]K-th Number
    [JSOI2008]最大数
    [BZOJ3673&3674]可持久化并查集&加强版
    C++ STL rope介绍----可持久化平衡树
  • 原文地址:https://www.cnblogs.com/opengl/p/2450468.html
Copyright © 2020-2023  润新知