📄 wmlspatial.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 "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 + -