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

📄 mgcmorphcontroller.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
字号:
// 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 "MgcGeometry.h"
#include "MgcMorphController.h"

MgcImplementRTTI(MgcMorphController,MgcController);
MgcImplementStream(MgcMorphController);

//----------------------------------------------------------------------------
MgcMorphController::MgcMorphController (MgcGeometry* pkObject)
{
    m_uiTargetQuantity = 0;
    m_aakVertex = 0;
    m_bUpdateNormals = false;
    m_uiKeyQuantity = 0;
    m_afTime = 0;
    m_aafWeight = 0;
    m_uiLastIndex = 0;
}
//----------------------------------------------------------------------------
MgcMorphController::~MgcMorphController ()
{
    DeleteTargets();
    DeleteTimes();
    DeleteWeights();
}
//----------------------------------------------------------------------------
void MgcMorphController::DeleteTargets ()
{
    if ( m_aakVertex )
    {
        for (unsigned int uiT = 0; uiT < m_uiTargetQuantity; uiT++)
            delete[] m_aakVertex[uiT];
        delete[] m_aakVertex;
        m_aakVertex = 0;
    }
}
//----------------------------------------------------------------------------
void MgcMorphController::DeleteTimes ()
{
    delete[] m_afTime;
    m_afTime = 0;
}
//----------------------------------------------------------------------------
void MgcMorphController::DeleteWeights ()
{
    if ( m_aafWeight )
    {
        for (unsigned int uiK = 0; uiK < m_uiKeyQuantity; uiK++)
            delete[] m_aafWeight[uiK];
        delete[] m_aafWeight;
        m_aafWeight = 0;
    }
}
//----------------------------------------------------------------------------
void MgcMorphController::SetTargetQuantity (unsigned int uiTargetQuantity)
{
    assert( uiTargetQuantity > 0 );

    DeleteTargets();
    m_uiTargetQuantity = uiTargetQuantity;
    m_aakVertex = new MgcVector3*[m_uiTargetQuantity];
    memset(m_aakVertex,0,m_uiTargetQuantity*sizeof(MgcVector3*));
}
//----------------------------------------------------------------------------
void MgcMorphController::SetKeyQuantity (unsigned int uiKeyQuantity)
{
    assert( uiKeyQuantity > 0 );

    DeleteTimes();
    DeleteWeights();
    m_uiKeyQuantity = uiKeyQuantity;
    m_aafWeight = new MgcReal*[m_uiKeyQuantity];
    memset(m_aafWeight,0,m_uiKeyQuantity*sizeof(MgcReal*));
}
//----------------------------------------------------------------------------
void MgcMorphController::GetKeyInfo (MgcReal fCtrlTime, MgcReal& rfTime,
    MgcReal& rfOmTime, unsigned int& ruiI0, unsigned int& ruiI1)
{
    if ( fCtrlTime <= m_afTime[0] )
    {
        rfTime = 0.0;
        rfOmTime = 1.0;
        m_uiLastIndex = 0;
        ruiI0 = 0;
        ruiI1 = 0;
        return;
    }

    if ( fCtrlTime >= m_afTime[m_uiKeyQuantity-1] )
    {
        rfTime = 0.0;
        rfOmTime = 1.0;
        m_uiLastIndex = m_uiKeyQuantity - 1;
        ruiI0 = m_uiLastIndex;
        ruiI1 = m_uiLastIndex;
        return;
    }

    unsigned int uiNextIndex;
    if ( fCtrlTime > m_afTime[m_uiLastIndex] )
    {
        uiNextIndex = m_uiLastIndex + 1;
        while ( fCtrlTime >= m_afTime[uiNextIndex] )
        {
            m_uiLastIndex = uiNextIndex;
            uiNextIndex++;
        }

        ruiI0 = m_uiLastIndex;
        ruiI1 = uiNextIndex;
        rfTime = (fCtrlTime - m_afTime[ruiI0]) /
            (m_afTime[ruiI1] - m_afTime[ruiI0]);
    }
    else if ( fCtrlTime < m_afTime[m_uiLastIndex] )
    {
        uiNextIndex = m_uiLastIndex - 1;
        while ( fCtrlTime <= m_afTime[uiNextIndex] )
        {
            m_uiLastIndex = uiNextIndex;
            uiNextIndex--;
        }

        ruiI0 = uiNextIndex;
        ruiI1 = m_uiLastIndex;
        rfTime = (fCtrlTime - m_afTime[ruiI0]) /
            (m_afTime[ruiI1] - m_afTime[ruiI0]);
    }
    else
    {
        rfTime = 0.0;
        ruiI0 = m_uiLastIndex;
        ruiI1 = m_uiLastIndex;
    }

    rfOmTime = 1.0 - rfTime;
}
//----------------------------------------------------------------------------
bool MgcMorphController::Update (MgcReal fAppTime)
{
    // The key interpolation uses linear interpolation.  To get higher-order
    // interpolation, you need to provide a more sophisticated key (Bezier
    // cubic or TCB spline, for example).

    if ( !Active() )
    {
        // controller does not compute world transform
        return false;
    }

    // set vertices to target[0]
    MgcGeometry* pkGeom = (MgcGeometry*) m_pkObject;
    unsigned int uiVertexQuantity = pkGeom->GetVertexQuantity();
    MgcVector3* akVertex = pkGeom->Vertices();
    memcpy(akVertex,m_aakVertex[0],uiVertexQuantity*sizeof(MgcVector3));

    // lookup the bounding keys
    MgcReal fCtrlTime = GetControlTime(fAppTime);
    MgcReal fNT, fOmNT;
    unsigned int uiI0, uiI1;
    GetKeyInfo(fCtrlTime,fNT,fOmNT,uiI0,uiI1);

    // add the remaining components in the convex composition
    for (unsigned int uiT = 1; uiT < m_uiTargetQuantity; uiT++)
    {
        MgcReal fCoeff = fOmNT*m_aafWeight[uiI0][uiT-1] +
            fNT*m_aafWeight[uiI1][uiT-1];

        for (unsigned int uiV = 0; uiV < uiVertexQuantity; uiV++)
            akVertex[uiV] += fCoeff*m_aakVertex[uiT][uiV];
    }

    // controller does not compute world transform
    return false;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// streaming
//----------------------------------------------------------------------------
MgcObject* MgcMorphController::Factory (MgcStream& rkStream)
{
    MgcMorphController* pkObject = new MgcMorphController;
    MgcStream::Link* pkLink = new MgcStream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//----------------------------------------------------------------------------
void MgcMorphController::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcController::Load(rkStream,pkLink);

    MgcStreamRead(rkStream,m_uiTargetQuantity);
    SetTargetQuantity(m_uiTargetQuantity);

    unsigned int uiVertexQuantity;
    MgcStreamRead(rkStream,uiVertexQuantity);
    for (unsigned int uiT = 0; uiT < m_uiTargetQuantity; uiT++)
    {
        MgcVector3* akVertex = new MgcVector3[uiVertexQuantity];
        MgcStreamRead(rkStream,akVertex,uiVertexQuantity);
        SetVertices(uiT,akVertex);
    }

    MgcStreamRead(rkStream,m_bUpdateNormals);

    MgcStreamRead(rkStream,m_uiKeyQuantity);
    SetKeyQuantity(m_uiKeyQuantity);

    MgcReal* afTime = new MgcReal[m_uiKeyQuantity];
    MgcStreamRead(rkStream,afTime,m_uiKeyQuantity);
    SetTimes(afTime);

    for (unsigned int uiK = 0; uiK < m_uiKeyQuantity; uiK++)
    {
        MgcReal* afWeight = new MgcReal[m_uiKeyQuantity-1];
        MgcStreamRead(rkStream,afWeight,m_uiKeyQuantity-1);
        SetWeights(uiK,afWeight);
    }
}
//----------------------------------------------------------------------------
void MgcMorphController::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
    MgcController::Link(rkStream,pkLink);
}
//----------------------------------------------------------------------------
bool MgcMorphController::Register (MgcStream& rkStream)
{
    return MgcController::Register(rkStream);
}
//----------------------------------------------------------------------------
void MgcMorphController::Save (MgcStream& rkStream)
{
    MgcController::Save(rkStream);

    MgcStreamWrite(rkStream,m_uiTargetQuantity);

    MgcGeometry* pkGeom = (MgcGeometry*) m_pkObject;
    unsigned int uiVertexQuantity = pkGeom->GetVertexQuantity();
    MgcStreamWrite(rkStream,uiVertexQuantity);
    for (unsigned int uiT = 0; uiT < m_uiTargetQuantity; uiT++)
        MgcStreamWrite(rkStream,m_aakVertex[uiT],uiVertexQuantity);

    MgcStreamWrite(rkStream,m_bUpdateNormals);

    MgcStreamWrite(rkStream,m_uiKeyQuantity);
    MgcStreamWrite(rkStream,m_afTime,m_uiKeyQuantity);
    for (unsigned int uiK = 0; uiK < m_uiKeyQuantity; uiK++)
        MgcStreamWrite(rkStream,m_aafWeight[uiK],m_uiKeyQuantity-1);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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