📄 mgcspatial.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 "MgcNode.h"
#include "MgcRenderer.h"
#include "MgcSpatial.h"
MgcImplementRTTI(MgcSpatial,MgcObject);
MgcImplementStream(MgcSpatial);
//---------------------------------------------------------------------------
MgcSpatial::MgcSpatial ()
:
m_kRotate(MgcMatrix3::IDENTITY),
m_kTranslate(MgcVector3::ZERO),
m_kWorldRotate(MgcMatrix3::IDENTITY),
m_kWorldTranslate(MgcVector3::ZERO)
{
m_pkParent = 0;
m_fScale = 1.0;
m_fWorldScale = 1.0;
m_bForceCull = false;
m_pkStateList = 0;
}
//---------------------------------------------------------------------------
MgcSpatial::~MgcSpatial ()
{
RemoveAllStates();
}
//---------------------------------------------------------------------------
MgcRenderStatePtr MgcSpatial::SetRenderState (MgcRenderState* pkState)
{
assert( pkState );
// check if type of state already exists
MgcRenderState::List* pkList;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
if ( pkList->m_spkState->GetType() == pkState->GetType() )
{
// type of state exists, replace it
MgcRenderState* pkSave = pkList->m_spkState;
pkList->m_spkState = pkState;
return pkSave;
}
}
// type of state not in current list, add state
pkList = new MgcRenderState::List;
pkList->m_spkState = pkState;
pkList->m_pkNext = m_pkStateList;
m_pkStateList = pkList;
return 0;
}
//---------------------------------------------------------------------------
MgcRenderState* MgcSpatial::GetRenderState (MgcRenderState::Type eType)
{
// check if type of state already exists
MgcRenderState::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 0;
}
//---------------------------------------------------------------------------
MgcRenderStatePtr MgcSpatial::RemoveRenderState (MgcRenderState::Type eType)
{
// check if type of state already exists
MgcRenderState::List* pkList;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
if ( pkList->m_spkState->GetType() == eType )
{
// type of state exists, remove it
MgcRenderState* pkSave = pkList->m_spkState;
pkList->m_spkState = 0;
return pkSave;
}
}
// type of state not in current list
return 0;
}
//---------------------------------------------------------------------------
void MgcSpatial::RemoveAllStates ()
{
while ( m_pkStateList )
{
m_pkStateList->m_spkState = 0;
MgcRenderState::List* pSave = m_pkStateList->m_pkNext;
delete m_pkStateList;
m_pkStateList = pSave;
}
}
//---------------------------------------------------------------------------
void MgcSpatial::UpdateWorldData (MgcReal fAppTime)
{
// update render state controllers
MgcRenderState::List* pkSList;
MgcController* pkControl;
for (pkSList = m_pkStateList; pkSList; pkSList = pkSList->m_pkNext)
{
MgcRenderState* pkState = pkSList->m_spkState;
pkControl = pkState->GetControllers();
while ( pkControl )
{
pkControl->Update(fAppTime);
pkControl = pkControl->GetNext();
}
}
// update spatial controllers
bool bComputesWorldTransform = false;
pkControl = GetControllers();
while ( pkControl )
{
bComputesWorldTransform = pkControl->Update(fAppTime);
pkControl = pkControl->GetNext();
}
// update world transforms
if ( !bComputesWorldTransform )
{
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 MgcSpatial::PropagateBoundToRoot ()
{
if ( m_pkParent )
{
m_pkParent->UpdateWorldBound();
m_pkParent->PropagateBoundToRoot();
}
}
//---------------------------------------------------------------------------
void MgcSpatial::UpdateGS (MgcReal fAppTime, bool bInitiator)
{
UpdateWorldData(fAppTime);
UpdateWorldBound();
if ( bInitiator )
PropagateBoundToRoot();
}
//---------------------------------------------------------------------------
void MgcSpatial::PropagateStateFromRoot (MgcRenderState* apkState[])
{
// traverse to root to allow downward state propagation
if ( m_pkParent )
m_pkParent->PropagateStateFromRoot(apkState);
// update previous state by current state
MgcRenderState::List* pkList;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
MgcRenderState* pkState = pkList->m_spkState;
MgcRenderState::Type eType = pkState->GetType();
pkState->Update(apkState[eType]);
}
}
//---------------------------------------------------------------------------
void MgcSpatial::UpdateRS (MgcRenderState* apkPreviousState[])
{
MgcRenderState* apkState[MgcRenderState::RS_MAX_STATE];
MgcRenderState::List* pkList;
// update render states
if ( apkPreviousState )
{
// initialize with previous render states
memcpy(apkState,apkPreviousState,MgcRenderState::RS_QUANTITY);
// Update previous state by current state. The default light and
// texture states act as accumulators and are changed. They need
// to be restored on return from the recursive traversal.
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
MgcRenderState* pkState = pkList->m_spkState;
MgcRenderState::Type eType = pkState->GetType();
pkState->Update(apkState[eType]);
}
}
else
{
// initialize with default render states
memcpy(apkState,MgcRenderState::GetDefaultStates(),
MgcRenderState::RS_QUANTITY);
PropagateStateFromRoot(apkState);
}
UpdateRenderState(apkState);
// restore render states
if ( apkPreviousState )
{
// Restore previous state. The default light and texture states
// were potentially changed during the recursive traversal. They
// need to be restored.
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
MgcRenderState* pkState = pkList->m_spkState;
MgcRenderState::Type eType = pkState->GetType();
pkState->Restore(apkState[eType]);
}
}
}
//---------------------------------------------------------------------------
void MgcSpatial::OnDraw (MgcRenderer& rkRenderer)
{
if ( m_bForceCull )
return;
MgcCameraPtr spCamera = rkRenderer.GetCamera();
unsigned int uiState = spCamera->GetPlaneState();
if ( !spCamera->Culled(m_kWorldBound) )
Draw(rkRenderer);
spCamera->SetPlaneState(uiState);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// streaming
//---------------------------------------------------------------------------
MgcObject* MgcSpatial::Factory (MgcStream& rkStream)
{
// MgcSpatial is abstract, Factory never called
return 0;
}
//---------------------------------------------------------------------------
void MgcSpatial::Load (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcObject::Load(rkStream,pkLink);
// native data
MgcStreamRead(rkStream,m_kRotate);
MgcStreamRead(rkStream,m_kTranslate);
MgcStreamRead(rkStream,m_fScale);
// world transforms and world bound are derived, no need to save
// link data
unsigned int uiQuantity;
MgcStreamRead(rkStream,uiQuantity);
m_pkStateList = 0;
for (unsigned int uiI = 0; uiI < uiQuantity; uiI++)
{
MgcRenderState* pkState;
MgcStreamRead(rkStream,pkState);
pkLink->Add(pkState);
// build render state list, to be filled in by Link
MgcRenderState::List* pkList = new MgcRenderState::List;
pkList->m_spkState = 0;
pkList->m_pkNext = m_pkStateList;
m_pkStateList = pkList;
}
}
//---------------------------------------------------------------------------
void MgcSpatial::Link (MgcStream& rkStream, MgcStream::Link* pkLink)
{
MgcObject::Link(rkStream,pkLink);
MgcRenderState::List* pkList;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
MgcObject* pkLinkID = pkLink->GetLinkID();
pkList->m_spkState = (MgcRenderState*)rkStream.GetFromMap(pkLinkID);
}
}
//---------------------------------------------------------------------------
bool MgcSpatial::Register (MgcStream& rkStream)
{
if ( !MgcObject::Register(rkStream) )
return false;
// m_pkParent need not be registered since the parent itself must have
// initiated the Register call to its children, 'this' being one of them.
MgcRenderState::List* pkList;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
{
MgcRenderState* pkState = pkList->m_spkState;
if ( pkState )
pkState->Register(rkStream);
}
return true;
}
//---------------------------------------------------------------------------
void MgcSpatial::Save (MgcStream& rkStream)
{
MgcObject::Save(rkStream);
// native data
MgcStreamWrite(rkStream,m_kRotate);
MgcStreamWrite(rkStream,m_kTranslate);
MgcStreamWrite(rkStream,m_fScale);
// world transforms and world bound are derived, no need to save
// link data
// m_pkParent need not be saved since 'this' will be attached as a child
// in MgcNode::Link.
MgcRenderState::List* pkList;
unsigned int uiQuantity = 0;
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
uiQuantity++;
MgcStreamWrite(rkStream,uiQuantity);
for (pkList = m_pkStateList; pkList; pkList = pkList->m_pkNext)
MgcStreamWrite(rkStream,pkList->m_spkState);
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -