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

📄 wmlnurbscurve2.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 "WmlNURBSCurve2.h"
using namespace Wml;

//----------------------------------------------------------------------------
template <class Real>
NURBSCurve2<Real>::NURBSCurve2 (int iNumCtrlPoints,
    Vector2<Real>* akCtrlPoint, Real* afCtrlWeight, int iDegree, bool bLoop,
    bool bOpen)
    :
    SingleCurve2<Real>(0.0,1.0),
    m_bLoop(bLoop)
{
    assert( iNumCtrlPoints >= 2 );
    assert( 1 <= iDegree && iDegree <= iNumCtrlPoints-1 );

    m_iNumCtrlPoints = iNumCtrlPoints;
    m_iReplicate = ( bLoop ? (bOpen ? 1 : iDegree) : 0 );
    CreateControl(akCtrlPoint,afCtrlWeight);
    m_kBasis.Create(m_iNumCtrlPoints+m_iReplicate,iDegree,bOpen);
}
//----------------------------------------------------------------------------
template <class Real>
NURBSCurve2<Real>::NURBSCurve2 (int iNumCtrlPoints,
    Vector2<Real>* akCtrlPoint, Real* afCtrlWeight, int iDegree, bool bLoop,
    Real* afKnot)
    :
    SingleCurve2<Real>(0.0,1.0),
    m_bLoop(bLoop)
{
    assert( iNumCtrlPoints >= 2 );
    assert( 1 <= iDegree && iDegree <= iNumCtrlPoints-1 );

    m_iNumCtrlPoints = iNumCtrlPoints;
    m_iReplicate = ( bLoop ? 1 : 0 );
    CreateControl(akCtrlPoint,afCtrlWeight);
    m_kBasis.Create(m_iNumCtrlPoints+m_iReplicate,iDegree,afKnot);
}
//----------------------------------------------------------------------------
template <class Real>
NURBSCurve2<Real>::~NURBSCurve2 ()
{
    delete[] m_akCtrlPoint;
    delete[] m_afCtrlWeight;
}
//----------------------------------------------------------------------------
template <class Real>
void NURBSCurve2<Real>::CreateControl (Vector2<Real>* akCtrlPoint,
    Real* afCtrlWeight)
{
    int iNewNumCtrlPoints = m_iNumCtrlPoints + m_iReplicate;
    m_akCtrlPoint = new Vector2<Real>[iNewNumCtrlPoints];
    m_afCtrlWeight = new Real[iNewNumCtrlPoints];
    memcpy(m_akCtrlPoint,akCtrlPoint,m_iNumCtrlPoints*sizeof(Vector2<Real>));
    memcpy(m_afCtrlWeight,afCtrlWeight,m_iNumCtrlPoints*sizeof(Real));
    for (int i = 0; i < m_iReplicate; i++)
    {
        m_akCtrlPoint[m_iNumCtrlPoints+i] = akCtrlPoint[i];
        m_afCtrlWeight[m_iNumCtrlPoints+i] = afCtrlWeight[i];
    }
}
//----------------------------------------------------------------------------
template <class Real>
int NURBSCurve2<Real>::GetNumCtrlPoints () const
{
    return m_iNumCtrlPoints;
}
//----------------------------------------------------------------------------
template <class Real>
int NURBSCurve2<Real>::GetDegree () const
{
    return m_kBasis.GetDegree();
}
//----------------------------------------------------------------------------
template <class Real>
bool NURBSCurve2<Real>::IsOpen () const
{
    return m_kBasis.IsOpen();
}
//----------------------------------------------------------------------------
template <class Real>
bool NURBSCurve2<Real>::IsUniform () const
{
    return m_kBasis.IsUniform();
}
//----------------------------------------------------------------------------
template <class Real>
bool NURBSCurve2<Real>::IsLoop () const
{
    return m_bLoop;
}
//----------------------------------------------------------------------------
template <class Real>
void NURBSCurve2<Real>::SetControlPoint (int i, const Vector2<Real>& rkCtrl)
{
    if ( 0 <= i && i < m_iNumCtrlPoints )
    {
        // set the control point
        m_akCtrlPoint[i] = rkCtrl;

        // set the replicated control point
        if ( i < m_iReplicate )
            m_akCtrlPoint[m_iNumCtrlPoints+i] = rkCtrl;
    }
}
//----------------------------------------------------------------------------
template <class Real>
const Vector2<Real>& NURBSCurve2<Real>::GetControlPoint (int i) const
{
    if ( 0 <= i && i < m_iNumCtrlPoints )
        return m_akCtrlPoint[i];

    return ms_kInvalidCtrlPoint;
}
//----------------------------------------------------------------------------
template <class Real>
void NURBSCurve2<Real>::SetControlWeight (int i, Real fWeight)
{
    if ( 0 <= i && i < m_iNumCtrlPoints )
    {
        // set the control weight
        m_afCtrlWeight[i] = fWeight;

        // set the replicated control weight
        if ( i < m_iReplicate )
            m_afCtrlWeight[m_iNumCtrlPoints+i] = fWeight;
    }
}
//----------------------------------------------------------------------------
template <class Real>
Real NURBSCurve2<Real>::GetControlWeight (int i) const
{
    if ( 0 <= i && i < m_iNumCtrlPoints )
        return m_afCtrlWeight[i];

    return Math<Real>::MAX_REAL;
}
//----------------------------------------------------------------------------
template <class Real>
Real& NURBSCurve2<Real>::Knot (int i)
{
    return m_kBasis.Knot(i);
}
//----------------------------------------------------------------------------
template <class Real>
void NURBSCurve2<Real>::Get (Real fTime, Vector2<Real>* pkPos,
    Vector2<Real>* pkDer1, Vector2<Real>* pkDer2, Vector2<Real>* pkDer3) const
{
    int i, iMin, iMax;
    if ( pkDer3 )
    {
        m_kBasis.Compute(fTime,0,iMin,iMax);
        m_kBasis.Compute(fTime,1,iMin,iMax);
        m_kBasis.Compute(fTime,2,iMin,iMax);
        m_kBasis.Compute(fTime,3,iMin,iMax);
    }
    else if ( pkDer2 )
    {
        m_kBasis.Compute(fTime,0,iMin,iMax);
        m_kBasis.Compute(fTime,1,iMin,iMax);
        m_kBasis.Compute(fTime,2,iMin,iMax);
    }
    else if ( pkDer1 )
    {
        m_kBasis.Compute(fTime,0,iMin,iMax);
        m_kBasis.Compute(fTime,1,iMin,iMax);
    }
    else  // pkPos
    {
        m_kBasis.Compute(fTime,0,iMin,iMax);
    }

    Real fTmp;

    // compute position
    Vector2<Real> kX = Vector2<Real>::ZERO;
    Real fW = (Real)0.0;
    for (i = iMin; i <= iMax; i++)
    {
        fTmp = m_kBasis.GetD0(i)*m_afCtrlWeight[i];
        kX += fTmp*m_akCtrlPoint[i];
        fW += fTmp;
    }
    Real fInvW = ((Real)1.0)/fW;
    Vector2<Real> kP = fInvW*kX;
    if ( pkPos )
        *pkPos = kP;

    if ( !pkDer1 && !pkDer2 && !pkDer3 )
        return;

    // compute first derivative
    Vector2<Real> kXDer1 = Vector2<Real>::ZERO;
    Real fWDer1 = (Real)0.0;
    for (i = iMin; i <= iMax; i++)
    {
        fTmp = m_kBasis.GetD1(i)*m_afCtrlWeight[i];
        kXDer1 += fTmp*m_akCtrlPoint[i];
        fWDer1 += fTmp;
    }
    Vector2<Real> kPDer1 = fInvW*(kXDer1 - fWDer1*kP);
    if ( pkDer1 )
        *pkDer1 = kPDer1;

    if ( !pkDer2 && !pkDer3 )
        return;

    // compute second derivative
    Vector2<Real> kXDer2 = Vector2<Real>::ZERO;
    Real fWDer2 = (Real)0.0;
    for (i = iMin; i <= iMax; i++)
    {
        fTmp = m_kBasis.GetD2(i)*m_afCtrlWeight[i];
        kXDer2 += fTmp*m_akCtrlPoint[i];
        fWDer2 += fTmp;
    }
    Vector2<Real> kPDer2 = fInvW*(kXDer2-((Real)2.0)*fWDer1*kPDer1-fWDer2*kP);
    if ( pkDer2 )
        *pkDer2 = kPDer2;

    if ( !pkDer3 )
        return;

    // compute third derivative
    Vector2<Real> kXDer3 = Vector2<Real>::ZERO;
    Real fWDer3 = (Real)0.0;
    for (i = iMin; i <= iMax; i++)
    {
        fTmp = m_kBasis.GetD3(i)*m_afCtrlWeight[i];
        kXDer3 += fTmp*m_akCtrlPoint[i];
        fWDer3 += fTmp;
    }
    if ( pkDer3 )
    {
        *pkDer3 = fInvW*(kXDer3 - ((Real)3.0)*fWDer1*kPDer2 -
            ((Real)3.0)*fWDer2*kPDer1 -fWDer3*kP);
    }
}
//----------------------------------------------------------------------------
template <class Real>
Vector2<Real> NURBSCurve2<Real>::GetPosition (Real fTime) const
{
    Vector2<Real> kPos;
    Get(fTime,&kPos,NULL,NULL,NULL);
    return kPos;
}
//----------------------------------------------------------------------------
template <class Real>
Vector2<Real> NURBSCurve2<Real>::GetFirstDerivative (Real fTime) const
{
    Vector2<Real> kDer1;
    Get(fTime,NULL,&kDer1,NULL,NULL);
    return kDer1;
}
//----------------------------------------------------------------------------
template <class Real>
Vector2<Real> NURBSCurve2<Real>::GetSecondDerivative (Real fTime) const
{
    Vector2<Real> kDer2;
    Get(fTime,NULL,NULL,&kDer2,NULL);
    return kDer2;
}
//----------------------------------------------------------------------------
template <class Real>
Vector2<Real> NURBSCurve2<Real>::GetThirdDerivative (Real fTime) const
{
    Vector2<Real> kDer3;
    Get(fTime,NULL,NULL,NULL,&kDer3);
    return kDer3;
}
//----------------------------------------------------------------------------
template <class Real>
Real NURBSCurve2<Real>::GetVariation (Real, Real,  const Vector2<Real>*,
    const Vector2<Real>*) const
{
    // TO DO.
    return (Real)0.0;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template class WML_ITEM NURBSCurve2<float>;
Vector2f NURBSCurve2f::ms_kInvalidCtrlPoint = Vector2f::ZERO;

template class WML_ITEM NURBSCurve2<double>;
Vector2d NURBSCurve2d::ms_kInvalidCtrlPoint = Vector2d::ZERO;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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