本文来自http://blog.csdn.net/runaying ,引用必须注明出处!
cocos2d-x节点(b2BroadPhase.h)API
温馨提醒:为了大家能更好学习,强烈推荐大家看看本人的这篇博客 Cocos2d-X权威指南笔记
Box2d中broad-phase用于计算pairs【相交记录】,执行容量查询和光线投射。主要还是调用动态树进行数据方面的管理。
///cocos2d-x-3.0alpha0/external/Box2D/Collision
// Box2d中broad-phase用于计算pairs【相交记录】,执行容量查询和光线投射。主要还是调用动态树进行数据方面的管理。
#ifndef B2_BROAD_PHASE_H
#define B2_BROAD_PHASE_H
#include <Box2D/Common/b2Settings.h>
#include <Box2D/Collision/b2Collision.h>
#include <Box2D/Collision/b2DynamicTree.h>
#include <algorithm>
struct b2Pair
{
int32 proxyIdA;
int32 proxyIdB;
int32 next;
};
// broad-phase用于计算pairs,执行体积查询和光线投射
// broad-phase不会持续pairs.相反,它会汇报新的pairs。这取决于客户端是否用掉新的pairs和是否跟踪后续重叠。
class b2BroadPhase
{
public:
// 空节点代理
enum
{
e_nullProxy = -1
};
b2BroadPhase();
~b2BroadPhase();
///创建一个代理,并用aabb初始化。pairs不会汇报直到UpdatePairs被调用
//参数说明: allocator :soa分配器对象指针
// userData :用户数据
int32 CreateProxy(const b2AABB& aabb, void* userData);
/// 销毁一个代理,任何pairs的删除都取决于客户端
// 参数说明: proxyId :代理id
void DestroyProxy(int32 proxyId);
/**************************************************************************
* 功能描述:移动一个代理。只要你喜欢可以多次调用MoveProxy,
当你完成后调用UpdatePairs用于完成代理pairs(在你的时间步内)
* 参数说明: proxyId :代理id
aabb :aabb变量
displacement :移动坐标向量
* 返 回 值: (void)
***************************************************************************/
void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement);
/// 功能描述: 在下次调用UpdatePairs时,调用一个触发器触发它的pairs
void TouchProxy(int32 proxyId);
/// Get the fat AABB for a proxy(代理).
const b2AABB& GetFatAABB(int32 proxyId) const;
/// 通过一个代理获取userData,如果id无效,返回NULL
void* GetUserData(int32 proxyId) const;
/// Test fat AABBs 的重复部分.
bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const;
/// 获取代理数量
int32 GetProxyCount() const;
/// 更新pairs.结果在pair回调里。只能添加pairs
template <typename T>
void UpdatePairs(T* callback);
// 在重叠代理中查询一个aabb.每个提供aabb重叠的代理将会被回调类调用
template <typename T>
void Query(T* callback, const b2AABB& aabb) const;
///光线投射在树上的代理。
// 这依赖于回调被执行一个精确的光线投射在一个代理包含一个形状
回调也执行任何碰撞过滤,性能大致等于 k * log(n) 其中k是碰撞数量,n是树中的代理服务器的数目
/// @param input 光线投射输入数据。这个光线从p1扩展到p1+maxFraction *(p2 - p1)
/// @param callback 一个回调对象类,当被调用时,光线将会撒到每个代理中。
template <typename T>
void RayCast(T* callback, const b2RayCastInput& input) const;
/// 获取嵌入树的高度
int32 GetTreeHeight() const;
/// 获取嵌入树的平衡值
int32 GetTreeBalance() const;
/// 获取嵌入树的质量,即是树的总aabbs周长与根节点aabb周长的比
float32 GetTreeQuality() const;
private:
//友元类
friend class b2DynamicTree;
// 根据代理id添加代理到移动缓冲区中
void BufferMove(int32 proxyId);
void UnBufferMove(int32 proxyId);
// 查询回调函数
// 参数说明: proxyId :代理id
// 返 回 值: true :表示正常回调
bool QueryCallback(int32 proxyId);
b2DynamicTree m_tree; //动态树声明
int32 m_proxyCount; //代理数量
int32* m_moveBuffer; //移动的缓冲区
int32 m_moveCapacity; //移动缓冲区的总容量
int32 m_moveCount; //需要移动的代理数量
b2Pair* m_pairBuffer; //pair缓冲区
int32 m_pairCapacity; //pair缓冲区中的总容量
int32 m_pairCount; //pair数量
int32 m_queryProxyId; //查询代理id
};
/// 这是用来排序 pairs 的.
inline bool b2PairLessThan(const b2Pair& pair1, const b2Pair& pair2)
{
//比对pair的代理idA
if (pair1.proxyIdA < pair2.proxyIdA)
{
return true;
}
//再比对代理idB
if (pair1.proxyIdA == pair2.proxyIdA)
{
return pair1.proxyIdB < pair2.proxyIdB;
}
return false;
}
//根据代理id获取userData
inline void* b2BroadPhase::GetUserData(int32 proxyId) const
{
return m_tree.GetUserData(proxyId);
}
//测试重叠
inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const
{
const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA);
const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB);
return b2TestOverlap(aabbA, aabbB);
}
//获取aabb
inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const
{
return m_tree.GetFatAABB(proxyId);
}
//获取代理数量
inline int32 b2BroadPhase::GetProxyCount() const
{
return m_proxyCount;
}
//获取树的高度
inline int32 b2BroadPhase::GetTreeHeight() const
{
return m_tree.GetHeight();
}
//获取树的平衡值
inline int32 b2BroadPhase::GetTreeBalance() const
{
return m_tree.GetMaxBalance();
}
//获取树的质量
inline float32 b2BroadPhase::GetTreeQuality() const
{
return m_tree.GetAreaRatio();
}
//更新pairs
template <typename T>
void b2BroadPhase::UpdatePairs(T* callback)
{
// 复位 pair 缓冲区
m_pairCount = 0;
//执行树查询所有移动代理。
for (int32 i = 0; i < m_moveCount; ++i)
{
m_queryProxyId = m_moveBuffer[i];
if (m_queryProxyId == e_nullProxy)
{
continue;
}
//我们使用 fat AABB 查询树,所以我们就无法创建一个可以在随后碰到的 pair
const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId);
// Query tree ,创建他们,并把他们添加到 pair 缓冲区。
m_tree.Query(this, fatAABB);
}
//复位move缓冲
m_moveCount = 0;
//对缓冲区进行排序来查找重复的
std::sort(m_pairBuffer, m_pairBuffer + m_pairCount, b2PairLessThan);
// 把 pair 返回给客户端
int32 i = 0;
while (i < m_pairCount)
{
b2Pair* primaryPair = m_pairBuffer + i;
//根据相交记录
void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA);
void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB);
callback->AddPair(userDataA, userDataB);
++i;
//跳过任何重复的对。
while (i < m_pairCount)
{
b2Pair* pair = m_pairBuffer + i;
if (pair->proxyIdA != primaryPair->proxyIdA || pair->proxyIdB != primaryPair->proxyIdB)
{
break;
}
++i;
}
}
//尽量保持树的平衡。
//m_tree.Rebalance(4);
}
//区域查询
template <typename T>
inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const
{
m_tree.Query(callback, aabb);
}
//光线投射
template <typename T>
inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const
{
m_tree.RayCast(callback, input);
}
#endif