#include "CharSphereTree.h" #include #include #include CCharSphereTree& CCharSphereTree::GetInstance() { static CCharSphereTree ms_this( SphereConst::MAX_SPHERE_NODE, SphereConst::DEFAULT_ROOT_SIZE, SphereConst::DEFAULT_LEAF_SIZE, SphereConst::DEFAULT_GRAVY ); return ms_this; } CCharSphereNode::CCharSphereNode() : m_dwCID(0), m_pCharacter(NULL), m_pParent(NULL), m_pChildren(NULL), m_pPrevSibling(NULL), m_pNextSibling(NULL), m_ppRecomuteFifo(NULL), m_ppIntegrateFifo(NULL), m_iChildCount(0), m_dwFlag(0), m_fBindingDistance2(0), m_pLink(NULL), m_pTree(NULL) { } CCharSphereNode::CCharSphereNode( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink ) : CSphere(Pos, fRadius), m_dwCID(0), m_pCharacter(NULL), m_pParent(NULL), m_pChildren(NULL), m_pPrevSibling(NULL), m_pNextSibling(NULL), m_ppRecomuteFifo(NULL), m_ppIntegrateFifo(NULL), m_iChildCount(0), m_dwFlag(0), m_fBindingDistance2(0), m_pLink(pLink), m_pTree(pTree) { } void CCharSphereNode::Init( CCharSphereTree* pTree, const Position& Pos, float fRadius, void* pLink ) { m_pTree = pTree; m_Center = Pos; SetRadius( fRadius ); m_pLink = pLink; } void CCharSphereNode::AddChild( CCharSphereNode* pChild ) { CCharSphereNode* pOldChild = m_pChildren; m_pChildren = pChild; pChild->SetNextSibling( pOldChild ); pChild->SetPrevSibling( NULL ); pChild->SetParent( this ); if ( pOldChild ) { pOldChild->SetPrevSibling( pChild ); } ++m_iChildCount; float fDist = Distance2( pChild ); float fRadius = sqrtf( fDist ) + pChild->GetRadius(); assert( fRadius <= GetRadius() ); } void CCharSphereNode::DeleteChild( CCharSphereNode* pChild ) { assert( m_iChildCount ); assert( m_pChildren ); #ifdef _DEBUG // pChild °¡ ÇöÀç ³ëµåÀÇ ÀÚ½ÄÀÎÁö üũ CCharSphereNode* pChildren = m_pChildren; bool bFound = false; while ( pChildren ) { if ( pChildren == pChild ) { assert( !bFound ); bFound = true; break; } pChildren = pChildren->GetNextSibling(); } assert( bFound ); #endif // Prev ¿Í Next Sibling ´Ù½Ã ¼³Á¤ CCharSphereNode* pPrev = pChild->GetPrevSibling(); if ( pPrev ) { CCharSphereNode* pNext = pChild->GetNextSibling(); pPrev->SetNextSibling( pNext ); if ( pNext ) pNext->SetPrevSibling( pPrev ); } else { CCharSphereNode* pNext = pChild->GetNextSibling(); m_pChildren = pNext; if ( m_pChildren ) m_pChildren->SetPrevSibling( NULL ); } --m_iChildCount; if ( 0 == m_iChildCount && HasSphereNodeFlag( SNF_SUPERSPHERE ) ) { m_pTree->DeleteSphere( this ); } } void CCharSphereNode::Unlink() { // Recompute & Integrate Fifo ¿¡¼­ Á¦°ÅÇÑ´Ù. if ( m_ppRecomuteFifo ) { *m_ppRecomuteFifo = NULL; m_ppRecomuteFifo = NULL; } if ( m_ppIntegrateFifo ) { *m_ppIntegrateFifo = NULL; m_ppIntegrateFifo = NULL; } if ( m_pParent ) { m_pParent->DeleteChild( this ); } assert( !m_pChildren ); m_pParent = NULL; } void CCharSphereNode::NewPos( const Position& Pos ) { // »õ·Î¿î ÁÂÇ¥ ¼³Á¤ m_Center = Pos; // ºÎ¸ð°¡ ÀÖ°í, À籸¼ºµÇ¾î¾ß ÇÒ Ç÷¡±×°¡ ¾ø´Ù¸é, À籸¼ºÀ» ÇÒÁö¸¦ ÆÇ´ÜÇÑ´Ù. if ( m_pParent && !HasSphereNodeFlag( SNF_INTEGRATE ) ) { // ºÎ¸ð¿ÍÀÇ °Å¸®ÀÇ Á¦°ö°ªÀ» °è»êÇÑ´Ù. float fDistance2 = Distance2( m_pParent ); // °Å¸®°¡ ¹ÙÀεù °Å¸®¸¦ ¹þ¾î³­ °æ¿ì if ( fDistance2 >= m_fBindingDistance2 ) { // Àç°è»ê Ç÷¡±×°¡ ¾ø´Ù¸é, ºÎ¸ðÀÇ Å©±â°¡ Àç°è»êµÇ¾î¾ß ÇÑ´Ù. if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) ) { m_pTree->AddRecompute( m_pParent ); } // ºÎ¸ð¿ÍÀÇ ¿¬°áÀ» ²÷°í, ÇØ´ç Root ³ëµå¿¡ ¿¬°áÇÑ´Ù. Unlink(); m_pTree->AddIntegrate( this ); } } } void CCharSphereNode::NewPos( float fX, float fY, float fZ ) { NewPos( Position(fX, fY, fZ) ); } void CCharSphereNode::NewPosRadius( const Position& Pos, float fRadius ) { // »õ·Î¿î ÁÂÇ¥ ¼³Á¤ m_Center = Pos; // ºÎ¸ð°¡ ÀÖ°í, À籸¼ºµÇ¾î¾ß ÇÒ Ç÷¡±×°¡ ¾ø´Ù¸é, À籸¼ºÀ» ÇÒÁö¸¦ ÆÇ´ÜÇÑ´Ù. if ( m_pParent && !HasSphereNodeFlag( SNF_INTEGRATE ) ) { // ¹ÝÁö¸§ÀÌ º¯°æ µÇ¾ú´ÂÁö¸¦ Ã¼Å©ÇØ¼­ º¯°æµÇ¾ú´Ù¸é, // ¹ÝÁö¸§À» ´Ù½Ã ¼³Á¤Çϰí, ¹ÙÀεù °Å¸®¸¦ Àç°è»êÇÑ´Ù. if ( fRadius != GetRadius() ) { SetRadius( fRadius ); ComputeBindingDistance( m_pParent ); } // ºÎ¸ð¿ÍÀÇ °Å¸®ÀÇ Á¦°ö°ªÀ» °è»êÇÑ´Ù. float fDistance2 = Distance2( m_pParent ); // °Å¸®°¡ ¹ÙÀεù °Å¸®¸¦ ¹þ¾î³­ °æ¿ì if ( fDistance2 >= m_fBindingDistance2 ) { // Àç°è»ê Ç÷¡±×°¡ ¾ø´Ù¸é, ºÎ¸ðÀÇ Å©±â°¡ Àç°è»êµÇ¾î¾ß ÇÑ´Ù. if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) ) { m_pTree->AddRecompute( m_pParent ); } // ºÎ¸ð¿ÍÀÇ ¿¬°áÀ» ²÷°í, ÇØ´ç Root ³ëµå¿¡ ¿¬°áÇÑ´Ù. Unlink(); m_pTree->AddIntegrate( this ); } // ÀÚ½ÄÀÌ ºÎ¸ðÀÇ ¹ÙÀεù °Å¸®¾È¿¡ ÀÖÀ» °æ¿ì else { // ºÎ¸ðÀÇ ¹ÙÀεù °Å¸®¸¦ ÁÙÀϼö ÀÖÀ»¼öµµ Àֱ⠶§¹®¿¡, Àç°è»êÀ» ÇÑ´Ù. if ( !m_pParent->HasSphereNodeFlag( SNF_RECOMPUTE ) ) { m_pTree->AddRecompute( m_pParent ); } } } } void CCharSphereNode::NewPosRadius( float fX, float fY, float fZ, float fRadius ) { NewPosRadius( Position(fX, fY, fZ), fRadius ); } float CCharSphereNode::Distance2( const CCharSphereNode* pNode ) { return static_cast( m_Center.GetSquaredDistance( pNode->GetCenter() ) ); } void CCharSphereNode::ComputeBindingDistance( const CCharSphereNode* pParent ) { m_fBindingDistance2 = pParent->GetRadius() - GetRadius(); if ( m_fBindingDistance2 <= 0 ) m_fBindingDistance2 = 0; else m_fBindingDistance2 *= m_fBindingDistance2; } bool CCharSphereNode::Recompute( float fGravy ) { if ( !m_pChildren ) return true; // Á¦°Å ¿ä¸Á if ( HasSphereNodeFlag( SNF_ROOT_NODE ) ) return false; // Root ´Â Àç°è»êÇÏÁö ¾Ê´Â´Ù. Position sumPos; int iCount = 0; // ÀڽĵéÀÇ À§Ä¡¸¦ ¸ðµÎ ´õÇØ¼­ Æò±ÕÀ» ±¸Çؼ­, // »õ·Î¿î Á᫐ ÁÂÇ¥¸¦ °è»êÇØ ³½´Ù. CCharSphereNode* pChild = m_pChildren; while ( pChild ) { sumPos.m_fPointX += pChild->GetCenter().m_fPointX; sumPos.m_fPointY += pChild->GetCenter().m_fPointY; sumPos.m_fPointZ += pChild->GetCenter().m_fPointZ; ++iCount; pChild = pChild->GetNextSibling(); } if ( iCount ) { float fRecip = 1.0f / float(iCount); sumPos.m_fPointX *= fRecip; sumPos.m_fPointY *= fRecip; sumPos.m_fPointZ *= fRecip; Position oldCenter = m_Center; m_Center = sumPos; // »õ·Î ±¸ÇØÁØ Á᫐ ÁÂÇ¥·Î ¼³Á¤ float fMaxRadius = 0; // ÀڽĵéÀÌ Æ÷ÇԵǴ°¡ È®ÀÎÇÑ´Ù. pChild = m_pChildren; while ( pChild ) { float fDistance2 = Distance2( pChild ); float fRadius = sqrtf( fDistance2 ) + pChild->GetRadius(); if ( fRadius > fMaxRadius ) { fMaxRadius = fRadius; if ( (fMaxRadius + fGravy) >= GetRadius() ) { m_Center = oldCenter; ClearShpereNodeFlag( SNF_RECOMPUTE ); return false; } } pChild = pChild->GetNextSibling(); } // ´õ Ä¿Áø ¹ÝÁö¸§À¸·Î Àç ¼³Á¤ fMaxRadius += fGravy; SetRadius( fMaxRadius ); // ÀڽĵéÀÇ ¹ÙÀεù °Å¸®¸¦ Àç °è»ê pChild = m_pChildren; while ( pChild ) { pChild->ComputeBindingDistance( this ); pChild = pChild->GetNextSibling(); } } ClearShpereNodeFlag( SNF_RECOMPUTE ); return false; } CCharSphereTree::CCharSphereTree( int iMaxSphereNode, float fRootSize, float fLeafSize, float fGravy ) : m_fMaxRootSize(fRootSize), m_fMaxLeafSize(fLeafSize), m_fSuperSphereGravy(fGravy) { iMaxSphereNode *= 4; m_Recompute = new CCharSphereNodeFifo( iMaxSphereNode ); m_Integrate = new CCharSphereNodeFifo( iMaxSphereNode ); // Root Tree »ý¼º Position rootPos; m_pRoot = new CCharSphereNode(); m_pRoot->Init( this, rootPos, 65535, NULL ); m_pRoot->SetSphereNodeFlag( eSphereNodeFlag(SNF_ROOT_NODE | SNF_SUPERSPHERE | SNF_ROOT_TREE) ); // Leaf Tree »ý¼º m_pLeaf = new CCharSphereNode(); m_pLeaf->Init( this, rootPos, 16384, NULL ); m_pLeaf->SetSphereNodeFlag( eSphereNodeFlag(SNF_ROOT_NODE | SNF_SUPERSPHERE | SNF_LEAF_TREE) ); } CCharSphereTree::~CCharSphereTree() { DeleteAllChildSphere( m_pRoot ); DeleteAllChildSphere( m_pLeaf ); SAFE_DELETE( m_pRoot ); SAFE_DELETE( m_pLeaf ); SAFE_DELETE( m_Recompute ); SAFE_DELETE( m_Integrate ); m_CharSphereMap.clear(); } void CCharSphereTree::Process() { // Àç°è»ê µÇ¾î¾ß ÇÒ ¸ñ·Ï¿¡ ÀÖ´Â ³ëµå¸¦ Àç°è»êÇÑ´Ù. // ¸¸¾à leaf node °¡ ºÎ¸ð¸¦ ¹þ¾î³µ´Ù¸é, ºÎ¸ð°¡ Àç ±¸¼ºµÇ°Å³ª, ÀÚ½ÄÀÌ ¾ø´Ù¸é, Á¦°ÅµÇ¾î¾ß ÇÑ´Ù. if ( m_Recompute->GetCount() > 0 ) { bool bKill; CCharSphereNode* pTempNode = NULL; int iCount = m_Recompute->GetCount(); for (int i=0; iPop(); if ( !pTempNode ) continue; pTempNode->SetRecomputeFifo( NULL ); bKill = pTempNode->Recompute( m_fSuperSphereGravy ); if ( bKill ) { DeleteSphere( pTempNode ); } } } // À籸¼º µÇ¾î¾ß ÇÒ ¸ñ·Ï¿¡ ÀÖ´Â ³ëµå¸¦ À籸¼ºÇÑ´Ù. if ( m_Integrate->GetCount() > 0 ) { CCharSphereNode* pTempNode = NULL; int iCount = m_Integrate->GetCount(); for (int i=0; iPop(); if ( !pTempNode ) continue; pTempNode->SetIntegrateFifo( NULL ); if ( pTempNode->HasSphereNodeFlag( SNF_ROOT_TREE ) ) Integrate( pTempNode, m_pRoot, m_fMaxRootSize ); // integrate this one single dude against the root node. else Integrate( pTempNode, m_pLeaf, m_fMaxLeafSize ); // integrate this one single dude against the root node. } } } bool CCharSphereTree::AddCharacter( unsigned long dwCID, CCharacter* pCharacter, const Position& Pos ) { CCharSphereNode* pNode = AddSphere( Pos, SphereConst::CHAR_RADIUS, NULL ); if ( pNode ) { pNode->SetCID( dwCID ); pNode->SetCharacter( pCharacter ); pNode->SetSphereNodeFlag( SNF_ACTOR_NODE ); return m_CharSphereMap.insert( std::make_pair(dwCID, pNode) ).second; } return false; } bool CCharSphereTree::DeleteCharacter( unsigned long dwCID ) { CharSphereMap::iterator itr = m_CharSphereMap.find( dwCID ); if ( itr != m_CharSphereMap.end() ) { CCharSphereNode* pNode = itr->second; if ( pNode ) { DeleteSphere( pNode ); } m_CharSphereMap.erase( itr ); return true; } return false; } void CCharSphereTree::MoveTo( unsigned long dwCID, const Position& NewPos ) { CharSphereMap::iterator itr = m_CharSphereMap.find( dwCID ); if ( itr != m_CharSphereMap.end() ) { CCharSphereNode* pNode = itr->second; if ( pNode && pNode->GetCenter() != NewPos ) { pNode->NewPos( NewPos ); } } } CCharSphereNode* CCharSphereTree::AddSphere( const Position& Pos, float fRadius, void* pLink, unsigned long dwFlag ) { // »õ·Î¿î ³ëµå¸¦ ¸¸µç´Ù. CCharSphereNode* pNode = new CCharSphereNode(); assert( pNode ); if ( pNode ) { // Root ¿Í Leaf Áß¿¡ ÇÑÂÊÀÇ ¸â¹ö·Î ºÙ¿©ÁÖ°í, Àç ±¸¼º ¸®½ºÆ®¿¡ ³Ö´Â´Ù. if ( dwFlag & SNF_ROOT_TREE ) { pNode->Init( this, Pos, fRadius, pLink ); pNode->SetSphereNodeFlag( SNF_ROOT_TREE ); AddIntegrate( pNode ); } else { pNode->Init( this, Pos, fRadius, pLink ); pNode->SetSphereNodeFlag( SNF_LEAF_TREE ); AddIntegrate( pNode ); } } return pNode; } void CCharSphereTree::DeleteSphere( CCharSphereNode* pNode ) { // Root node ´Â »ç¿ëÀÚ°¡ Áö¿öÁØ´Ù. if ( pNode->HasSphereNodeFlag( SNF_ROOT_NODE ) ) return; // Leaf node tree ÀÇ supersphere ´Â ¸µÅ©µÈ root node tree ÀÇ node ¸¦ Áö¿öÁØ´Ù. if ( pNode->HasSphereNodeFlag( SNF_SUPERSPHERE ) && pNode->HasSphereNodeFlag( SNF_LEAF_TREE) ) { CCharSphereNode* pLink = (CCharSphereNode*) pNode->GetLink(); DeleteSphere( pLink ); } pNode->Unlink(); SAFE_DELETE( pNode ); } void CCharSphereTree::DeleteAllChildSphere( CCharSphereNode* pRootNode ) { CCharSphereNode* pTempNode = NULL; CCharSphereNode* pChild = pRootNode->GetChildren(); while ( pChild ) { if ( pChild->GetChildCount() ) { DeleteAllChildSphere( pChild ); } pTempNode = pChild; pChild = pChild->GetNextSibling(); SAFE_DELETE( pTempNode ); } } void CCharSphereTree::AddRecompute( CCharSphereNode* pNode ) { if ( !pNode->HasSphereNodeFlag( SNF_RECOMPUTE ) ) { if ( pNode->GetChildCount() ) { pNode->SetSphereNodeFlag( SNF_RECOMPUTE ); CCharSphereNode** ppFifo = m_Recompute->Push( pNode ); pNode->SetRecomputeFifo( ppFifo ); } else { DeleteSphere( pNode ); } } } void CCharSphereTree::AddIntegrate( CCharSphereNode* pNode ) { if ( pNode->HasSphereNodeFlag( SNF_ROOT_TREE ) ) { m_pRoot->AddChild( pNode ); } else { m_pLeaf->AddChild( pNode ); } pNode->SetSphereNodeFlag( SNF_INTEGRATE ); CCharSphereNode** ppFifo = m_Integrate->Push( pNode ); pNode->SetIntegrateFifo( ppFifo ); } void CCharSphereTree::Integrate( CCharSphereNode* pNode, CCharSphereNode* pSuperSphere, float fNodeSize ) { // À籸¼º ´Ü°è ù¹øÂ°·Î pNode ¿Í °¡Àå °¡±îÀÌ ÀÖ´Â SuperSphere ¸¦ ã´Â´Ù. CCharSphereNode* pSearch = pSuperSphere->GetChildren(); CCharSphereNode* pNearestNode1st = NULL; // pNode ¸¦ ¿ÏÀüÈ÷ µÑ·¯½Ò¼ö ÀÖ´Â SuperSphere CCharSphereNode* pNearestNode2nd = NULL; // pNode ¸¦ Ãß°¡Çϱâ À§ÇØ ¾à°£ Å©±â¸¦ Áõ°¡ÇØ¾ß ÇÏ´Â SuperSphere float fNearDist1st2 = 1e9; float fNearDist2nd2 = 1e9; while ( pSearch ) { if ( !pSearch->HasSphereNodeFlag( SNF_ROOT_NODE ) && pSearch->HasSphereNodeFlag( SNF_SUPERSPHERE ) && pSearch->GetChildCount() ) { float fDistance2 = pNode->Distance2( pSearch ); if ( pNearestNode1st ) { // ã¾Æ ³õÀº ¿ÏÀüÈ÷ Æ÷ÇÔÇÏ´Â SuperSphere º¸´Ù ´õ °¡±î¿î ³à¼®À» ãÀº °æ¿ì if ( fDistance2 < fNearDist1st2 ) { float fDist = sqrtf( fDistance2 ) + pNode->GetRadius(); if ( fDist <= pSearch->GetRadius() ) { pNearestNode1st = pSearch; fNearDist1st2 = fDistance2; } } } else { float fDist = sqrtf( fDistance2 ) + pNode->GetRadius() - pSearch->GetRadius(); if ( fDist < fNearDist2nd2 ) { if ( fDist < 0 ) { // ¿ÏÀüÈ÷ Æ÷ÇÔÇÏ´Â SuperSphere ¸¦ ãÀº °æ¿ì pNearestNode1st = pSearch; fNearDist1st2 = fDistance2; } else { // ¿ÏÀüÈ÷ Æ÷ÇÔÇÏÁö´Â ¸øÇÏÁö¸¸, ¹ÝÁö¸§À» Ű¿ö¼­ Æ÷ÇÔÇÒ ¼ö ÀÖ´Â // °¡´É¼ºÀÌ ÀÖ´Â SuperSphere ¸¦ ãÀº °æ¿ì pNearestNode2nd = pSearch; fNearDist2nd2 = fDist; } } } } pSearch = pSearch->GetNextSibling(); } // pNode ¸¦ ¿ÏÀüÈ÷ Æ÷ÇÔÇÒ ¼ö ÀÖ´Â SuperSphere ¸¦ ãÀº °æ¿ì if ( pNearestNode1st ) { // pNode ¸¦ pNearestNode1st ÀÇ ÀÚ½ÄÀ¸·Î ºÙ¿©ÁÖ¸é µÈ´Ù. pNode->Unlink(); pNearestNode1st->AddChild( pNode ); pNearestNode1st->Recompute( m_fSuperSphereGravy ); pNode->ComputeBindingDistance( pNearestNode1st ); // ¸¸¾à leaf node ÀÇ supersphere ¶ó¸é, root tree ÀÇ link node ¶ÇÇÑ ÁÂÇ¥¿Í Å©±â¸¦ °»½ÅÇØÁØ´Ù. if ( pNearestNode1st->HasSphereNodeFlag( SNF_LEAF_TREE ) ) { CCharSphereNode* pLink = (CCharSphereNode*) pNearestNode1st->GetLink(); pLink->NewPosRadius( pNearestNode1st->GetCenter(), pNearestNode1st->GetRadius() ); } } else { bool bCreateNewSphere = true; // Å©±â¸¦ ¾à°£ Ű¿ì¸é pNode ¸¦ Æ÷ÇÔÇÒ ¼ö ÀÖÀ»¸¸ÇÑ SuperSphere ¸¦ ãÀº °æ¿ì if ( pNearestNode2nd ) { float fNewSize = fNearDist2nd2 + pNearestNode2nd->GetRadius() + m_fSuperSphereGravy; if ( fNewSize <= fNodeSize ) { pNode->Unlink(); pNearestNode2nd->SetRadius( fNewSize ); pNearestNode2nd->AddChild( pNode ); pNearestNode2nd->Recompute( m_fSuperSphereGravy ); pNode->ComputeBindingDistance( pNearestNode2nd ); if ( pNearestNode2nd->HasSphereNodeFlag( SNF_LEAF_TREE ) ) { CCharSphereNode* pLink = (CCharSphereNode*) pNearestNode2nd->GetLink(); pLink->NewPosRadius( pNearestNode2nd->GetCenter(), pNearestNode2nd->GetRadius() ); } bCreateNewSphere = false; } } // »õ·Î¿î SuperSphere ¸¦ ¸¸µé¾î¾ß ÇÏ´Â °æ¿ì if ( bCreateNewSphere ) { assert( pSuperSphere->HasSphereNodeFlag( SNF_ROOT_NODE ) ); pNode->Unlink(); CCharSphereNode* pParent = new CCharSphereNode(); assert( pParent ); pParent->Init( this, pNode->GetCenter(), pNode->GetRadius() + m_fSuperSphereGravy, NULL ); if ( pSuperSphere->HasSphereNodeFlag( SNF_ROOT_TREE ) ) { pParent->SetSphereNodeFlag( eSphereNodeFlag(SNF_SUPERSPHERE | SNF_ROOT_TREE) ); } else { pParent->SetSphereNodeFlag( eSphereNodeFlag(SNF_SUPERSPHERE | SNF_LEAF_TREE) ); } pParent->AddChild( pNode ); pSuperSphere->AddChild( pParent ); pParent->Recompute( m_fSuperSphereGravy ); pNode->ComputeBindingDistance( pParent ); if ( pParent->HasSphereNodeFlag( SNF_LEAF_TREE ) ) { // root node ¿¡ link ¸¦ »ý¼ºÇØ¾ß ÇÑ´Ù. CCharSphereNode* pLink = AddSphere( pParent->GetCenter(), pParent->GetRadius(), pParent, SNF_ROOT_TREE ); pParent->SetLink( pLink ); } } } pNode->ClearShpereNodeFlag( SNF_INTEGRATE ); } void CCharSphereNode::RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack ) { float fDist = static_cast( m_Center.GetDistance( centerPos ) ); if ( (fDist - fDistance) > GetRadius() ) return; if ( HasSphereNodeFlag( SNF_SUPERSPHERE ) ) { CCharSphereNode* pNode = m_pChildren; while ( pNode ) { pNode->RangeTest( centerPos, fDistance, pCallBack ); pNode = pNode->GetNextSibling(); } } else { if ( HasSphereNodeFlag( SNF_ROOT_TREE ) ) { CCharSphereNode* pLink = (CCharSphereNode*) GetLink(); if ( pLink ) { pLink->RangeTest( centerPos, fDistance, pCallBack ) ; } } else { pCallBack->RangeTestCallBack( centerPos, fDistance, this ); } } } void CCharSphereTree::RangeTest( const Position& centerPos, float fDistance, ICharSphereTreeCallBack* pCallBack ) { m_pRoot->RangeTest( centerPos, fDistance, pCallBack ); } void CCharSphereNode::SendToRange( const Position& centerPos, float fDistance, const char* szPacket, unsigned long dwPacketSize, unsigned char cCMD_In ) { float fDist = static_cast( m_Center.GetDistance( centerPos ) ); if ( (fDist - fDistance) > GetRadius() ) return; if ( HasSphereNodeFlag( SNF_SUPERSPHERE ) ) { CCharSphereNode* pNode = m_pChildren; while ( pNode ) { pNode->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In ); pNode = pNode->GetNextSibling(); } } else { if ( HasSphereNodeFlag( SNF_ROOT_TREE ) ) { CCharSphereNode* pLink = (CCharSphereNode*) GetLink(); if ( pLink ) { pLink->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In ) ; } } else { // Packet Àü¼Û if (NULL != m_pCharacter) { CGameClientDispatch* lpDispatcher = m_pCharacter->GetDispatcher(); if (NULL != lpDispatcher) { lpDispatcher->GetSendStream().PutBuffer( szPacket, dwPacketSize, cCMD_In ); } } } } } void CCharSphereTree::SendToRange( const Position& centerPos, float fDistance, const char* szPacket, unsigned long dwPacketSize, unsigned char cCMD_In ) { m_pRoot->SendToRange( centerPos, fDistance, szPacket, dwPacketSize, cCMD_In ); }