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

📄 wmlspatial.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 "WmlNode.h"
#include "WmlRenderer.h"
#include "WmlSpatial.h"
#include <algorithm>
using namespace Wml;

WmlImplementRTTI(Spatial,Object);
WmlImplementStream(Spatial);

//----------------------------------------------------------------------------
Spatial::Spatial ()
    :
    m_kRotate(Matrix3f::IDENTITY),
    m_kTranslate(Vector3f::ZERO),
    m_kWorldRotate(Matrix3f::IDENTITY),
    m_kWorldTranslate(Vector3f::ZERO)
{
    m_pkParent = NULL;
    m_fScale = 1.0f;
    m_fWorldScale = 1.0f;
    m_bForceCull = false;
    m_pkStateList = NULL;
}
//----------------------------------------------------------------------------
Spatial::~Spatial ()
{
    RemoveAllStates();
}
//----------------------------------------------------------------------------
RenderStatePtr Spatial::SetRenderState (RenderState* pkState)
{
    assert( pkState );

    // check if type of state already exists
    RenderState::List* pkList;
    for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
    {
        if ( pkList->m_spkState->GetType() == pkState->GetType() )
        {
            // type of state exists, replace it
            RenderStatePtr spkSave = pkList->m_spkState;
            pkList->m_spkState = pkState;
            return spkSave;
        }
    }

    // type of state not in current list, add state
    pkList = new RenderState::List;
    pkList->m_spkState = pkState;
    pkList->m_pkNext = m_pkStateList;
    m_pkStateList = pkList;
    return NULL;
}
//----------------------------------------------------------------------------
RenderStatePtr Spatial::GetRenderState (RenderState::Type eType)
{
    // check if type of state already exists
    RenderState::List* pkList;
    for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
    {
        if ( pkList->m_spkState->GetType() == eType )
        {
            // type of state exists, return it
            return pkList->m_spkState;
        }
    }

    return NULL;
}
//----------------------------------------------------------------------------
RenderStatePtr Spatial::RemoveRenderState (RenderState::Type eType)
{
    // check if type of state already exists
    RenderState::List* pkList = m_pkStateList;
    RenderState::List* pkPrev = NULL;
    for (/**/; pkList; pkPrev = pkList, pkList = pkList->m_pkNext)
    {
        if ( pkList->m_spkState->GetType() == eType )
        {
            // type of state exists, remove it
            RenderStatePtr spkSave = pkList->m_spkState;

            if ( pkPrev )
            {
                // render state not at front of list
                pkPrev->m_pkNext = pkList->m_pkNext;
            }
            else
            {
                // render state at front of list
                assert( pkList == m_pkStateList );
                m_pkStateList = pkList->m_pkNext;
            }
            pkList->m_pkNext = NULL;
            delete pkList;

            return spkSave;
        }
    }

    // type of state not in current list
    return NULL;
}
//----------------------------------------------------------------------------
void Spatial::RemoveAllStates ()
{
    while ( m_pkStateList )
    {
        m_pkStateList->m_spkState = NULL;
        RenderState::List* pkSave = m_pkStateList->m_pkNext;
        delete m_pkStateList;
        m_pkStateList = pkSave;
    }
}
//----------------------------------------------------------------------------
void Spatial::UpdateWorldData (float fAppTime)
{
    // update render state controllers
    RenderState::List* pkSList;
    Controller* pkControl;
    for (pkSList = m_pkStateList; pkSList; pkSList = pkSList->m_pkNext)
    {
        RenderState* pkState = pkSList->m_spkState;
        pkControl = pkState->GetControllers();
        while ( pkControl )
        {
            pkControl->Update(fAppTime);
            pkControl = pkControl->GetNext();
        }
    }

    // update spatial controllers
    int iComputesWorldTransform = 0;
    pkControl = GetControllers();
    while ( pkControl )
    {
        if ( pkControl->Update(fAppTime) )
            iComputesWorldTransform++;
        pkControl = pkControl->GetNext();
    }

    // If two controllers set the world transforms, there is most likely a
    // problem (one controller is unaware that the other is also changing
    // transforms).
    assert( iComputesWorldTransform <= 1 );

    // update world transforms
    if ( iComputesWorldTransform == 0 )
    {
        if ( m_pkParent )
        {
            m_fWorldScale = m_pkParent->m_fWorldScale*m_fScale;
            m_kWorldRotate = m_pkParent->m_kWorldRotate*m_kRotate;
            m_kWorldTranslate = m_pkParent->m_kWorldTranslate +
                m_pkParent->m_fWorldScale*(m_pkParent->m_kWorldRotate *
                m_kTranslate);
        }
        else
        {
            m_fWorldScale = m_fScale;
            m_kWorldRotate = m_kRotate;
            m_kWorldTranslate = m_kTranslate;
        }
    }
}
//----------------------------------------------------------------------------
void Spatial::PropagateBoundToRoot ()
{
    if ( m_pkParent )
    {
        m_pkParent->UpdateWorldBound();
        m_pkParent->PropagateBoundToRoot();
    }
}
//----------------------------------------------------------------------------
void Spatial::UpdateGS (float fAppTime, bool bInitiator)
{
    UpdateWorldData(fAppTime);
    UpdateWorldBound();
    if ( bInitiator )
        PropagateBoundToRoot();
}
//----------------------------------------------------------------------------
void Spatial::PropagateStateFromRoot (RenderState::Stack* pkStack)
{
    // traverse to root to allow downward state propagation
    if ( m_pkParent )
        m_pkParent->PropagateStateFromRoot(pkStack);

    // push states onto current render state stack
    RenderState::List* pkList;
    for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
        pkStack->Push(pkList->m_spkState);
}
//----------------------------------------------------------------------------
void Spatial::RestoreStateToRoot (RenderState::Stack* pkStack)
{
    // pop states from current render state stack
    RenderState::List* pkList;
    for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
        pkStack->Pop(pkList->m_spkState);

    // traverse to root
    if ( m_pkParent )
        m_pkParent->RestoreStateToRoot(pkStack);
}
//----------------------------------------------------------------------------
void Spatial::UpdateRS (RenderState::Stack* pkStack)
{
    bool bInitiator = (pkStack == NULL);
    RenderState::List* pkList;

    // update previous state by current state
    if ( bInitiator )
    {
        // traverse to root and push states from root to this node
        pkStack = new RenderState::Stack;
        PropagateStateFromRoot(pkStack);
    }
    else
    {
        // push states at this node
        for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
            pkStack->Push(pkList->m_spkState);
    }

    // propagate the new state to the subtree rooted here
    UpdateRenderState(pkStack);

    // restore previous state
    if ( bInitiator )
    {
        // traverse to root and pop states along the way
        RestoreStateToRoot(pkStack);
        delete pkStack;
    }
    else
    {

⌨️ 快捷键说明

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