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

📄 mgckeyframecontroller.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 "MgcKeyframeController.h"
#include "MgcQuaternion.h"
#include "MgcSpatial.h"

MgcImplementRTTI(MgcKeyframeController,MgcController);
MgcImplementStream(MgcKeyframeController);

//----------------------------------------------------------------------------
MgcKeyframeController::MgcKeyframeController (MgcSpatial* pkObject)
{
    MgcController::SetObject(pkObject);

    m_uiTQuantity = 0;
    m_afTTime = 0;
    m_akTData = 0;
    m_uiTLastIndex = 0;

    m_uiRQuantity = 0;
    m_afRTime = 0;
    m_akRData = 0;
    m_uiRLastIndex = 0;

    m_uiSQuantity = 0;
    m_afSTime = 0;
    m_afSData = 0;
    m_uiSLastIndex = 0;

    m_uiSharedQuantity = 0;
    m_afSharedTime = 0;
    m_uiSharedLastIndex = 0;
}
//----------------------------------------------------------------------------
MgcKeyframeController::~MgcKeyframeController ()
{
    delete[] m_akTData;
    delete[] m_akRData;
    delete[] m_afSData;

    if ( m_uiSharedQuantity > 0 )
    {
        delete[] m_afSharedTime;
    }
    else
    {
        delete[] m_afTTime;
        delete[] m_afRTime;
        delete[] m_afSTime;
    }
}
//----------------------------------------------------------------------------
void MgcKeyframeController::SetSharedQuantity (unsigned int uiQuantity)
{
    m_uiSharedQuantity = uiQuantity;
    m_uiTQuantity = uiQuantity;
    m_uiRQuantity = uiQuantity;
    m_uiSQuantity = uiQuantity;
}
//----------------------------------------------------------------------------
void MgcKeyframeController::SetSharedTimes (MgcReal* afTime)
{
    m_afSharedTime = afTime;
    m_afTTime = afTime;
    m_afRTime = afTime;
    m_afSTime = afTime;
}
//----------------------------------------------------------------------------
void MgcKeyframeController::GetKeyInfo (MgcReal fCtrlTime,
    unsigned int uiQuantity, MgcReal* afTime, unsigned int& ruiLastIndex,
    MgcReal& rfTime, unsigned int& ruiI0, unsigned int& ruiI1)
{
    if ( fCtrlTime <= afTime[0] )
    {
        rfTime = 0.0;
        ruiLastIndex = 0;
        ruiI0 = 0;
        ruiI1 = 0;
        return;
    }

    if ( fCtrlTime >= afTime[uiQuantity-1] )
    {
        rfTime = 0.0;
        ruiLastIndex = uiQuantity - 1;
        ruiI0 = ruiLastIndex;
        ruiI1 = ruiLastIndex;
        return;
    }

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

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

        ruiI0 = uiNextIndex;
        ruiI1 = ruiLastIndex;
        rfTime = (fCtrlTime - afTime[ruiI0])/(afTime[ruiI1] - afTime[ruiI0]);
    }
    else
    {
        rfTime = 0.0;
        ruiI0 = ruiLastIndex;
        ruiI1 = ruiLastIndex;
    }
}
//----------------------------------------------------------------------------
MgcVector3 MgcKeyframeController::GetTranslation (MgcReal fNormTime,
    unsigned int uiI0, unsigned int uiI1)
{
    return m_akTData[uiI0] + fNormTime*(m_akTData[uiI1] - m_akTData[uiI0]);
}
//----------------------------------------------------------------------------
MgcMatrix3 MgcKeyframeController::GetRotation (MgcReal fNormTime,
    unsigned int uiI0, unsigned int uiI1)
{
    MgcQuaternion kQ = MgcQuaternion::Slerp(fNormTime,m_akRData[uiI0],
        m_akRData[uiI1]);

    MgcMatrix3 kRot;
    kQ.ToRotationMatrix(kRot);
    return kRot;
}
//----------------------------------------------------------------------------
MgcReal MgcKeyframeController::GetScale (MgcReal fNormTime,
    unsigned int uiI0, unsigned int uiI1)
{
    return m_afSData[uiI0] + fNormTime*(m_afSData[uiI1] - m_afSData[uiI0]);
}
//----------------------------------------------------------------------------
bool MgcKeyframeController::Update (MgcReal fAppTime)
{
    if ( !Active() )
    {
        // controller does not compute world transform
        return false;
    }

    MgcSpatial* pkSpatial = (MgcSpatial*) m_pkObject;
    MgcReal fCtrlTime = GetControlTime(fAppTime);
    MgcReal fNormTime;
    unsigned int uiI0, uiI1;

    if ( m_uiSharedQuantity > 0 )
    {
        GetKeyInfo(fCtrlTime,m_uiSharedQuantity,m_afSharedTime,
            m_uiSharedLastIndex,fNormTime,uiI0,uiI1);

        if ( m_uiTQuantity > 0 )
            pkSpatial->Translate() = GetTranslation(fNormTime,uiI0,uiI1);

        if ( m_uiRQuantity > 0 )
            pkSpatial->Rotate() = GetRotation(fNormTime,uiI0,uiI1);

        if ( m_uiSQuantity > 0 )
            pkSpatial->Scale() = GetScale(fNormTime,uiI0,uiI1);
    }
    else
    {
        if ( m_uiTQuantity > 0 )
        {
            GetKeyInfo(fCtrlTime,m_uiTQuantity,m_afTTime,m_uiTLastIndex,
                fNormTime,uiI0,uiI1);
            pkSpatial->Translate() = GetTranslation(fNormTime,uiI0,uiI1);
        }

        if ( m_uiRQuantity > 0 )
        {
            GetKeyInfo(fCtrlTime,m_uiRQuantity,m_afRTime,m_uiRLastIndex,
                fNormTime,uiI0,uiI1);
            pkSpatial->Rotate() = GetRotation(fNormTime,uiI0,uiI1);
        }

        if ( m_uiSQuantity > 0 )
        {
            GetKeyInfo(fCtrlTime,m_uiSQuantity,m_afSTime,m_uiSLastIndex,
                fNormTime,uiI0,uiI1);
            pkSpatial->Scale() = GetScale(fNormTime,uiI0,uiI1);
        }
    }

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

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

    bool bShared;
    MgcStreamRead(rkStream,bShared);

    if ( bShared )
    {
        MgcStreamRead(rkStream,m_uiSharedQuantity);
        if ( m_uiSharedQuantity > 0 )
        {
            m_afSharedTime = new MgcReal[m_uiSharedQuantity];
            m_akTData = new MgcVector3[m_uiSharedQuantity];
            m_akRData = new MgcQuaternion[m_uiSharedQuantity];
            m_afSData = new MgcReal[m_uiSharedQuantity];

            MgcStreamRead(rkStream,m_afSharedTime,m_uiSharedQuantity);
            MgcStreamRead(rkStream,m_akTData,m_uiSharedQuantity);
            MgcStreamRead(rkStream,m_akRData,m_uiSharedQuantity);
            MgcStreamRead(rkStream,m_afSData,m_uiSharedQuantity);
        }
    }
    else
    {
        MgcStreamRead(rkStream,m_uiTQuantity);
        if ( m_uiTQuantity > 0 )
        {
            m_afTTime = new MgcReal[m_uiTQuantity];
            m_akTData = new MgcVector3[m_uiTQuantity];
            MgcStreamRead(rkStream,m_afTTime,m_uiTQuantity);
            MgcStreamRead(rkStream,m_akTData,m_uiTQuantity);
        }

        MgcStreamRead(rkStream,m_uiRQuantity);
        if ( m_uiRQuantity > 0 )
        {
            m_afRTime = new MgcReal[m_uiRQuantity];
            m_akRData = new MgcQuaternion[m_uiRQuantity];
            MgcStreamRead(rkStream,m_afRTime,m_uiRQuantity);
            MgcStreamRead(rkStream,m_akRData,m_uiRQuantity);
        }

        MgcStreamRead(rkStream,m_uiSQuantity);
        if ( m_uiSQuantity > 0 )
        {
            m_afSTime = new MgcReal[m_uiSQuantity];
            m_afSData = new MgcReal[m_uiSQuantity];
            MgcStreamRead(rkStream,m_afSTime,m_uiSQuantity);
            MgcStreamRead(rkStream,m_afSData,m_uiSQuantity);
        }
    }
}
//----------------------------------------------------------------------------
void MgcKeyframeController::Link (MgcStream& rkStream,
    MgcStream::Link* pkLink)
{
    MgcController::Link(rkStream,pkLink);
}
//----------------------------------------------------------------------------
bool MgcKeyframeController::Register (MgcStream& rkStream)
{
    return MgcController::Register(rkStream);
}
//----------------------------------------------------------------------------
void MgcKeyframeController::Save (MgcStream& rkStream)
{
    MgcController::Save(rkStream);

    bool bShared = m_uiSharedQuantity > 0;
    MgcStreamWrite(rkStream,bShared);

    if ( bShared  )
    {
        MgcStreamWrite(rkStream,m_uiSharedQuantity);
        if ( m_uiSharedQuantity > 0 )
        {
            MgcStreamWrite(rkStream,m_afSharedTime,m_uiSharedQuantity);
            MgcStreamWrite(rkStream,m_akTData,m_uiSharedQuantity);
            MgcStreamWrite(rkStream,m_akRData,m_uiSharedQuantity);
            MgcStreamWrite(rkStream,m_afSData,m_uiSharedQuantity);
        }
    }
    else
    {
        MgcStreamWrite(rkStream,m_uiTQuantity);
        if ( m_uiTQuantity > 0 )
        {
            MgcStreamWrite(rkStream,m_afTTime,m_uiTQuantity);
            MgcStreamWrite(rkStream,m_akTData,m_uiTQuantity);
        }

        MgcStreamWrite(rkStream,m_uiRQuantity);
        if ( m_uiRQuantity > 0 )
        {
            MgcStreamWrite(rkStream,m_afRTime,m_uiRQuantity);
            MgcStreamWrite(rkStream,m_akRData,m_uiRQuantity);
        }

        MgcStreamWrite(rkStream,m_uiSQuantity);
        if ( m_uiSQuantity > 0 )
        {
            MgcStreamWrite(rkStream,m_afSTime,m_uiSQuantity);
            MgcStreamWrite(rkStream,m_afSData,m_uiSQuantity);
        }
    }
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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