Go to the documentation of this file.00001 using System;
00002 using System.Collections.Generic;
00003 using Microsoft.Xna.Framework;
00004 using Microsoft.Xna.Framework.Graphics;
00005
00006 namespace XnaCollisionLib
00007 {
00008 public class OctTree
00009 {
00010 private List<Triangle> _Triangles;
00011 private OctTree[] _Children;
00012 private BoundingBox _Box;
00013 private int _Count;
00014
00015 private OctTree()
00016 {
00017 _Triangles = new List<Triangle>();
00018 _Children = new OctTree[8];
00019 for (int i = 0; i != _Children.Length; i++)
00020 _Children[i] = null;
00021 _Box = new BoundingBox();
00022 _Count = 0;
00023 }
00024
00025 private int CountTriangles()
00026 {
00027 int count = _Triangles.Count;
00028
00029 foreach (OctTree node in _Children)
00030 if (node != null)
00031 count += node.CountTriangles();
00032 return count;
00033 }
00034
00035 public int Count
00036 {
00037 get { return _Count; }
00038 }
00039
00040 public Nullable<float> ISect(Ray ray, ref float nearestDistance, ref Triangle nearestTriangle)
00041 {
00042 Nullable<float> t = ray.Intersects(_Box);
00043
00044 if (t.HasValue && t.Value >= 0 && t.Value < nearestDistance)
00045 {
00046 t = null;
00047
00048 foreach (Triangle triangle in _Triangles)
00049 {
00050 Nullable<float> t2 = triangle.ISect(ray);
00051
00052 if (t2.HasValue && t2.Value >= 0 && t2.Value < nearestDistance)
00053 {
00054 nearestDistance = t2.Value;
00055 nearestTriangle = triangle;
00056 t = t2;
00057 }
00058 }
00059 foreach (OctTree node in _Children)
00060 if (node != null)
00061 {
00062 Nullable<float> t2 = node.ISect(ray, ref nearestDistance, ref nearestTriangle);
00063
00064 if (t2.HasValue)
00065 t = t2;
00066 }
00067 }
00068 return t;
00069 }
00070
00071 public void Query(BoundingBox box, List<Triangle> triangles, Matrix transform)
00072 {
00073 if (_Box.Contains(box) == ContainmentType.Disjoint)
00074 return;
00075
00076 foreach (Triangle triangle in _Triangles)
00077 triangles.Add(new Triangle(triangle, transform));
00078 foreach (OctTree node in _Children)
00079 if (node != null)
00080 node.Query(box, triangles, transform);
00081 }
00082
00083 public static OctTree Create(IEnumerable<Triangle> triangles, int minTrianglesPerNode)
00084 {
00085 OctTree node = new OctTree();
00086
00087 node._Triangles.AddRange(triangles);
00088 Create(node, minTrianglesPerNode);
00089 node._Count = node.CountTriangles();
00090
00091 return node;
00092 }
00093
00094 private static void Create(OctTree node, int minTrianglesPerNode)
00095 {
00096 node._Box.Min = node._Box.Max = node._Triangles[0].A;
00097 for (int i = 0; i != node._Triangles.Count; i++)
00098 {
00099 CollisionHelper.AddToBox(ref node._Box, node._Triangles[i].A);
00100 CollisionHelper.AddToBox(ref node._Box, node._Triangles[i].B);
00101 CollisionHelper.AddToBox(ref node._Box, node._Triangles[i].C);
00102 }
00103 if (node._Triangles.Count < minTrianglesPerNode)
00104 return;
00105
00106 Vector3 center = (node._Box.Max + node._Box.Min) / 2;
00107 Vector3[] corners = node._Box.GetCorners();
00108 List<Triangle> keepTriangles = new List<Triangle>();
00109
00110 for (int i = 0; i != 8; i++)
00111 {
00112 node._Children[i] = new OctTree();
00113 node._Children[i]._Box.Min = node._Children[i]._Box.Max = center;
00114 CollisionHelper.AddToBox(ref node._Children[i]._Box, corners[i]);
00115 for (int j = 0; j != node._Triangles.Count; j++)
00116 if (node._Children[i]._Box.Contains(node._Triangles[j].A) != ContainmentType.Disjoint &&
00117 node._Children[i]._Box.Contains(node._Triangles[j].B) != ContainmentType.Disjoint &&
00118 node._Children[i]._Box.Contains(node._Triangles[j].C) != ContainmentType.Disjoint)
00119 node._Children[i]._Triangles.Add(node._Triangles[j]);
00120 else
00121 keepTriangles.Add(node._Triangles[j]);
00122 node._Triangles = new List<Triangle>(keepTriangles);
00123 keepTriangles.Clear();
00124 if (node._Children[i]._Triangles.Count == 0)
00125 node._Children[i] = null;
00126 else
00127 Create(node._Children[i], minTrianglesPerNode);
00128 }
00129 }
00130 }
00131 }