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

📄 wmlnode.cpp

📁 3D Game Engine Design Source Code非常棒
💻 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"
using namespace Wml;

WmlImplementRTTI(Node,Spatial);
WmlImplementStream(Node);

//----------------------------------------------------------------------------
Node::Node (int iQuantity, int iGrowBy)
    :
    m_kChild(iQuantity)
{
    m_iGrowBy = iGrowBy;
    m_iUsed = 0;
}
//----------------------------------------------------------------------------
Node::~Node ()
{
    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        SpatialPtr spkChild = DetachChildAt(i);
        spkChild = NULL;
    }
}
//----------------------------------------------------------------------------
int Node::AttachChild (Spatial* pkChild)
{
    // Some folks are of the impression that a node can have multiple parents,
    // the scene graph therefore being a DAG.  That is not the case.  The
    // parent-child relationships form a tree.  This assertion is to let folks
    // know this and to warn them that a child is being kidnapped from another
    // parent.  To be safe, you should really call DetachChild before you
    // reattach somewhere else with AttachChild or SetChild.
    assert( pkChild && !pkChild->GetParent() );

    pkChild->SetParent(this);
    m_iUsed++;

    // attach child in first available slot (if any)
    int iQuantity = (int)m_kChild.size();
    for (int i = 0; i < iQuantity; i++)
    {
        if ( m_kChild[i] == 0 )
        {
            m_kChild[i] = pkChild;
            return i;
        }
    }

    // all slots used, increase array size
    m_kChild.resize(iQuantity + m_iGrowBy);
    m_kChild[iQuantity] = pkChild;
    return iQuantity;
}
//----------------------------------------------------------------------------
int Node::DetachChild (Spatial* pkChild)
{
    if ( pkChild )
    {
        // search to see if child exists
        for (int i = 0; i < (int)m_kChild.size(); i++)
        {
            if ( m_kChild[i] == pkChild )
            {
                // child found, detach it
                pkChild->SetParent(NULL);
                m_kChild[i] = NULL;
                m_iUsed--;
                return i;
            }
        }
    }

    return -1;
}
//----------------------------------------------------------------------------
SpatialPtr Node::DetachChildAt (int i)
{
    if ( i < (int)m_kChild.size() )
    {
        SpatialPtr spkChild = m_kChild[i];
        if ( spkChild )
        {
            // child exists in slot, detach it
            spkChild->SetParent(NULL);
            m_kChild[i] = NULL;
            m_iUsed--;
        }
        return spkChild;
    }
    else
    {
        return NULL;
    }
}
//----------------------------------------------------------------------------
SpatialPtr Node::SetChild (int i, Spatial* pkChild)
{
    // Some folks are of the impression that a node can have multiple parents,
    // the scene graph therefore being a DAG.  That is not the case.  The
    // parent-child relationships form a tree.  This assertion is to let folks
    // know this and to warn them that a child is being kidnapped from another
    // parent.  To be safe, you should really call DetachChild before you
    // reattach somewhere else with AttachChild or SetChild.
    if ( pkChild )
    {
        assert( !pkChild->GetParent() );
    }

    if ( i < (int)m_kChild.size() )
    {
        // detach child currently in slot
        SpatialPtr spkPreviousChild = m_kChild[i];
        if ( spkPreviousChild )
        {
            spkPreviousChild->SetParent(NULL);
            m_iUsed--;
        }

        // attach new child to slot
        if ( pkChild )
        {
            pkChild->SetParent(this);
            m_iUsed++;
        }

        m_kChild[i] = pkChild;
        return spkPreviousChild;
    }
    else
    {
        // index out of range, increase array size and attach new child
        pkChild->SetParent(this);
        m_kChild.resize(i + m_iGrowBy);
        m_kChild[i] = pkChild;
        m_iUsed++;
        return NULL;
    }
}
//----------------------------------------------------------------------------
SpatialPtr Node::GetChild (int i)
{
    if ( i < (int)m_kChild.size() )
        return m_kChild[i];
    else
        return NULL;
}
//----------------------------------------------------------------------------
void Node::UpdateWorldData (float fAppTime)
{
    Spatial::UpdateWorldData(fAppTime);

    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
            pkChild->UpdateGS(fAppTime,false);
    }
}
//----------------------------------------------------------------------------
void Node::UpdateWorldBound ()
{
    bool bFoundFirstBound = false;
    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
        {
            if ( bFoundFirstBound )
            {
                // merge current world bound with child world bound
                m_kWorldBound += pkChild->WorldBound();
            }
            else
            {
                // set world bound to first non-null child world bound
                bFoundFirstBound = true;
                m_kWorldBound = pkChild->WorldBound();
            }
        }
    }
}
//----------------------------------------------------------------------------
void Node::UpdateRenderState (RenderState::Stack* pkStack)
{
    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
            pkChild->UpdateRS(pkStack);
    }
}
//----------------------------------------------------------------------------
void Node::Draw (Renderer& rkRenderer)
{
    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
            pkChild->OnDraw(rkRenderer);
    }
}
//----------------------------------------------------------------------------
Object* Node::GetObjectByName (const char* acName)
{
    Object* pkFound = Spatial::GetObjectByName(acName);
    if ( pkFound )
        return pkFound;

    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
        {
            pkFound = pkChild->GetObjectByName(acName);
            if ( pkFound )
                return pkFound;
        }
    }

    return NULL;
}
//----------------------------------------------------------------------------
void Node::GetAllObjectsByName (const char* acName,
    std::vector<Object*>& rkObjects)
{
    Spatial::GetAllObjectsByName(acName,rkObjects);

    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
            pkChild->GetAllObjectsByName(acName,rkObjects);
    }
}
//----------------------------------------------------------------------------
void Node::DoPick (const Vector3f& rkOrigin, const Vector3f& rkDirection,
    PickArray& rkResults)
{
    if ( m_kWorldBound.TestIntersection(rkOrigin,rkDirection) )
    {
        for (int i = 0; i < (int)m_kChild.size(); i++)
        {
            Spatial* pkChild = m_kChild[i];
            if ( pkChild )
                pkChild->DoPick(rkOrigin,rkDirection,rkResults);
        }
    }
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// streaming
//----------------------------------------------------------------------------
Object* Node::Factory (Stream& rkStream)
{
    Node* pkObject = new Node;
    Stream::Link* pkLink = new Stream::Link(pkObject);
    pkObject->Load(rkStream,pkLink);
    return pkObject;
}
//----------------------------------------------------------------------------
void Node::Load (Stream& rkStream, Stream::Link* pkLink)
{
    Spatial::Load(rkStream,pkLink);

    // native data
    StreamRead(rkStream,m_iGrowBy);

    if ( rkStream.GetVersion() == Version(1,0) )
    {
        // The value m_iUsed is really a derived quantity that gets set in the
        // Link call when children are added.  It was streamed in Version
        // 1.00, but does not need to be (and is not in later versions).
        StreamRead(rkStream,m_iUsed);
        m_iUsed = 0;
    }

    // link data
    int iQuantity;
    StreamRead(rkStream,iQuantity);
    for (int i = 0; i < iQuantity; i++)
    {
        Spatial* pkChild;
        StreamRead(rkStream,pkChild);
        pkLink->Add(pkChild);
    }

    // set array quantity, array filled in by Link
    m_kChild.resize(iQuantity);
}
//----------------------------------------------------------------------------
void Node::Link (Stream& rkStream, Stream::Link* pkLink)
{
    Spatial::Link(rkStream,pkLink);

    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        Object* pkLinkID = pkLink->GetLinkID();
        Spatial* pkChild = (Spatial*)rkStream.GetFromMap(pkLinkID);
        SetChild(i,pkChild);
    }
}
//----------------------------------------------------------------------------
bool Node::Register (Stream& rkStream)
{
    if ( !Spatial::Register(rkStream) )
        return false;

    for (int i = 0; i < (int)m_kChild.size(); i++)
    {
        if ( m_kChild[i] )
            m_kChild[i]->Register(rkStream);
    }

    return true;
}
//----------------------------------------------------------------------------
void Node::Save (Stream& rkStream)
{
    Spatial::Save(rkStream);

    // native data
    StreamWrite(rkStream,m_iGrowBy);

    // link data
    StreamWrite(rkStream,m_kChild.size());
    for (int i = 0; i < (int)m_kChild.size(); i++)
        StreamWrite(rkStream,m_kChild[i]);
}
//----------------------------------------------------------------------------
StringTree* Node::SaveStrings ()
{
    StringTree* pkTree = new StringTree(4,0,m_iUsed+1,0);

    // strings
    int iCQuantity = (int)m_kChild.size();
    pkTree->SetString(0,MakeString(&ms_kRTTI,GetName()));
    pkTree->SetString(1,MakeString("quantity =",iCQuantity));
    pkTree->SetString(2,MakeString("used =",m_iUsed));
    pkTree->SetString(3,MakeString("grow by =",m_iGrowBy));

    // children
    pkTree->SetChild(0,Spatial::SaveStrings());
    int iSlot = 1;
    for (int i = 0; i < iCQuantity; i++)
    {
        Spatial* pkChild = m_kChild[i];
        if ( pkChild )
            pkTree->SetChild(iSlot++,pkChild->SaveStrings());
    }

    return pkTree;
}
//----------------------------------------------------------------------------
int Node::GetMemoryUsed () const
{
    int iBaseSize = sizeof(Node) - sizeof(Spatial);
    int iDynaSize = ((int)m_kChild.size())*sizeof(m_kChild[0]);
    int iTotalSize = iBaseSize + iDynaSize + Spatial::GetMemoryUsed();
    return iTotalSize;
}
//----------------------------------------------------------------------------
int Node::GetDiskUsed () const
{
    return Spatial::GetDiskUsed() +
        sizeof(m_iGrowBy) +
        sizeof(m_kChild.size()) +
        ((int)m_kChild.size())*sizeof(m_kChild[0]);
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

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