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

📄 wmlintrutilitybox3.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// 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 "WmlIntrUtilityBox3.h"
#include "WmlIntrUtilityTri3.h"
#include "WmlIntrUtilityLin3.h"
using namespace Wml;

//----------------------------------------------------------------------------
template <class Real>
void Wml::BoxProjection (const Vector3<Real>& rkAxis,
    const Box3<Real>& rkBox, Real& rfMin, Real& rfMax)
{
    Real fOrigin = rkAxis.Dot(rkBox.Center());
    Real fMaximumExtent =
        Math<Real>::FAbs(rkBox.Extent(0)*rkAxis.Dot(rkBox.Axis(0))) +
        Math<Real>::FAbs(rkBox.Extent(1)*rkAxis.Dot(rkBox.Axis(1))) +
        Math<Real>::FAbs(rkBox.Extent(2)*rkAxis.Dot(rkBox.Axis(2)));

    rfMin = fOrigin - fMaximumExtent;
    rfMax = fOrigin + fMaximumExtent;
}
//----------------------------------------------------------------------------
template <class Real>
void Wml::GetBoxConfiguration (const Vector3<Real>& rkAxis, 
    const Box3<Real>& rkBox, ContactConfig<Real>& rkConfig)
{
    // Description of coordinate ordering scheme for ContactConfig.m_aiIndex.
    //
    // Vertex number (up/down) vs. sign of extent (only matters in mapping
    // back)
    //   012
    // 0 ---
    // 1 +--
    // 2 -+-
    // 3 ++-
    // 4 --+
    // 5 +-+
    // 6 -++
    // 7 +++
    //
    // When it returns an ordering in the ContactConfig, it is also
    // guarenteed to be in-order (if 4 vertices, then they are guarunteed in
    // an order that will create a box, e.g. 0,1,3,2).
    //
    // assert: akAxis is an array containing unit length vectors

    Real afAxis[3] =
    {
        rkAxis.Dot(rkBox.Axis(0)),
        rkAxis.Dot(rkBox.Axis(1)),
        rkAxis.Dot(rkBox.Axis(2))
    };

    Real afAAxis[3] =
    {
        Math<Real>::FAbs(afAxis[0]),
        Math<Real>::FAbs(afAxis[1]),
        Math<Real>::FAbs(afAxis[2])
    };

    Real fMaxProjectedExtent;

    if ( afAAxis[0] < Math<Real>::EPSILON )
    {
        if ( afAAxis[1] < Math<Real>::EPSILON )
        {
            // face-face
            rkConfig.m_kMap = m44;

            fMaxProjectedExtent = afAAxis[2]*rkBox.Extent(2);

            // faces have normals along axis[2]
            if ( afAxis[2] > (Real)0.0 )
            {       
                rkConfig.m_aiIndex[0] = 0;
                rkConfig.m_aiIndex[1] = 1;
                rkConfig.m_aiIndex[2] = 3;
                rkConfig.m_aiIndex[3] = 2;

                rkConfig.m_aiIndex[4] = 6;
                rkConfig.m_aiIndex[5] = 7;
                rkConfig.m_aiIndex[6] = 5;
                rkConfig.m_aiIndex[7] = 4;
            }
            else
            {
                rkConfig.m_aiIndex[0] = 6;
                rkConfig.m_aiIndex[1] = 7;
                rkConfig.m_aiIndex[2] = 5;
                rkConfig.m_aiIndex[3] = 4;

                rkConfig.m_aiIndex[4] = 0;
                rkConfig.m_aiIndex[5] = 1;
                rkConfig.m_aiIndex[6] = 3;
                rkConfig.m_aiIndex[7] = 2;
            }
        }
        else if ( afAAxis[2] < Math<Real>::EPSILON )
        {
            // face-face
            rkConfig.m_kMap = m44;

            fMaxProjectedExtent = afAAxis[1]*rkBox.Extent(1);

            // faces have normals along axis[1]
            if ( afAxis[1] > (Real)0.0 ) 
            {
                rkConfig.m_aiIndex[0] = 4;
                rkConfig.m_aiIndex[1] = 5;
                rkConfig.m_aiIndex[2] = 1;
                rkConfig.m_aiIndex[3] = 0;

                rkConfig.m_aiIndex[4] = 2;
                rkConfig.m_aiIndex[5] = 3;
                rkConfig.m_aiIndex[6] = 7;
                rkConfig.m_aiIndex[7] = 6;
            }
            else
            {
                rkConfig.m_aiIndex[0] = 2;
                rkConfig.m_aiIndex[1] = 3;
                rkConfig.m_aiIndex[2] = 7;
                rkConfig.m_aiIndex[3] = 6;

                rkConfig.m_aiIndex[4] = 4;
                rkConfig.m_aiIndex[5] = 5;
                rkConfig.m_aiIndex[6] = 1;
                rkConfig.m_aiIndex[7] = 0;
            }
        }
        else // only afAxis[0] is equal to 0
        {
            // seg-seg
            rkConfig.m_kMap = m2_2;

            fMaxProjectedExtent = afAAxis[1]*rkBox.Extent(1) +
                afAAxis[2]*rkBox.Extent(2);

            // axis 0 is perpendicular to rkAxis
            if ( afAxis[1] > (Real)0.0 )
            {
                if ( afAxis[2] > (Real)0.0 ) 
                {
                    rkConfig.m_aiIndex[0] = 0;
                    rkConfig.m_aiIndex[1] = 1;

                    rkConfig.m_aiIndex[6] = 6;
                    rkConfig.m_aiIndex[7] = 7;
                }
                else 
                {
                    rkConfig.m_aiIndex[0] = 4;
                    rkConfig.m_aiIndex[1] = 5;

                    rkConfig.m_aiIndex[6] = 2;
                    rkConfig.m_aiIndex[7] = 3;
                }
            }
            else // afAxis[1] < 0
            {
                if ( afAxis[2] > (Real)0.0 )
                {
                    rkConfig.m_aiIndex[0] = 2;
                    rkConfig.m_aiIndex[1] = 3;

                    rkConfig.m_aiIndex[6] = 4;
                    rkConfig.m_aiIndex[7] = 5;
                }
                else
                {
                    rkConfig.m_aiIndex[0] = 6;
                    rkConfig.m_aiIndex[1] = 7;

                    rkConfig.m_aiIndex[6] = 0;
                    rkConfig.m_aiIndex[7] = 1;
                }
            }
        }
    }
    else if ( afAAxis[1] < Math<Real>::EPSILON )
    {
        if ( afAAxis[2] < Math<Real>::EPSILON )
        {
            // face-face
            rkConfig.m_kMap = m44;

            fMaxProjectedExtent = afAAxis[0]*rkBox.Extent(0);

            // faces have normals along axis[0]
            if ( afAxis[0] > (Real)0.0 )
            {
                rkConfig.m_aiIndex[0] = 0;
                rkConfig.m_aiIndex[1] = 2;
                rkConfig.m_aiIndex[2] = 6;
                rkConfig.m_aiIndex[3] = 4;

                rkConfig.m_aiIndex[4] = 5;
                rkConfig.m_aiIndex[5] = 7;
                rkConfig.m_aiIndex[6] = 3;
                rkConfig.m_aiIndex[7] = 1;
            }
            else
            {
                rkConfig.m_aiIndex[4] = 0;
                rkConfig.m_aiIndex[5] = 2;
                rkConfig.m_aiIndex[6] = 6;
                rkConfig.m_aiIndex[7] = 4;

                rkConfig.m_aiIndex[0] = 5;
                rkConfig.m_aiIndex[1] = 7;
                rkConfig.m_aiIndex[2] = 3;
                rkConfig.m_aiIndex[3] = 1;
            }

        }
        else // only afAxis[1] is equal to 0
        {
            // seg-seg
            rkConfig.m_kMap = m2_2;

            fMaxProjectedExtent = afAAxis[0]*rkBox.Extent(0) + 
                afAAxis[2]*rkBox.Extent(2);

            // axis 1 is perpendicular to rkAxis
            if ( afAxis[0] > (Real)0.0 )
            {
                if ( afAxis[2] > (Real)0.0 ) 
                {
                    rkConfig.m_aiIndex[0] = 0;
                    rkConfig.m_aiIndex[1] = 2;

                    rkConfig.m_aiIndex[6] = 5;
                    rkConfig.m_aiIndex[7] = 7;
                }
                else 
                {
                    rkConfig.m_aiIndex[0] = 4;
                    rkConfig.m_aiIndex[1] = 6;

                    rkConfig.m_aiIndex[6] = 1;
                    rkConfig.m_aiIndex[7] = 3;
                }
            }
            else // afAxis[0] < 0
            {
                if ( afAxis[2] > (Real)0.0 )
                {
                    rkConfig.m_aiIndex[0] = 1;
                    rkConfig.m_aiIndex[1] = 3;

                    rkConfig.m_aiIndex[6] = 4;
                    rkConfig.m_aiIndex[7] = 6;
                }
                else
                {
                    rkConfig.m_aiIndex[0] = 5;
                    rkConfig.m_aiIndex[1] = 7;

                    rkConfig.m_aiIndex[6] = 0;
                    rkConfig.m_aiIndex[7] = 2;
                }
            }
        }
    }
    
    else if ( afAAxis[2] < Math<Real>::EPSILON ) // only axis2 less than zero
    {
        // seg-seg
        rkConfig.m_kMap = m2_2;

        fMaxProjectedExtent = afAAxis[0]*rkBox.Extent(0) +
            afAAxis[1]*rkBox.Extent(1);

        // axis 2 is perpendicular to rkAxis
        if ( afAxis[0] > (Real)0.0 )
        {
            if ( afAxis[1] > (Real)0.0 ) 
            {
                rkConfig.m_aiIndex[0] = 0;
                rkConfig.m_aiIndex[1] = 4;

                rkConfig.m_aiIndex[6] = 3;
                rkConfig.m_aiIndex[7] = 7;
            }
            else 
            {
                rkConfig.m_aiIndex[0] = 2;
                rkConfig.m_aiIndex[1] = 6;

                rkConfig.m_aiIndex[6] = 1;
                rkConfig.m_aiIndex[7] = 5;
            }
        }
        else // afAxis[0] < 0
        {
            if ( afAxis[1] > (Real)0.0 )
            {
                rkConfig.m_aiIndex[0] = 1;
                rkConfig.m_aiIndex[1] = 5;

                rkConfig.m_aiIndex[6] = 2;
                rkConfig.m_aiIndex[7] = 6;
            }
            else
            {
                rkConfig.m_aiIndex[0] = 3;
                rkConfig.m_aiIndex[1] = 7;

                rkConfig.m_aiIndex[6] = 0;
                rkConfig.m_aiIndex[7] = 4;
            }
        }
    }
  
    else // no axis is equal to zero
    {
        // point-point (unique maximal and minimal vertex)
        rkConfig.m_kMap = m1_1;

        fMaxProjectedExtent = afAAxis[0]*rkBox.Extent(0) +
            afAAxis[1]*rkBox.Extent(1) + afAAxis[2]*rkBox.Extent(2);

        // only these two vertices matter, the rest are irrelevant
        rkConfig.m_aiIndex[0] = 
            ( afAxis[0] > (Real)0.0 ? 0 : 1 ) + 
            ( afAxis[1] > (Real)0.0 ? 0 : 2 ) + 
            ( afAxis[2] > (Real)0.0 ? 0 : 4 );
        // by ordering the vertices this way, opposite corners add up to 7
        rkConfig.m_aiIndex[7] = 7 - rkConfig.m_aiIndex[0];
    }

    // Find projections onto line
    Real fOrigin = rkAxis.Dot(rkBox.Center());
    rkConfig.m_fMin = fOrigin - fMaxProjectedExtent;
    rkConfig.m_fMax = fOrigin + fMaxProjectedExtent;
}
//----------------------------------------------------------------------------
template <class Real>
void Wml::FindContactSetCoplanarLineRect (const Vector3<Real> akSeg[2],
    const Vector3<Real> akFace[4], int& riQuantity, Vector3<Real>* akP)
{
    // The potential intersection is initialized to the line segment and then
    // clipped against the four sides of the rect

    riQuantity = 2;
    memcpy(akP,akSeg,2*sizeof(Vector3<Real>));

    for (int i0 = 3, i1 = 0; i1 < 4; i0 = i1++)
    {
        Vector3<Real> kNormal = akFace[i1] - akFace[i0];
        Real fConstant = kNormal.Dot(akFace[i0]);
        ClipConvexPolygonAgainstPlane(kNormal,fConstant,riQuantity,akP);
    }
}
//----------------------------------------------------------------------------
template <class Real>
Vector3<Real> Wml::GetPoint (int iIndex, const Box3<Real>& rkBox)
{
    Vector3<Real> kPoint = rkBox.Center();

    if ( iIndex & 4 )
        kPoint += rkBox.Extent(2)*rkBox.Axis(2);
    else
        kPoint -= rkBox.Extent(2)*rkBox.Axis(2);

    if ( iIndex & 2 )
        kPoint += rkBox.Extent(1)*rkBox.Axis(1);
    else
        kPoint -= rkBox.Extent(1)*rkBox.Axis(1);

    if ( iIndex & 1 )
        kPoint += rkBox.Extent(0)*rkBox.Axis(0);
    else
        kPoint -= rkBox.Extent(0)*rkBox.Axis(0);

    return kPoint;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template WML_ITEM void BoxProjection<float> (const Vector3<float>&,
    const Box3<float>&, float&, float&);
template WML_ITEM void GetBoxConfiguration<float> (
    const Vector3<float>&, const Box3<float>&, ContactConfig<float>&);
template WML_ITEM void FindContactSetCoplanarLineRect<float> (
    const Vector3<float>[2], const Vector3<float>[4], int&,
    Vector3<float>*);
template WML_ITEM Vector3<float> GetPoint<float> (int,
    const Box3<float>&);

template WML_ITEM void BoxProjection<double> (const Vector3<double>&,
    const Box3<double>&, double&, double&);
template WML_ITEM void GetBoxConfiguration<double> (
    const Vector3<double>&, const Box3<double>&, ContactConfig<double>&);
template WML_ITEM void FindContactSetCoplanarLineRect<double> (
    const Vector3<double>[2], const Vector3<double>[4], int&,
    Vector3<double>*);
template WML_ITEM Vector3<double> GetPoint<double> (int,
    const Box3<double>&);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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