QuadTree.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // QuadTree.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Text;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Content;
  15. using Microsoft.Xna.Framework.Graphics;
  16. using RobotGameData.GameObject;
  17. using RobotGameData.Helper;
  18. #endregion
  19. namespace RobotGameData.Collision
  20. {
  21. /// <summary>
  22. /// This is a quad tree only colliding. not support render model.
  23. /// </summary>
  24. public class QuadTree
  25. {
  26. /// <summary>
  27. /// quad tree area.
  28. /// </summary>
  29. enum IntersectionType
  30. {
  31. UpperLeft = 0,
  32. UpperRight,
  33. LowerLeft,
  34. LowerRight,
  35. }
  36. #region Fields
  37. protected QuadNode rootNode = null;
  38. protected int nodeCount = 0;
  39. protected int depthLevel = 0;
  40. #endregion
  41. #region Properties
  42. public QuadNode RootNode
  43. {
  44. get { return rootNode; }
  45. }
  46. public int NodeCount
  47. {
  48. get { return nodeCount; }
  49. }
  50. public int DepthLevel
  51. {
  52. get { return depthLevel; }
  53. }
  54. #endregion
  55. /// <summary>
  56. /// build a quad tree.
  57. /// </summary>
  58. /// <param name="vertices">vertex array</param>
  59. /// <param name="depthLevel">quad tree depth count</param>
  60. /// <returns></returns>
  61. public int Build(Vector3[] vertices, int depthLevel)
  62. {
  63. this.depthLevel = depthLevel;
  64. rootNode = BuildNode(vertices, depthLevel);
  65. rootNode.Name = "QUADTREE: root node";
  66. return nodeCount;
  67. }
  68. /// <summary>
  69. /// build a quad node.
  70. /// </summary>
  71. /// <param name="vertices">vertex array</param>
  72. /// <param name="depthLevel">quad tree depth count</param>
  73. /// <returns>new quad node</returns>
  74. protected QuadNode BuildNode(Vector3[] vertices, int depthLevel)
  75. {
  76. QuadNode newNode = null;
  77. Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
  78. Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue);
  79. float centerX = 0.0f;
  80. float centerZ = 0.0f;
  81. IntersectionType[] Intersection = new IntersectionType[3];
  82. // checks min and max of vertices
  83. for (int i = 0; i < vertices.Length; i++)
  84. {
  85. if (min.X > vertices[i].X) min.X = vertices[i].X;
  86. if (min.Y > vertices[i].Y) min.Y = vertices[i].Y;
  87. if (min.Z > vertices[i].Z) min.Z = vertices[i].Z;
  88. if (max.X < vertices[i].X) max.X = vertices[i].X;
  89. if (max.Y < vertices[i].Y) max.Y = vertices[i].Y;
  90. if (max.Z < vertices[i].Z) max.Z = vertices[i].Z;
  91. }
  92. centerX = (max.X + min.X) / 2;
  93. centerZ = (max.Z + min.Z) / 2;
  94. // creates node
  95. newNode = new QuadNode(min, max);
  96. newNode.Depth = this.depthLevel - depthLevel;
  97. nodeCount++;
  98. if (depthLevel-- > 0)
  99. {
  100. List<Vector3> upperLeftVertexList = new List<Vector3>();
  101. List<Vector3> upperRightVertexList = new List<Vector3>();
  102. List<Vector3> lowerLeftVertexList = new List<Vector3>();
  103. List<Vector3> lowerRightVertexList = new List<Vector3>();
  104. List<Vector3> medlineVertexList = new List<Vector3>();
  105. // vertex count
  106. for (int count = 0; count < vertices.Length; count += 3)
  107. {
  108. // Triangle
  109. for (int i = 0; i < 3; i++)
  110. {
  111. // inside upper left
  112. if (vertices[count + i].X < centerX &&
  113. vertices[count + i].Z < centerZ)
  114. {
  115. Intersection[i] = IntersectionType.UpperLeft;
  116. }
  117. // inside upper right
  118. else if (vertices[count + i].X > centerX &&
  119. vertices[count + i].Z < centerZ)
  120. {
  121. Intersection[i] = IntersectionType.UpperRight;
  122. }
  123. // inside lower left
  124. else if (vertices[count + i].X < centerX &&
  125. vertices[count + i].Z > centerZ)
  126. {
  127. Intersection[i] = IntersectionType.LowerLeft;
  128. }
  129. // inside lower right
  130. else if (vertices[count + i].X > centerX &&
  131. vertices[count + i].Z > centerZ)
  132. {
  133. Intersection[i] = IntersectionType.LowerRight;
  134. }
  135. }
  136. // intersecting with upper left area
  137. if (Intersection[0] == IntersectionType.UpperLeft &&
  138. Intersection[1] == IntersectionType.UpperLeft &&
  139. Intersection[2] == IntersectionType.UpperLeft)
  140. {
  141. upperLeftVertexList.Add(vertices[count + 0]);
  142. upperLeftVertexList.Add(vertices[count + 1]);
  143. upperLeftVertexList.Add(vertices[count + 2]);
  144. }
  145. // intersecting with upper right area
  146. else if (Intersection[0] == IntersectionType.UpperRight &&
  147. Intersection[1] == IntersectionType.UpperRight &&
  148. Intersection[2] == IntersectionType.UpperRight)
  149. {
  150. upperRightVertexList.Add(vertices[count + 0]);
  151. upperRightVertexList.Add(vertices[count + 1]);
  152. upperRightVertexList.Add(vertices[count + 2]);
  153. }
  154. // intersecting with lower left area
  155. else if (Intersection[0] == IntersectionType.LowerLeft &&
  156. Intersection[1] == IntersectionType.LowerLeft &&
  157. Intersection[2] == IntersectionType.LowerLeft)
  158. {
  159. lowerLeftVertexList.Add(vertices[count + 0]);
  160. lowerLeftVertexList.Add(vertices[count + 1]);
  161. lowerLeftVertexList.Add(vertices[count + 2]);
  162. }
  163. // intersecting with lower right area
  164. else if (Intersection[0] == IntersectionType.LowerRight &&
  165. Intersection[1] == IntersectionType.LowerRight &&
  166. Intersection[2] == IntersectionType.LowerRight)
  167. {
  168. lowerRightVertexList.Add(vertices[count + 0]);
  169. lowerRightVertexList.Add(vertices[count + 1]);
  170. lowerRightVertexList.Add(vertices[count + 2]);
  171. }
  172. // intersecting with medline
  173. else
  174. {
  175. medlineVertexList.Add(vertices[count + 0]);
  176. medlineVertexList.Add(vertices[count + 1]);
  177. medlineVertexList.Add(vertices[count + 2]);
  178. }
  179. }
  180. string prefix = String.Empty;
  181. for (int i = 0; i < this.depthLevel - depthLevel; i++) prefix += "- ";
  182. // upper left
  183. if (upperLeftVertexList.Count > 0)
  184. {
  185. newNode.UpperLeftNode =
  186. BuildNode(upperLeftVertexList.ToArray(), depthLevel);
  187. newNode.UpperLeftNode.Parent = newNode;
  188. newNode.UpperLeftNode.Name = "QUADTREE: " + prefix + "UL ";
  189. if (newNode.UpperLeftNode.IsLeafNode )
  190. newNode.UpperLeftNode.Name += "leaf";
  191. else
  192. newNode.UpperLeftNode.Name += "node";
  193. }
  194. // upper right
  195. if (upperRightVertexList.Count > 0)
  196. {
  197. newNode.UpperRightNode =
  198. BuildNode(upperRightVertexList.ToArray(), depthLevel);
  199. newNode.UpperRightNode.Parent = newNode;
  200. newNode.UpperRightNode.Name = "QUADTREE: " + prefix + "UR ";
  201. if (newNode.UpperRightNode.IsLeafNode )
  202. newNode.UpperRightNode.Name += "leaf";
  203. else
  204. newNode.UpperRightNode.Name += "node";
  205. }
  206. // lower left
  207. if (lowerLeftVertexList.Count > 0)
  208. {
  209. newNode.LowerLeftNode =
  210. BuildNode(lowerLeftVertexList.ToArray(), depthLevel);
  211. newNode.LowerLeftNode.Parent = newNode;
  212. newNode.LowerLeftNode.Name = "QUADTREE: " + prefix + "LL ";
  213. if (newNode.LowerLeftNode.IsLeafNode )
  214. newNode.LowerLeftNode.Name += "leaf";
  215. else
  216. newNode.LowerLeftNode.Name += "node";
  217. }
  218. // lower right
  219. if (lowerRightVertexList.Count > 0)
  220. {
  221. newNode.LowerRightNode =
  222. BuildNode(lowerRightVertexList.ToArray(), depthLevel);
  223. newNode.LowerRightNode.Parent = newNode;
  224. newNode.LowerRightNode.Name = "QUADTREE: " + prefix + "LR ";
  225. if (newNode.LowerRightNode.IsLeafNode )
  226. newNode.LowerRightNode.Name += "leaf";
  227. else
  228. newNode.LowerRightNode.Name += "node";
  229. }
  230. // intersecting with medline
  231. if (medlineVertexList.Count > 0)
  232. {
  233. newNode.CreateVertices(medlineVertexList.ToArray());
  234. }
  235. }
  236. else
  237. {
  238. newNode.CreateVertices(vertices);
  239. }
  240. return newNode;
  241. }
  242. /// <summary>
  243. /// display build information to debug output window.
  244. /// </summary>
  245. /// <returns>total vertex count</returns>
  246. public int Dump()
  247. {
  248. int vertexCount = 0;
  249. vertexCount = this.rootNode.Dump();
  250. System.Diagnostics.Debug.WriteLine(
  251. "QUADTREE: total vertex count = " + vertexCount);
  252. return vertexCount;
  253. }
  254. /// <summary>
  255. /// Finds a contaning quad node.
  256. /// </summary>
  257. public QuadNode GetNodeContaining(ref CollideElement bounds)
  258. {
  259. if (rootNode != null)
  260. {
  261. if (rootNode.Contains(ref bounds) )
  262. return rootNode.GetNodeContaining(ref bounds);
  263. }
  264. return null;
  265. }
  266. }
  267. }