⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mgcgprendererclip.cpp

📁 《3D游戏引擎设计》的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#include "MgcGPRenderer.h"

//---------------------------------------------------------------------------
bool MgcGPRenderer::Clip ()
{
    // Clip against each clipping plane.  Camera will eventually maintain
    // an array of clipping planes (standard frustum and portal planes) and
    // will have the ability to "disable" the plane based on object-level
    // culling.  Portal planes should be clipped first as they provide a
    // higher probability of actually culling triangles compared to that for
    // near and far planes.
    //
    // Return value of 'true' indicates trimesh is completely culled.

    if ( ClipNear() )
        return true;

    if ( ClipFar() )
        return true;

    if ( ClipLeft() )
        return true;

    if ( ClipRight() )
        return true;

    if ( ClipTop() )
        return true;

    if ( ClipBottom() )
        return true;

    return false;
}
//---------------------------------------------------------------------------
bool MgcGPRenderer::ClipTriMesh ()
{
    unsigned int uiE, uiT;
    unsigned int uiOldNumEdges = m_kMesh.m_uiEdgesUsed;

    // clip the visible edges
    for (uiE = 0; uiE < uiOldNumEdges; uiE++)
    {
        if ( m_kMesh.m_abEdgeVisible[uiE] )
        {
            unsigned int uiV0 = m_kMesh.Edge(uiE).Vertex(0);
            unsigned int uiV1 = m_kMesh.Edge(uiE).Vertex(1);
            MgcReal fD0 = m_kMesh.m_afDistance[uiV0];
            MgcReal fD1 = m_kMesh.m_afDistance[uiV1];
            
            if ( fD0*fD1 < 0.0 )
            {
                MgcReal fParam = fD0/(fD0-fD1);

                // add new vertex
                unsigned int uiNV = m_kMesh.AddVertex();
                m_kMesh.m_auiClipVertex[uiE] = uiNV;
                m_kMesh.m_afClipParam[uiE] = fParam;
                
                // clip only the geometry
                MgcVector3& rkP0 = m_kMesh.Vertex(uiV0);
                MgcVector3& rkP1 = m_kMesh.Vertex(uiV1);
                m_kMesh.Vertex(uiNV) = rkP0 + fParam*(rkP1 - rkP0);

                // add new edge and cull old vertex
                unsigned int uiNE = m_kMesh.AddEdge();
                MgcGPTriMesh::EdgeRecord& rkNE = m_kMesh.Edge(uiNE);
                rkNE.Vertex(0) = uiNV;
                m_kMesh.m_abEdgeVisible[uiNE] = true;
                rkNE.Vertex(1) = ( fD1 > 0.0 ? uiV1 : uiV0 );

                // Use old triangle indices.  These fields will
                // be updated later when the triangles are split.
                rkNE.Triangle(0) = m_kMesh.Edge(uiE).Triangle(0);
                rkNE.Triangle(1) = m_kMesh.Edge(uiE).Triangle(1);

                // save old and new edge info for clipped vertex
                m_kMesh.m_auiOldEdge[uiNV] = uiE;
                m_kMesh.m_auiNewEdge[uiNV] = uiNE;

                // cull old edge
                m_kMesh.m_abEdgeVisible[uiE] = false;
            }
        }
    }

    // process all the newly added edges from clipping (update mesh)
    unsigned int uiOldNumTriangles = m_kMesh.m_uiTrianglesUsed;
    unsigned int uiNewNumEdges = m_kMesh.m_uiEdgesUsed;

    for (uiE = uiOldNumEdges; uiE < uiNewNumEdges; uiE++)
    {
        // clipped edge is m_kMesh.Edge(uiE)
        for (int i = 0; i < 2; i++)
        {
            // get adjacent triangle
            uiT = m_kMesh.Edge(uiE).Triangle(i);
            assert( uiT == MgcGPTriMesh::INVALID_INDEX ||
                    uiT < m_kMesh.m_uiTrianglesUsed );
            if ( uiT == MgcGPTriMesh::INVALID_INDEX
            ||   uiT >= uiOldNumTriangles
            ||   !m_kMesh.m_abTriangleVisible[uiT] )
            {
                continue;
            }

            MgcGPTriMesh::TriangleRecord& rkOldTri = m_kMesh.Triangle(uiT);

            // Inverse table look up where m_kMesh.Edge(uiE).Vertex(0) is
            // the index of the clipped vertex for the old edge shared between
            // T0 and T1.
            unsigned int uiClipV0 = m_kMesh.Edge(uiE).Vertex(0);
            assert( uiClipV0 < m_kMesh.m_uiVerticesUsed );
            unsigned int uiSE = m_kMesh.m_auiOldEdge[uiClipV0];
            assert( uiSE < m_kMesh.m_uiEdgesUsed );
            MgcGPTriMesh::EdgeRecord& rkSE = m_kMesh.Edge(uiSE);
            
            int iV0, iV1, iV2, iE0, iE1, iE2;
            
            iE0 = rkOldTri.GetEdgeIndex(uiSE);
            assert( iE0 != -1 );
            
            iV0 = rkOldTri.GetVertexIndex(m_kMesh.Edge(uiE).Vertex(1));
            assert( iV0 != -1 );
            
            if ( rkSE.Vertex(0) == m_kMesh.Edge(uiE).Vertex(1) )
                iV1 = rkOldTri.GetVertexIndex(rkSE.Vertex(1));
            else
                iV1 = rkOldTri.GetVertexIndex(rkSE.Vertex(0));
            assert( iV1 != -1 && iV1 != iV0 );
            
            if ( iV1 == ((iV0+1)%3) )
            {
                iV2 = (iV1+1)%3;
                iE1 = (iE0+1)%3;
                iE2 = (iE1+1)%3;
            }
            else
            {
                iV2 = (iV1+2)%3;
                iE1 = (iE0+2)%3;
                iE2 = (iE1+2)%3;
            }

            // finally, split the triangle
            unsigned int uiV0 = rkOldTri.Vertex(iV0);
            unsigned int uiV1 = rkOldTri.Vertex(iV1);
            unsigned int uiV2 = rkOldTri.Vertex(iV2);
            unsigned int uiE0 = rkOldTri.Edge(iE0);
            unsigned int uiE1 = rkOldTri.Edge(iE1);
            unsigned int uiE2 = rkOldTri.Edge(iE2);

            assert( uiV0 < m_kMesh.m_uiVerticesUsed );
            assert( uiV1 < m_kMesh.m_uiVerticesUsed );
            assert( uiV2 < m_kMesh.m_uiVerticesUsed );
            assert( uiE0 < m_kMesh.m_uiEdgesUsed );
            assert( uiE1 < m_kMesh.m_uiEdgesUsed );
            assert( uiE2 < m_kMesh.m_uiEdgesUsed );

            unsigned int uiNE, uiNT, uiNE0, uiNE1, uiNT0, uiNT1;
            unsigned int uiClipV1, uiClipV2, uiAE;

            if ( m_kMesh.m_auiClipVertex[uiE2] != MgcGPTriMesh::INVALID_INDEX )
            {
                // edge uiE2 was clipped

                // add edge
                uiNE = m_kMesh.AddEdge();
                MgcGPTriMesh::EdgeRecord& rkNE = m_kMesh.Edge(uiNE);

                // add triangle
                uiNT = m_kMesh.AddTriangle();
                MgcGPTriMesh::TriangleRecord& rkNT = m_kMesh.Triangle(uiNT);

                // update fields
                uiClipV2 = m_kMesh.m_auiClipVertex[uiE2];
                assert( uiClipV2 < m_kMesh.m_uiVerticesUsed );
                uiAE = m_kMesh.m_auiNewEdge[uiClipV2];
                assert( uiAE < m_kMesh.m_uiEdgesUsed );
                rkNE.Vertex(0) = uiClipV0;
                rkNE.Vertex(1) = uiClipV2;
                rkNE.Triangle(0) = uiNT;
                rkNE.Triangle(1) = MgcGPTriMesh::INVALID_INDEX;
                rkNT.Vertex(0) = uiV0;
                rkNT.Vertex(1) = uiClipV0;
                rkNT.Vertex(2) = uiClipV2;
                rkNT.Edge(0) = uiE;
                rkNT.Edge(1) = uiNE;
                rkNT.Edge(2) = uiAE;

                m_kMesh.Edge(uiE).Triangle(i) = uiNT;

                MgcGPTriMesh::EdgeRecord& rkAE = m_kMesh.Edge(uiAE);
                if ( rkAE.Triangle(0) == uiT )
                    rkAE.Triangle(0) = uiNT;
                else
                    rkAE.Triangle(1) = uiNT;

                // cull old edge
                m_kMesh.m_abEdgeVisible[uiE2] = false;
            }
            else if ( m_kMesh.m_auiClipVertex[uiE1] !=
                      MgcGPTriMesh::INVALID_INDEX )
            {
                // edge uiE1 was clipped

                // add edges
                uiNE0 = m_kMesh.AddEdge();
                uiNE1 = m_kMesh.AddEdge();
                MgcGPTriMesh::EdgeRecord& rkNE0 = m_kMesh.Edge(uiNE0);
                MgcGPTriMesh::EdgeRecord& rkNE1 = m_kMesh.Edge(uiNE1);

                // add triangles
                uiNT0 = m_kMesh.AddTriangle();
                uiNT1 = m_kMesh.AddTriangle();
                MgcGPTriMesh::TriangleRecord& rkNT0 = m_kMesh.Triangle(uiNT0);
                MgcGPTriMesh::TriangleRecord& rkNT1 = m_kMesh.Triangle(uiNT1);

                // update fields
                uiClipV1 = m_kMesh.m_auiClipVertex[uiE1];
                assert( uiClipV1 < m_kMesh.m_uiVerticesUsed );
                uiAE = m_kMesh.m_auiNewEdge[uiClipV1];
                assert( uiAE < m_kMesh.m_uiEdgesUsed );
                rkNE0.Vertex(0) = uiClipV0;
                rkNE0.Vertex(1) = uiV2;
                rkNE0.Triangle(0) = uiNT0;
                rkNE0.Triangle(1) = uiNT1;
                rkNE1.Vertex(0) = uiClipV0;
                rkNE1.Vertex(1) = uiClipV1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -