目錄
1.簡介
2.樹的結構
3.構造原則
4.重要介面
5.示例
6.壓測
7.更新
最近在研究四叉樹的二維空間碰撞檢測,隨筆記錄一下
四叉樹顧名思義,就是每科樹都包含4個分支,每個分支可以看做乙個區域象限,用來存放一些資料的空間索引
這裡只討論四叉樹在二維空間的碰撞檢測,unity的實現方式
// 區域象限定義
public enum quadranttype
public enum quadrantbittype
public inte***ce irect
/// /// 矩形的中心座標y
///
float y
/// /// 矩形的寬
///
float width
/// /// 矩形的高
///
float height
}public inte***ce imark
}public class qtreecomparer: icomparer> where t : irect
}// 四叉樹結構
public class qtree: irect where t : irect
public float y
public float width
public float height
public int depth; // 樹的深度
public int childcount; // 物件數量
public bool isleaf; // 是否葉子節點
public listchildlist; // 物件引用
public qtree childnodes; // 子節點陣列(4個)
public qtree()
public qtree(int depth)
private void init()
public void initrect(float x, float y, float width, float height)
public void clear()
else
childnodes = null;}}
}
1.預設構造的qtree樹節點都是葉子節點
2.物件只會放入葉子節點
3.每個葉子節點可以存放的物件上限是 maxchildcount,下同(在深度沒有達到最大值的情況下,否則不限)
4.當葉子節點存放的物件數量超過 maxchildcount,則分離生成子樹(4個區域象限),並把自身儲存的所有物件存放到子樹中,然後標記為非葉子節點,清除自身所有儲存的物件引用
5.根據物件的座標及寬高插入qtree樹中(邊界物件可能會加入多個qtree樹中)
/// /// 插入四叉樹
///
public void insertqtree(qtreenode, t t) where t : irect, imark
else
}else}}
/// /// 分離樹(象限)
///
private void splitqtree(qtreenode) where t : irect, imark
}/// /// 建立子樹(葉子節點)
///
private qtreecreatechildnode(float x, float y, float width, float height, int depth) where t : irect, imark
/// /// 查詢樹,並返回包含所有樹節點的列表
///
public void queryqtreeretrunlist(qtreenode, ref list> qtreelist) where t : irect, imark}}
/// /// 查詢樹,並返回包含所有樹節點的列表(按depth公升序排列)
///
public void queryqtreereturnriselist(qtreenode, ref list> qtreelist) where t : irect, imark
/// /// 獲取目標所在的象限索引列表
///
public int gettargetquadrantindex(qtreenode, t target) where t : irect, imark
if (isright)
return indexs;
}/// /// 返回目標周圍的可能碰撞物件列表
///
public void findtargetaroundobjs(qtreenode, t target) where t : irect, imark
}else}}
如上圖:黃色方塊為跟隨滑鼠移動的目標物件,綠色方塊為待與黃色方塊做碰撞計算的物件,紅色方塊為已發生碰撞的物件
下圖為最大深度4、根節點深度1,10000個物件的插入、查詢測試:
如上圖:10000個物件的四叉樹插入平均耗時14ms,查詢計算物件700多個大概5ms,300多個大概1.5ms
優化了如下兩個介面,移除了list造成的gc
1.優化了gettargetquadrantindex介面,移除了原有返回的list,改為int,位列舉儲存
2.新增了imark介面:用來標記待比較物件,findtargetaroundobjs後,在呼叫段通過for迴圈找出所有的待比較物件
呼叫段示例:
public class element : irect, imark
public colortype color
public bool ismoving
public float from_x
public float from_y
public float to_x
public float to_y
public float duration
public float x
public float y
public float width
public float height
public int mark
private float factorspeed;
private float factor;
public void init(int id, float x, float y, float width, float height)
public void move(float from_x, float from_y, float to_x, float to_y, float duration)
, duration = , from_x = , from_y = , to_x = , to_y = ");
this.from_x = from_x;
this.from_y = from_y;
this.to_x = to_x;
this.to_y = to_y;
this.duration = duration;
ismoving = true;
factorspeed = 1f / duration;
factor = 0;
x = from_x;
y = from_y;
}public void update(float deltatime)
else
}}
private void findtargetaroundobjs()
}if (objs != null && objs.count > 0)
calculatecollision(mouseuielement.m_element, objs);
for (int i = 0; i < muielementlist.count; ++i)
}else
resetelementcolor();
mouseuielement.setvisable(checkoutiscollision(mouseuielement.m_element, rootelement));
}
詳見原始碼: Unity學習 十三 場景優化之四叉樹
四叉樹是在二維中定位畫素的唯一適合的演算法。因為二維空間 圖經常被描述的方式 中,平面畫素可以重複的被分為四部分,樹的深度由 計算機記憶體和圖形的複雜度決定。四叉樹 quad tree 是一種資料結構,是一種每個節點最多有四個子樹的資料結構。四叉樹可以用來在資料庫中放置和定位檔案 稱作記錄或鍵 這一...
四叉樹與八叉樹
前序 四叉樹或四元樹也被稱為q樹 q tree 四叉樹廣泛應用於影象處理 空間資料索引 2d中的快速碰撞檢測 儲存稀疏資料等,而八叉樹 octree 主要應用於3d圖形處理。對遊戲程式設計,這會很有用。本文著重於對四叉樹與八叉樹的原理與結構的介紹,幫助您在腦海中建立四叉樹與八叉樹的基本思想。本文並不...
四叉樹與八叉樹
前序 四叉樹或四元樹也被稱為q樹 q tree 四叉樹廣泛應用於影象處理 空間資料索引 2d中的快速碰撞檢測 儲存稀疏資料等,而八叉樹 octree 主要應用於3d圖形處理。對遊戲程式設計,這會很有用。本文著重於對四叉樹與八叉樹的原理與結構的介紹,幫助您在腦海中建立四叉樹與八叉樹的基本思想。本文並不...