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

📄 wmlintrlin3tri3.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 "WmlIntrLin3Tri3.h"
#include "WmlDistLin3Tri3.h"
#include "WmlIntrUtilityLin3.h"
#include "WmlIntrUtilityTri3.h"
using namespace Wml;

//----------------------------------------------------------------------------
// stationary objects
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (const Segment3<Real>& rkSegment,
    const Triangle3<Real>& rkTriangle)
{
    return SqrDistance(rkSegment,rkTriangle) <= Math<Real>::EPSILON;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (const Ray3<Real>& rkRay,
    const Triangle3<Real>& rkTriangle)
{
    return SqrDistance(rkRay,rkTriangle) <= Math<Real>::EPSILON;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (const Line3<Real>& rkLine,
    const Triangle3<Real>& rkTriangle)
{
    return SqrDistance(rkLine,rkTriangle) <= Math<Real>::EPSILON;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (const Segment3<Real>& rkSegment,
    const Triangle3<Real>& rkTriangle, Vector3<Real>& rkPoint)
{
    Real fSegP;
    if ( SqrDistance(rkSegment,rkTriangle,&fSegP) <= Math<Real>::EPSILON )
    {
        rkPoint = rkSegment.Origin() + fSegP*rkSegment.Direction();
        return true;
    }
    return false;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (const Ray3<Real>& rkRay,
    const Triangle3<Real>& rkTriangle, Vector3<Real>& rkPoint)
{
    Real fRayP;
    if ( SqrDistance(rkRay,rkTriangle,&fRayP) <= Math<Real>::EPSILON )
    {
        rkPoint = rkRay.Origin() + fRayP*rkRay.Direction();
        return true;
    }
    return false;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (const Line3<Real>& rkLine,
    const Triangle3<Real>& rkTriangle, Vector3<Real>& rkPoint)
{
    Real fLinP;
    if ( SqrDistance(rkLine,rkTriangle,&fLinP) <= Math<Real>::EPSILON )
    {
        rkPoint = rkLine.Origin() + fLinP*rkLine.Direction();
        return true;
    }
    return false;
}
//----------------------------------------------------------------------------
// moving objects
//----------------------------------------------------------------------------
template <class Real>
static bool SegTriAxisTest (const Vector3<Real>& rkVel,
    const Vector3<Real>& rkAxis, const Vector3<Real> akU[2],
    const Vector3<Real> akV[3], Real& rfTFirst, Real& rfTLast,Real fTMax)
{
    Real fUMin, fUMax;
    LineProjection(rkAxis,akU,fUMin,fUMax);

    Real fVMin, fVMax;
    TriProjection(rkAxis,akV,fVMin,fVMax);

    return AxisTest(rkVel,rkAxis,fUMin,fUMax,fVMin,fVMax,rfTFirst,rfTLast,
        fTMax);
}
//----------------------------------------------------------------------------
template <class Real>
static bool SegTriAxisFind (const Vector3<Real>& rkVel, 
    const Vector3<Real>& rkAxis, const Vector3<Real> akU[2], 
    const Vector3<Real> akV[3], Real& rfTFirst, Real& rfTLast, Real fTMax,
    ContactSide& reSide, ContactConfig<Real>& rkTUC,
    ContactConfig<Real>& rkTVC)
{
	ContactConfig<Real> kUC;
    GetLineConfiguration(rkAxis,akU,kUC);

	ContactConfig<Real> kVC;
    GetTriConfiguration(rkAxis,akV,kVC);

    return AxisFind(rkVel,rkAxis,kUC,kVC,reSide,rkTUC,rkTVC,rfTFirst,rfTLast,
        fTMax);
}
//----------------------------------------------------------------------------
template <class Real>
static void FindContactSet (const Vector3<Real> akU[2],
    const Vector3<Real> akV[3], ContactSide eSide,
    const ContactConfig<Real>& rkUC, const ContactConfig<Real>& rkVC,
    const Vector3<Real>& rkVelU, const Vector3<Real>& rkVelV, Real fTime,
    int& riQuantity, Vector3<Real>* akP)
{
    Vector3<Real> akUFinal[2] =
    {
        akU[0] + fTime*rkVelU, 
        akU[1] + fTime*rkVelU
    };

    Vector3<Real> akVFinal[3] =
    {
        akV[0] + fTime*rkVelV,
        akV[1] + fTime*rkVelV,
        akV[2] + fTime*rkVelV
    };

    if ( eSide == LEFT ) // V on left of U
    {
        if ( rkUC.m_kMap == m11 )
        {
            riQuantity = 1;
            akP[0] = akUFinal[rkUC.m_aiIndex[0]];
        }
        else if ( ( rkVC.m_kMap == m111 ) || ( rkVC.m_kMap == m21 ) )
        {
            riQuantity = 1;
            akP[0] = akVFinal[rkVC.m_aiIndex[2]];
        }
        else if ( rkVC.m_kMap == m12 )
        {
            Vector3<Real> kTemp[2];
            kTemp[0] = akVFinal[rkVC.m_aiIndex[1]];
            kTemp[1] = akVFinal[rkVC.m_aiIndex[2]];
            FindContactSetLinLin(akUFinal,kTemp,riQuantity,akP);
        }
        else // U is m2, V is m3
        {
            FindContactSetColinearLineTri(akUFinal,akV,riQuantity,akP);
        }
    }
    else // U on left of V
    {
        if ( rkUC.m_kMap == m11 )
        {
            riQuantity = 1;
            akP[0] = akUFinal[rkUC.m_aiIndex[1]];
        }
        else if ( ( rkVC.m_kMap == m111 ) || ( rkVC.m_kMap == m12 ) )
        {
            riQuantity = 1;
            akP[0] = akVFinal[rkVC.m_aiIndex[0]];
        }
        else if ( rkVC.m_kMap == m21 )
        {
            Vector3<Real> kTemp[2];
            kTemp[0] = akVFinal[rkVC.m_aiIndex[0]];
            kTemp[1] = akVFinal[rkVC.m_aiIndex[1]];
            FindContactSetLinLin(akUFinal,kTemp,riQuantity,akP);
        }
        else // U is m2, V is m3
        {
            FindContactSetColinearLineTri(akUFinal,akVFinal,riQuantity,akP);
        }
    }
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::TestIntersection (const Segment3<Real>& rkSegment,
    const Vector3<Real>& rkSegVelocity, const Triangle3<Real>& rkTriangle,
    const Vector3<Real>& rkTriVelocity, Real& rfTFirst, Real fTMax)
{
    // get end points of segment
    Vector3<Real> akU[2] =
    {
        rkSegment.Origin(),
        rkSegment.Origin() + rkSegment.Direction()
    };

    // get vertices of triangle
    Vector3<Real> akV[3] =
    {
        rkTriangle.Origin(),
        rkTriangle.Origin() + rkTriangle.Edge0(),
        rkTriangle.Origin() + rkTriangle.Edge1()
    };

    // get triangle velocity relative to segment
    Vector3<Real> kVel = rkTriVelocity - rkSegVelocity;

    rfTFirst = (Real)0.0;
    Real fTLast = Math<Real>::MAX_REAL;

    // test tri-normal
    Vector3<Real> kNormV = rkTriangle.Edge0().Cross(rkTriangle.Edge1());
    if ( !SegTriAxisTest(kVel,kNormV,akU,akV,rfTFirst,fTLast,fTMax) )
        return false;

    // Test if the segment is parallel to the triangle, effectively the
    // test:  sin(Angle(NormV,DirU)) > 1-epsilon
    Vector3<Real> kDirU = akU[1] - akU[0];
    Vector3<Real> kNormU = kNormV.Cross(kDirU);
    Real fDirUSqrLen = kDirU.SquaredLength();
    Real fNorUSqrLen = kNormU.SquaredLength();
    Real fNorVSqrLen = kNormV.SquaredLength();
    Real fOmEpsilon = (Real)1.0 - Math<Real>::EPSILON;

    int i0, i1;
    Vector3<Real> kAxis;

    if ( fNorUSqrLen > fOmEpsilon*fNorVSqrLen*fDirUSqrLen )  // parallel
    {
        // test tri-normal cross seg-direction
        if ( !SegTriAxisTest(kVel,kNormU,akU,akV,rfTFirst,fTLast,fTMax) )
            return false;

        // test tri-normal cross tri-edges
        for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
        {
            kAxis = kNormV.Cross(akV[i1]-akV[i0]);
            if ( !SegTriAxisTest(kVel,kAxis,akU,akV,rfTFirst,fTLast,fTMax) )
                return false;
        }
    }
    else  // not parallel
    {
        // test seg-direction cross tri-edges
        for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
        {
            kAxis = kDirU.Cross(akV[i1]-akV[i0]);
            if ( !SegTriAxisTest(kVel,kAxis,akU,akV,rfTFirst,fTLast,fTMax) )
                return false;
        }
    }

    return true;
}
//----------------------------------------------------------------------------
template <class Real>
bool Wml::FindIntersection (const Segment3<Real>& rkSegment,
    const Vector3<Real>& rkSegVelocity,  const Triangle3<Real>& rkTriangle,
    const Vector3<Real>& rkTriVelocity, Real& rfTFirst, Real fTMax,
    int& riQuantity, Vector3<Real> akP[2])
{
    // get end points of segment
    Vector3<Real> akU[2] =
    {
        rkSegment.Origin(),
        rkSegment.Origin() + rkSegment.Direction()
    };

    // get vertices of triangle
    Vector3<Real> akV[3] =
    {
        rkTriangle.Origin(),
        rkTriangle.Origin() + rkTriangle.Edge0(),
        rkTriangle.Origin() + rkTriangle.Edge1()
    };

    // get triangle velocity relative to segment
    Vector3<Real> kVel = rkTriVelocity - rkSegVelocity;

    riQuantity = 0;
    rfTFirst = (Real)0.0;
    Real fTLast = Math<Real>::MAX_REAL;

    // test tri-normal
    Vector3<Real> kNormV = rkTriangle.Edge0().Cross(rkTriangle.Edge1());
    ContactConfig<Real> kUC, kVC;
    ContactSide eSide;
    if ( !SegTriAxisFind(kVel,kNormV,akU,akV,rfTFirst,fTLast,fTMax,eSide,
         kUC,kVC) )
    {
        return false;
    }

    // Test if the segment is parallel to the triangle, effectively the
    // test:  sin(Angle(NormV,DirU)) > 1-epsilon
    Vector3<Real> kDirU = akU[1] - akU[0];
    Vector3<Real> kNormU = kNormV.Cross(kDirU);
    Real fDirUSqrLen = kDirU.SquaredLength();
    Real fNorUSqrLen = kNormU.SquaredLength();
    Real fNorVSqrLen = kNormV.SquaredLength();
    Real fOmEpsilon = (Real)1.0 - Math<Real>::EPSILON;

    int i0, i1;
    Vector3<Real> kAxis;

    if ( fNorUSqrLen > fOmEpsilon*fNorVSqrLen*fDirUSqrLen )  // parallel
    {
        // find tri-normal cross seg-direction
        if ( !SegTriAxisFind(kVel,kNormU,akU,akV,rfTFirst,fTLast,fTMax,eSide,
             kUC,kVC) )
        {
            return false;
        }

        // test tri-normal cross tri-edges
        for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
        {
            kAxis = kNormV.Cross(akV[i1]-akV[i0]);
            if ( !SegTriAxisFind(kVel,kAxis,akU,akV,rfTFirst,fTLast,fTMax,
                 eSide,kUC,kVC) )
            {
                return false;
            }
        }
    } 
    else 
    {
        // test seg-direction cross tri-edges
        for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
        {
            kDirU.Cross(akV[i1]-akV[i0]);
            if ( !SegTriAxisFind(kVel,kAxis,akU,akV,rfTFirst,fTLast,fTMax,
                 eSide,kUC,kVC) )
            {
                return false;
            }
        }
    }

    if ( rfTFirst < (Real)0.0 )
        return false;

    FindContactSet(akU,akV,eSide,kUC,kVC,rkSegVelocity,rkTriVelocity,
        rfTFirst,riQuantity,akP);
    return true;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template WML_ITEM bool TestIntersection<float> (
    const Segment3<float>&, const Triangle3<float>&);
template WML_ITEM bool TestIntersection<float> (
    const Ray3<float>&, const Triangle3<float>&);
template WML_ITEM bool TestIntersection<float> (
    const Line3<float>&, const Triangle3<float>&);
template WML_ITEM bool FindIntersection<float> (
    const Segment3<float>&, const Triangle3<float>&, Vector3<float>&);
template WML_ITEM bool FindIntersection<float> (
    const Ray3<float>&, const Triangle3<float>&, Vector3<float>&);
template WML_ITEM bool FindIntersection<float> (
    const Line3<float>&, const Triangle3<float>&, Vector3<float>&);
template WML_ITEM bool TestIntersection<float> (
    const Segment3<float>&, const Vector3<float>&,
    const Triangle3<float>&, const Vector3<float>&, float&, float);
template WML_ITEM bool FindIntersection<float> (
    const Segment3<float>&, const Vector3<float>&,
    const Triangle3<float>&, const Vector3<float>&, float&, float, int&,
    Vector3<float>[2]);

template WML_ITEM bool TestIntersection<double> (
    const Segment3<double>&, const Triangle3<double>&);
template WML_ITEM bool TestIntersection<double> (
    const Ray3<double>&, const Triangle3<double>&);
template WML_ITEM bool TestIntersection<double> (
    const Line3<double>&, const Triangle3<double>&);
template WML_ITEM bool FindIntersection<double> (
    const Segment3<double>&, const Triangle3<double>&, Vector3<double>&);
template WML_ITEM bool FindIntersection<double> (
    const Ray3<double>&, const Triangle3<double>&, Vector3<double>&);
template WML_ITEM bool FindIntersection<double> (
    const Line3<double>&, const Triangle3<double>&, Vector3<double>&);
template WML_ITEM bool TestIntersection<double> (
    const Segment3<double>&, const Vector3<double>&,
    const Triangle3<double>&, const Vector3<double>&, double&, double);
template WML_ITEM bool FindIntersection<double> (
    const Segment3<double>&, const Vector3<double>&,
    const Triangle3<double>&, const Vector3<double>&, double&, double, int&,
    Vector3<double>[2]);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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