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

📄 wmlbsptree.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Magic Software, Inc.
// http://www.magic-software.com
// http://www.wild-magic.com
// Copyright (c) 2003.  All Rights Reserved
//
// The Wild Magic Library (WML) source code is supplied under the terms of
// the license agreement http://www.magic-software.com/License/WildMagic.pdf
// and may not be copied or disclosed except in accordance with the terms of
// that agreement.

#include "WmlBspTree.h"
using namespace Wml;

WmlImplementRTTI(BspTree,BspNode);
WmlImplementStream(BspTree);

//----------------------------------------------------------------------------
BspTree::BspTree (TriangleList& rkList)
{
    assert( rkList.size() > 0 );
    CreateTree(rkList);
}
//----------------------------------------------------------------------------
BspTree::BspTree ()
{
}
//----------------------------------------------------------------------------
BspTree::Triangle::Triangle ()
{
    memset(m_apkNormal,0,3*sizeof(Vector3f*));
    memset(m_apkColor,0,3*sizeof(ColorRGB*));
    memset(m_apkTexture,0,3*sizeof(Vector2f*));
}
//----------------------------------------------------------------------------
void BspTree::CreateTree (TriangleList& rkList)
{
    // construct plane of first triangle in list
    Triangle* pkTri = rkList.front();
    rkList.pop_front();
    m_kModelPlane = Plane3f(pkTri->m_akVertex[0],pkTri->m_akVertex[1],
        pkTri->m_akVertex[2]);

    // place first triangle on node's coincident list
    TriangleList* pkCoincident = new TriangleList;
    pkCoincident->push_front(pkTri);
    m_pvData = pkCoincident;

    if ( rkList.size() > 0 )
    {
        // split remaining triangles against plane
        TriangleList kPositive, kNegative;
        while ( rkList.size() > 0 )
        {
            pkTri = rkList.front();
            rkList.pop_front();
            SplitTriangle(pkTri,kPositive,kNegative,*pkCoincident);
        }

        // recurse on left child
        if ( kPositive.size() > 0 )
        {
            BspTree* pkLeftChild = new BspTree(kPositive);
            AttachLeftChild(pkLeftChild);
        }

        // recurse on right child
        if ( kNegative.size() > 0 )
        {
            BspTree* pkRightChild = new BspTree(kNegative);
            AttachRightChild(pkRightChild);
        }
    }
    else
    {
        // TO DO.  This node has no children.  Create a TriMesh from the
        // coincident triangles?
    }
}
//----------------------------------------------------------------------------
void BspTree::SplitTriangle (Triangle* pkTri, TriangleList& rkPositive,
    TriangleList& rkNegative, TriangleList& rkCoincident)
{
    // compute signed pseudodistances
    float afDistance[3];
    int i, iPosCount = 0, iNegCount = 0;
    for (i = 0; i < 3; i++)
    {
        afDistance[i] = m_kModelPlane.DistanceTo(pkTri->m_akVertex[i]);
        if ( afDistance[i] > Mathf::EPSILON )
            iPosCount++;
        else if ( afDistance[i] < -Mathf::EPSILON )
            iNegCount--;
        else
            afDistance[i] = 0.0f;
    }

    if ( iPosCount > 0 )
    {
        if ( iNegCount == 0 )
        {
            // triangle is on positive side of plane
            rkPositive.push_front(pkTri);
            return;
        }
    }
    else
    {
        if ( iNegCount > 0 )
        {
            // triangle is on negative side of plane
            rkNegative.push_front(pkTri);
        }
        else
        {
            // triangle is contained in plane
            rkCoincident.push_front(pkTri);
        }
        return;
    }

    // triangle straddles plane and must be split
    if ( afDistance[0]*afDistance[1] < 0.0f )
    {
        ClipTriangle(0,1,2,pkTri,afDistance,rkPositive,rkNegative);
        return;
    }

    if ( afDistance[2]*afDistance[0] < 0.0f )
    {
        ClipTriangle(2,0,1,pkTri,afDistance,rkPositive,rkNegative);
        return;
    }

    if ( afDistance[1]*afDistance[2] < 0.0f )
    {
        ClipTriangle(1,2,0,pkTri,afDistance,rkPositive,rkNegative);
        return;
    }

    // Distances are all nonnegative or all nonpositive.  This should have
    // been caught by ((iPos > 0 && iNeg == 0) || (iPos == 0 && iNeg > 0)),
    // but just in case of numerical round-off errors screwing up the
    // theory...
    assert( false );
}
//----------------------------------------------------------------------------
void BspTree::ClipTriangle (int i0, int i1, int i2, Triangle* pkTri,
    float afDistance[3], TriangleList& rkPositive, TriangleList& rkNegative)
{
    // Warning.  The normal interpolation is a convex combination of the
    // normals that is unitized.  You might want to use SLERP to get a more
    // standard interpolation.

    float fD0 = afDistance[i0];
    float fD1 = afDistance[i1];
    float fD2 = afDistance[i2];
    Vector3f& rkV0 = pkTri->m_akVertex[i0];
    Vector3f& rkV1 = pkTri->m_akVertex[i1];
    Vector3f& rkV2 = pkTri->m_akVertex[i2];

    bool bHasNormals = (pkTri->m_apkNormal[0] != NULL);
    Vector3f* apkN[3];
    if ( bHasNormals )
    {
        apkN[0] = pkTri->m_apkNormal[0];
        apkN[1] = pkTri->m_apkNormal[1];
        apkN[2] = pkTri->m_apkNormal[2];
    }

    bool bHasColors = (pkTri->m_apkColor[0] != NULL);
    ColorRGB* apkC[3];
    if ( bHasColors )
    {
        apkC[0] = pkTri->m_apkColor[0];
        apkC[1] = pkTri->m_apkColor[1];
        apkC[2] = pkTri->m_apkColor[2];
    }

    bool bHasTextures = (pkTri->m_apkTexture[0] != NULL);
    Vector2f* apkT[3];
    if ( bHasTextures )
    {
        apkT[0] = pkTri->m_apkTexture[0];
        apkT[1] = pkTri->m_apkTexture[1];
        apkT[2] = pkTri->m_apkTexture[2];
    }

    // clip edge <I0,I1>
    float fT = fD0/(fD0 - fD1);
    Vector3f kV01 = rkV0 + fT*(rkV1 - rkV0);

    Vector3f kN01;
    if ( bHasNormals )
    {
        // TO DO.  Use slerp instead of convex combination?
        kN01 = *apkN[i0] + fT*(*apkN[i1] - *apkN[i0]);
        kN01.Normalize();
    }

    ColorRGB kC01;
    if ( bHasColors )
        kC01 = *apkC[i0] + fT*(*apkC[i1] - *apkC[i0]);

    Vector2f kT01;
    if ( bHasTextures )
        kT01 = *apkT[i0] + fT*(*apkT[i1] - *apkT[i0]);

    Vector3f kV12, kN12;
    ColorRGB kC12;
    Vector2f kT12;

    if ( fD0 > 0.0f )
    {
        if ( fD2 > 0.0f )
        {
            // clip edge <I1,I2>
            fT = fD1/(fD1 - fD2);
            kV12 = rkV1 + fT*(rkV2 - rkV1);

            if ( bHasNormals )
            {
                kN12 = *apkN[i1] + fT*(*apkN[i2] - *apkN[i1]);
                kN12.Normalize();
            }

            if ( bHasColors )
                kC12 = *apkC[i1] + fT*(*apkC[i2] - *apkC[i1]);

            if ( bHasTextures )

⌨️ 快捷键说明

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