cococococos 2 d-xノード(b 2 DynamicTree.h)API


本論文はhttp://blog.csdn.net/runaying ,引用は出典を明記しなければならない!
cococococos 2 d-xノード(b 2 DynamicTree.h)API
みなさんがよりよく勉強できるように、私のブログを見ることを強くおすすめします. Cocos 2 d-X権威ガイドノート
//システムの衝突検出の速度を上げるために使用します.
//主にユーザーデータを操作して軸を揃えて取り囲むボックス(axis-alignedbounding bounding boxes、AABBs)を操作して、ツリーの様々な操作を完成します.また、AABBツリーから受け継いで、ツリー上の各ノードには子供が二人います.リーフノードは単独のユーザーAABBです.不活性入力でも、全体の数字は回転でバランスを維持できます.
///cocos2d-x-3.0alpha0/external/Box2D/Collision
//              。
//                   (axis-alignedbounding boxes,AABBs)         。        AABB ,              。           AABB。       ,              。

#ifndef B2_DYNAMIC_TREE_H
#define B2_DYNAMIC_TREE_H

#include <Box2D/Collision/b2Collision.h>
#include <Box2D/Common/b2GrowableStack.h>
//     
#define b2_nullNode (-1)

///         ,        
struct b2TreeNode
{
    //       
    bool IsLeaf() const
    {
        return child1 == b2_nullNode;
    }
    
    /// Enlarged AABB
    //  aabb  
    b2AABB aabb;
    //    
    void* userData;
    //     (  )       (  )
    //                  ,   n          
    //               。    ,         
    union
    {
        int32 parent;
        int32 next;
    };
    //      
    int32 child1;
    int32 child2;
    //        0,       -1
    // leaf = 0, free node = -1
    int32 height;
};

//  AABB broad-phase,     Nathanael Presson's btDbvt.
//                              。               
//      b2_fatAABBFactor   aabb  ,  aabb          。           
//        
//         ,               
class b2DynamicTree
{
public:
    ///     ,         
    b2DynamicTree();
    
    ///      ,        
    ~b2DynamicTree();
    
    ///             
    // *     :aabb    :aabb  
    //             user    :   
    // *      :          ,          .
    int32 CreateProxy(const b2AABB& aabb, void* userData);
    //       ,  id     
    //     *     :poxyid :  id
    //     *      :          ,         
    void DestroyProxy(int32 proxyId);
    
    //          AABB,            AABB  
    //                           。  ,       
    // *     :proxyId     :    id
    //             aabb        : aabb  
    //             displacement:      
    // *      : true :    
    //              false:    
    bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement);
    
    //  *     :       userData
    // *     :proxyId:    id
    // *      :id  ,     userData
    //             id  ,  0
    void* GetUserData(int32 proxyId) const;
    
    // *     :         AABB
    // *     :proxyId:    id
    // *      :aabb  
    const b2AABB& GetFatAABB(int32 proxyId) const;
    
    //  *     :callback :    
    //             aabb     :    aabb
    // *      :aabb  
    template <typename T>
    void Query(T* callback, const b2AABB& aabb) const;
    
    //  *     :             。
    //                                          
    //                          。
    //                   k * log(n),  k      ,n        
    // *     :callback :     ,                
    //             input    :        ,    p1 + maxFraction * (p2 - p1)
    template <typename T>
    void RayCast(T* callback, const b2RayCastInput& input) const;
    
    ///      ,    
    void Validate() const;
    
    //  O(N)           ,       
    int32 GetHeight() const;
    
    ///              。               
    int32 GetMaxBalance() const;
    
    ///               
    float32 GetAreaRatio() const;
    
    ///        ,    ,    
    // *     :(void)
    // *      :             
    void RebuildBottomUp();
    
private:
    
    int32 AllocateNode();                                       //           .         
    void FreeNode(int32 node);                          //    
    
    void InsertLeaf(int32 node);                        //      
    void RemoveLeaf(int32 node);                        //    
    
    int32 Balance(int32 index);                 //    a   ,               *     :iA :           *      :        
    
    
    int32 ComputeHeight() const;                //      
    int32 ComputeHeight(int32 nodeId) const;       //              *     :nodeid:      
    
    
    void ValidateStructure(int32 index) const;      //          *     :index:      
    void ValidateMetrics(int32 index) const;        //            *     :index:      
    
    int32 m_root;                   //     (    )
    
    b2TreeNode* m_nodes;             //        ,              
    int32 m_nodeCount;                //      
    int32 m_nodeCapacity;            //          
    
    int32 m_freeList;            //      
    
    /// //            
    uint32 m_path;
    
    int32 m_insertionCount;      //         
};
//    id  userData
inline void* b2DynamicTree::GetUserData(int32 proxyId) const
{
    //    id    
    b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
    return m_nodes[proxyId].userData;
}
//    id     AABB
inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const
{
    //    id    
    b2Assert(0 <= proxyId && proxyId < m_nodeCapacity);
    return m_nodes[proxyId].aabb;
}
//    aabb    ,      AABB          
template <typename T>
inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const
{
    //     ,     
    b2GrowableStack<int32, 256> stack;
    stack.Push(m_root);
    //      
    while (stack.GetCount() > 0)
    {
        //    id
        int32 nodeId = stack.Pop();
        if (nodeId == b2_nullNode)
        {
            //           
            continue;
        }
        //    
        const b2TreeNode* node = m_nodes + nodeId;
        //    
        if (b2TestOverlap(node->aabb, aabb))
        {
            //       
            if (node->IsLeaf())
            {
                //    
                bool proceed = callback->QueryCallback(nodeId);
                if (proceed == false)
                {
                    return;
                }
            }
            else
            {
                //        
                stack.Push(node->child1);
                stack.Push(node->child2);
            }
        }
    }
}
//    
template <typename T>
inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const
{
    b2Vec2 p1 = input.p1;
    b2Vec2 p2 = input.p2;
    b2Vec2 r = p2 - p1;
    b2Assert(r.LengthSquared() > 0.0f);
    r.Normalize();
    
    //v     r
    b2Vec2 v = b2Cross(1.0f, r);
    b2Vec2 abs_v = b2Abs(v);
    //          p80
    // 《Collision Detection in Interactive 3D Environments》 by Gino van den Bergen
    // 【  http://download.csdn.net/detail/cg0206/4875309   】
    //      :|dot(v, p1 - c)| > dot(|v|, h)
    
    float32 maxFraction = input.maxFraction;
    
    //               
    b2AABB segmentAABB;
    {
        b2Vec2 t = p1 + maxFraction * (p2 - p1);
        segmentAABB.lowerBound = b2Min(p1, t);
        segmentAABB.upperBound = b2Max(p1, t);
    }
    //       ,       
    b2GrowableStack<int32, 256> stack;
    stack.Push(m_root);
    //    
    while (stack.GetCount() > 0)
    {
        //  
        int32 nodeId = stack.Pop();
        if (nodeId == b2_nullNode)
        {
            //           
            continue;
        }
        //          
        const b2TreeNode* node = m_nodes + nodeId;
        //  AABB
        if (b2TestOverlap(node->aabb, segmentAABB) == false)
        {
            continue;
        }
        
        // Separating axis for segment (Gino, p80).             // //     p80
        // |dot(v, p1 - c)| > dot(|v|, h)
        b2Vec2 c = node->aabb.GetCenter();
        b2Vec2 h = node->aabb.GetExtents();
        float32 separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h);
        if (separation > 0.0f)
        {
            continue;
        }
        //       
        if (node->IsLeaf())
        {
            b2RayCastInput subInput;
            subInput.p1 = input.p1;
            subInput.p2 = input.p2;
            subInput.maxFraction = maxFraction;
            
            float32 value = callback->RayCastCallback(subInput, nodeId);
            
            if (value == 0.0f)
            {
                //          
                return;
            }
            
            if (value > 0.0f)
            {
                //          
                maxFraction = value;
                b2Vec2 t = p1 + maxFraction * (p2 - p1);
                segmentAABB.lowerBound = b2Min(p1, t);
                segmentAABB.upperBound = b2Max(p1, t);
            }
        }
        else
        {
            //         
            stack.Push(node->child1);
            stack.Push(node->child2);
        }
    }
}

#endif