├── .gitattributes ├── .gitignore ├── Assets ├── Scenes │ └── main.unity └── Scripts │ ├── Extensions.cs │ ├── GLDraw.cs │ ├── Octree │ ├── IOctree.cs │ ├── Octree.cs │ ├── OctreeBox.cs │ ├── OctreeLeaf.cs │ └── OctreeNode.cs │ └── OctreeTest.cs ├── Octree ├── .gitattributes └── .gitignore └── ProjectSettings ├── AudioManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshLayers.asset ├── NetworkManager.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── TagManager.asset └── TimeManager.asset /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | _ReSharper*/ 5 | 6 | # Autogenerated VS/MD solution and project files 7 | *.csproj 8 | *.unityproj 9 | *.sln 10 | *.pidb 11 | *.suo 12 | *.userprefs -------------------------------------------------------------------------------- /Assets/Scenes/main.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/Assets/Scenes/main.unity -------------------------------------------------------------------------------- /Assets/Scripts/Extensions.cs: -------------------------------------------------------------------------------- 1 |  2 | using UnityEngine; 3 | 4 | public static class Extensions 5 | { 6 | public static bool Contains(this Bounds b, Bounds other) 7 | { 8 | return b.Contains(other.min) && b.Contains(other.max); 9 | } 10 | 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Assets/Scripts/GLDraw.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class GLDraw 4 | { 5 | /* 6 | * Clipping code: http://forum.unity3d.com/threads/17066-How-to-draw-a-GUI-2D-quot-line-quot?p=230386#post230386 7 | * Thick line drawing code: http://unifycommunity.com/wiki/index.php?title=VectorLine 8 | */ 9 | protected static bool clippingEnabled; 10 | protected static Rect clippingBounds; 11 | public static Material lineMaterial = null; 12 | 13 | /* @ Credit: "http://cs-people.bu.edu/jalon/cs480/Oct11Lab/clip.c" */ 14 | protected static bool clip_test(float p, float q, ref float u1, ref float u2) 15 | { 16 | float r; 17 | bool retval = true; 18 | 19 | if (p < 0.0) 20 | { 21 | r = q / p; 22 | if (r > u2) 23 | retval = false; 24 | else if (r > u1) 25 | u1 = r; 26 | } 27 | else if (p > 0.0) 28 | { 29 | r = q / p; 30 | if (r < u1) 31 | retval = false; 32 | else if (r < u2) 33 | u2 = r; 34 | } 35 | else if (q < 0.0) 36 | retval = false; 37 | 38 | return retval; 39 | } 40 | 41 | protected static bool segment_rect_intersection(Rect bounds, ref Vector2 p1, ref Vector2 p2) 42 | { 43 | float u1 = 0.0f, u2 = 1.0f, dx = p2.x - p1.x, dy; 44 | 45 | if (clip_test(-dx, p1.x - bounds.xMin, ref u1, ref u2)) 46 | { 47 | if (clip_test(dx, bounds.xMax - p1.x, ref u1, ref u2)) 48 | { 49 | dy = p2.y - p1.y; 50 | if (clip_test(-dy, p1.y - bounds.yMin, ref u1, ref u2)) 51 | { 52 | if (clip_test(dy, bounds.yMax - p1.y, ref u1, ref u2)) 53 | { 54 | if (u2 < 1.0) 55 | { 56 | p2.x = p1.x + u2 * dx; 57 | p2.y = p1.y + u2 * dy; 58 | } 59 | 60 | if (u1 > 0.0) 61 | { 62 | p1.x += u1 * dx; 63 | p1.y += u1 * dy; 64 | } 65 | return true; 66 | } 67 | } 68 | } 69 | } 70 | return false; 71 | } 72 | 73 | public static void BeginGroup(Rect position) 74 | { 75 | clippingEnabled = true; 76 | clippingBounds = new Rect(0, 0, position.width, position.height); 77 | GUI.BeginGroup(position); 78 | } 79 | 80 | public static void EndGroup() 81 | { 82 | GUI.EndGroup(); 83 | clippingBounds = new Rect(0, 0, Screen.width, Screen.height); 84 | clippingEnabled = false; 85 | } 86 | 87 | public static void CreateMaterial() 88 | { 89 | if (lineMaterial != null) 90 | return; 91 | 92 | lineMaterial = new Material( "Shader \"Lines/Colored Blended\" {" + 93 | "SubShader { Pass { " + 94 | " Blend SrcAlpha OneMinusSrcAlpha " + 95 | " ZWrite Off Cull Off Fog { Mode Off } " + 96 | " BindChannels {" + 97 | " Bind \"vertex\", vertex Bind \"color\", color }" + 98 | "} } }"); 99 | lineMaterial.hideFlags = HideFlags.HideAndDontSave; 100 | lineMaterial.shader.hideFlags = HideFlags.HideAndDontSave; 101 | } 102 | 103 | public static void DrawLine(Vector2 start, Vector2 end, Color color, float width) 104 | { 105 | if (Event.current == null) 106 | return; 107 | if (Event.current.type != EventType.repaint) 108 | return; 109 | 110 | if (clippingEnabled) 111 | if (!segment_rect_intersection(clippingBounds, ref start, ref end)) 112 | return; 113 | 114 | CreateMaterial(); 115 | 116 | lineMaterial.SetPass(0); 117 | 118 | Vector3 startPt; 119 | Vector3 endPt; 120 | 121 | GL.Color(color); 122 | if (width == 1) { 123 | GL.Begin(GL.LINES); 124 | startPt = new Vector3(start.x, start.y, 0); 125 | endPt = new Vector3(end.x, end.y, 0); 126 | GL.Vertex(startPt); 127 | GL.Vertex(endPt); 128 | } 129 | else { 130 | GL.Begin(GL.QUADS); 131 | startPt = new Vector3(end.y, start.x, 0); 132 | endPt = new Vector3(start.y, end.x, 0); 133 | Vector3 perpendicular = (startPt - endPt).normalized * width; 134 | Vector3 v1 = new Vector3(start.x, start.y, 0); 135 | Vector3 v2 = new Vector3(end.x, end.y, 0); 136 | GL.Vertex(v1 - perpendicular); 137 | GL.Vertex(v1 + perpendicular); 138 | GL.Vertex(v2 + perpendicular); 139 | GL.Vertex(v2 - perpendicular); 140 | } 141 | GL.End(); 142 | } 143 | 144 | public static void DrawBox(Rect box, Color color, float width) 145 | { 146 | Vector2 p1 = new Vector2(box.xMin, box.yMin); 147 | Vector2 p2 = new Vector2(box.xMax, box.yMin); 148 | Vector2 p3 = new Vector2(box.xMax, box.yMax); 149 | Vector2 p4 = new Vector2(box.xMin, box.yMax); 150 | DrawLine(p1, p2, color, width); 151 | DrawLine(p2, p3, color, width); 152 | DrawLine(p3, p4, color, width); 153 | DrawLine(p4, p1, color, width); 154 | } 155 | 156 | public static void DrawBox(Vector2 topLeftCorner, Vector2 bottomRightCorner, Color color, float width) 157 | { 158 | Rect box = new Rect(topLeftCorner.x, topLeftCorner.y, bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - topLeftCorner.y); 159 | DrawBox(box, color, width); 160 | } 161 | 162 | public static void DrawRoundedBox(Rect box, float radius, Color color, float width) 163 | { 164 | Vector2 p1, p2, p3, p4, p5, p6, p7, p8; 165 | p1 = new Vector2(box.xMin + radius, box.yMin); 166 | p2 = new Vector2(box.xMax - radius, box.yMin); 167 | p3 = new Vector2(box.xMax, box.yMin + radius); 168 | p4 = new Vector2(box.xMax, box.yMax - radius); 169 | p5 = new Vector2(box.xMax - radius, box.yMax); 170 | p6 = new Vector2(box.xMin + radius, box.yMax); 171 | p7 = new Vector2(box.xMin, box.yMax - radius); 172 | p8 = new Vector2(box.xMin, box.yMin + radius); 173 | 174 | DrawLine(p1, p2, color, width); 175 | DrawLine(p3, p4, color, width); 176 | DrawLine(p5, p6, color, width); 177 | DrawLine(p7, p8, color, width); 178 | 179 | Vector2 t1, t2; 180 | float halfRadius = radius / 2; 181 | 182 | t1 = new Vector2(p8.x, p8.y + halfRadius); 183 | t2 = new Vector2(p1.x - halfRadius, p1.y); 184 | DrawBezier(p8, t1, p1, t2, color, width); 185 | 186 | t1 = new Vector2(p2.x + halfRadius, p2.y); 187 | t2 = new Vector2(p3.x, p3.y - halfRadius); 188 | DrawBezier(p2, t1, p3, t2, color, width); 189 | 190 | t1 = new Vector2(p4.x, p4.y + halfRadius); 191 | t2 = new Vector2(p5.x + halfRadius, p5.y); 192 | DrawBezier(p4, t1, p5, t2, color, width); 193 | 194 | t1 = new Vector2(p6.x - halfRadius, p6.y); 195 | t2 = new Vector2(p7.x, p7.y + halfRadius); 196 | DrawBezier(p6, t1, p7, t2, color, width); 197 | } 198 | 199 | 200 | 201 | public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width) 202 | { 203 | int segments = Mathf.FloorToInt((start - end).magnitude / 20) * 3; // Three segments per distance of 20 204 | DrawBezier(start, startTangent, end, endTangent, color, width, segments); 205 | } 206 | 207 | public static void DrawBezier(Vector2 start, Vector2 startTangent, Vector2 end, Vector2 endTangent, Color color, float width, int segments) 208 | { 209 | Vector2 startVector = CubeBezier(start, startTangent, end, endTangent, 0); 210 | for (int i = 1; i < segments; i++) 211 | { 212 | Vector2 endVector = CubeBezier(start, startTangent, end, endTangent, i/(float)segments); 213 | DrawLine(startVector, endVector, color, width); 214 | startVector = endVector; 215 | } 216 | } 217 | 218 | private static Vector2 CubeBezier(Vector2 s, Vector2 st, Vector2 e, Vector2 et, float t) 219 | { 220 | float rt = 1-t; 221 | float rtt = rt * t; 222 | return rt*rt*rt * s + 3 * rt * rtt * st + 3 * rtt * t * et + t*t*t* e; 223 | } 224 | } 225 | -------------------------------------------------------------------------------- /Assets/Scripts/Octree/IOctree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using UnityEngine; 3 | 4 | public interface IOctree 5 | { 6 | bool AddNode(float x, float y, float z, object obj); 7 | bool AddNode(Vector3 vector, object obj); 8 | 9 | object RemoveNode(float x, float y, float z, object obj); 10 | object RemoveNode(Vector3 vector, object obj); 11 | 12 | void Clear(); 13 | 14 | object GetNode(float x, float y, float z); 15 | object GetNode(Vector3 vector); 16 | object GetNode(float x, float y, float z, double shortestDistance); 17 | object GetNode(Vector3 vector, double shortestDistance); 18 | 19 | ArrayList GetNodes(float x, float y, float z, double radius); 20 | ArrayList GetNodes(Vector3 vector, double radius); 21 | ArrayList GetNodes(float x, float y, float z, double minRadius, double maxRadius); 22 | ArrayList GetNodes(Vector3 vector, double minRadius, double maxRadius); 23 | ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin); 24 | } 25 | -------------------------------------------------------------------------------- /Assets/Scripts/Octree/Octree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using UnityEngine; 4 | 5 | [Serializable] 6 | public class Octree : IOctree 7 | { 8 | protected internal OctreeNode Top; 9 | 10 | public Octree() : this(1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 20, OctreeNode.NoMinSize) { } 11 | 12 | public Octree(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maxItems) 13 | : this(xMax, xMin, yMax, yMin, zMax, zMin, maxItems, OctreeNode.NoMinSize) 14 | {} 15 | 16 | public Octree(int up, int left, int down, int right, int front, int back, int maxItems) 17 | : this( up, left, down, right, front, back, maxItems, OctreeNode.DefaultMinSize) 18 | {} 19 | 20 | public Octree(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maxItems, float minSize) 21 | { 22 | Top = new OctreeNode(xMax, xMin, yMax, yMin, zMax, zMin, maxItems, minSize); 23 | } 24 | 25 | public bool AddNode(float x, float y, float z, object obj) 26 | { 27 | return Top.AddNode(x, y, z, obj); 28 | } 29 | public bool AddNode(Vector3 vector, object obj) 30 | { 31 | return Top.AddNode(vector.x, vector.y, vector.z, obj); 32 | } 33 | 34 | public object RemoveNode(float x, float y, float z, object obj) 35 | { 36 | return Top.RemoveNode(x, y, z, obj); 37 | } 38 | public object RemoveNode(Vector3 vector, object obj) 39 | { 40 | return Top.RemoveNode(vector.x, vector.y, vector.z, obj); 41 | } 42 | 43 | public object GetNode(float x, float y, float z) 44 | { 45 | return Top.GetNode(x, y, z); 46 | } 47 | public object GetNode(Vector3 vector) 48 | { 49 | return Top.GetNode(vector.x, vector.y, vector.z); 50 | } 51 | public object GetNode(float x, float y, float z, double shortestDistance) 52 | { 53 | return Top.GetNode(x, y, z, shortestDistance); 54 | } 55 | public object GetNode(Vector3 vector, double shortestDistance) 56 | { 57 | return Top.GetNode(vector.x, vector.y, vector.z, shortestDistance); 58 | } 59 | public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) 60 | { 61 | return GetNode(xMax, xMin, yMax, yMin, zMax, zMin, ArrayList.Synchronized(new ArrayList(100))); 62 | } 63 | public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, ArrayList nodes) 64 | { 65 | if (nodes == null) 66 | nodes = ArrayList.Synchronized(new ArrayList(10)); 67 | 68 | if (xMin > xMax || (Math.Abs(xMin - xMax) < 1e-6)) 69 | return Top.GetNode(xMax, xMin, yMax, yMin, zMax, zMin, Top.GetNode(xMax, 0, yMax, yMin, zMax, zMin, nodes)); 70 | 71 | return Top.GetNode(xMax, xMin, yMax, yMin, zMax, zMin, nodes); 72 | } 73 | 74 | public ArrayList GetNodes(float x, float y, float z, double radius) 75 | { 76 | return Top.GetNodes(x, y, z, radius); 77 | } 78 | public ArrayList GetNodes(Vector3 vector, double radius) 79 | { 80 | return Top.GetNodes(vector.x, vector.y, vector.z, radius); 81 | } 82 | public ArrayList GetNodes(float x, float y, float z, double minRadius, double maxRadius) 83 | { 84 | return Top.GetNodes(x, y, z, minRadius, maxRadius); 85 | } 86 | public ArrayList GetNodes(Vector3 vector, double minRadius, double maxRadius) 87 | { 88 | return Top.GetNodes(vector.x, vector.y, vector.z, minRadius, maxRadius); 89 | } 90 | 91 | public void Clear() 92 | { 93 | Top.Clear(); 94 | } 95 | 96 | } -------------------------------------------------------------------------------- /Assets/Scripts/Octree/OctreeBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | [Serializable] 4 | public class OctreeBox 5 | { 6 | private float top; 7 | private float bottom; 8 | private float left; 9 | private float right; 10 | private float front; 11 | private float back; 12 | 13 | public OctreeBox(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) 14 | { 15 | right = xMax; 16 | left = xMin; 17 | front = yMax; 18 | back = yMin; 19 | top = zMax; 20 | bottom = zMin; 21 | } 22 | 23 | public bool Within(OctreeBox box) 24 | { 25 | return Within(box.Top, box.Left, box.Bottom, box.Right, box.Front, box.Back); 26 | } 27 | 28 | public bool Within(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) 29 | { 30 | if (xMin >= Right || 31 | xMax < Left || 32 | yMin >= Front || 33 | yMax < Back || 34 | zMin >= Top || 35 | zMax < Bottom) 36 | return false; 37 | 38 | return true; 39 | } 40 | 41 | public bool PointWithinBounds(float x, float y, float z) 42 | { 43 | return x <= Right && 44 | x > Left && 45 | y <= Front && 46 | y > Back && 47 | z <= Top && 48 | z > Bottom; 49 | } 50 | 51 | public double BorderDistance(float x, float y, float z) 52 | { 53 | double nsdistance; 54 | double ewdistance; 55 | double fbdistance; 56 | 57 | if (Left <= x && x <= Right) 58 | ewdistance = 0; 59 | else 60 | ewdistance = Math.Min((Math.Abs(x - Right)), (Math.Abs(x - Left))); 61 | 62 | if (Front <= y && y <= Back) 63 | fbdistance = 0; 64 | else 65 | fbdistance = Math.Min(Math.Abs(y - Back), Math.Abs(y - Front)); 66 | 67 | if (Bottom <= z && z <= Top) 68 | nsdistance = 0; 69 | else 70 | nsdistance = Math.Min(Math.Abs(z - Top), Math.Abs(z - Bottom)); 71 | 72 | return Math.Sqrt(nsdistance*nsdistance + 73 | ewdistance*ewdistance + 74 | fbdistance*fbdistance); 75 | } 76 | 77 | public float Right 78 | { 79 | get { return right; } 80 | set { right = value; } 81 | } 82 | 83 | public float Left 84 | { 85 | get { return left; } 86 | set { left = value; } 87 | } 88 | 89 | public float Front 90 | { 91 | get { return front; } 92 | set { front = value; } 93 | } 94 | 95 | public float Back 96 | { 97 | get { return back; } 98 | set { back = value; } 99 | } 100 | 101 | public float Top 102 | { 103 | get { return top; } 104 | set { top = value; } 105 | } 106 | 107 | public float Bottom 108 | { 109 | get { return bottom; } 110 | set { bottom = value; } 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /Assets/Scripts/Octree/OctreeLeaf.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | [Serializable] 4 | public class OctreeLeaf 5 | { 6 | 7 | private float fx, fy, fz; 8 | private object objectValue; 9 | 10 | public OctreeLeaf(float x, float y, float z, object obj) 11 | { 12 | fx = x; 13 | fy = y; 14 | fz = z; 15 | objectValue = obj; 16 | } 17 | 18 | 19 | public OctreeLeaf(double x, double y, double z, object obj) 20 | : this((float)x, (float)y, (float)z, (object)obj) 21 | { 22 | } 23 | 24 | public object LeafObject 25 | { 26 | get 27 | { 28 | return objectValue; 29 | } 30 | } 31 | 32 | public float X 33 | { 34 | get 35 | { 36 | return fx; 37 | } 38 | set 39 | { 40 | fx = value; ; 41 | } 42 | } 43 | public float Y 44 | { 45 | get 46 | { 47 | return fy; 48 | } 49 | set 50 | { 51 | fy = value; ; 52 | } 53 | } 54 | public float Z 55 | { 56 | get 57 | { 58 | return fz; 59 | } 60 | set 61 | { 62 | fz = value; ; 63 | } 64 | } 65 | 66 | } -------------------------------------------------------------------------------- /Assets/Scripts/Octree/OctreeNode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Linq; 4 | using UnityEngine; 5 | 6 | [Serializable] 7 | public class OctreeNode : IOctree 8 | { 9 | 10 | public const float NoMinSize = -1; 11 | public const float DefaultMinSize = 5; 12 | 13 | protected internal ArrayList Items; 14 | protected internal OctreeNode[] Branch; 15 | protected internal int MaxItems; 16 | protected internal float MinSize; 17 | public OctreeBox Bounds; 18 | 19 | protected internal bool AllTheSamePoint; 20 | protected internal float FirstX; 21 | protected internal float FirstY; 22 | protected internal float FirstZ; 23 | 24 | public OctreeNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maximumItems) 25 | : this(xMax, xMin, yMax, yMin, zMax, zMin, maximumItems, NoMinSize) 26 | { 27 | } 28 | 29 | public OctreeNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, int maximumItems, float minimumSize) 30 | { 31 | Bounds = new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin); 32 | MaxItems = maximumItems; 33 | MinSize = minimumSize; 34 | Items = ArrayList.Synchronized(new ArrayList(10)); 35 | } 36 | 37 | public bool HasChildren() 38 | { 39 | return Branch != null; 40 | } 41 | 42 | protected internal void Split() 43 | { 44 | // Make sure we're bigger than the minimum, if we care, 45 | if (MinSize != NoMinSize) 46 | if (Math.Abs(Bounds.Top - Bounds.Bottom) < MinSize && 47 | Math.Abs(Bounds.Right - Bounds.Left) < MinSize && 48 | Math.Abs(Bounds.Front - Bounds.Back) < MinSize) 49 | return; 50 | 51 | var nsHalf = (float)(Bounds.Top - (Bounds.Top - Bounds.Bottom) * 0.5); 52 | var ewHalf = (float)(Bounds.Right - (Bounds.Right - Bounds.Left) * 0.5); 53 | var fbHalf = (float)(Bounds.Front - (Bounds.Front - Bounds.Back) * 0.5); 54 | 55 | Branch = new OctreeNode[8]; 56 | 57 | Branch[0] = new OctreeNode(ewHalf, Bounds.Left, Bounds.Front, fbHalf, Bounds.Top, nsHalf, MaxItems); //left-front-top 58 | Branch[1] = new OctreeNode(Bounds.Right, ewHalf, Bounds.Front, fbHalf, Bounds.Top, nsHalf, MaxItems); 59 | Branch[2] = new OctreeNode(ewHalf, Bounds.Left, Bounds.Front, fbHalf, nsHalf, Bounds.Bottom, MaxItems); 60 | Branch[3] = new OctreeNode(Bounds.Right, ewHalf, Bounds.Front, fbHalf, nsHalf, Bounds.Bottom, MaxItems); 61 | 62 | Branch[4] = new OctreeNode(ewHalf, Bounds.Left, fbHalf, Bounds.Back, Bounds.Top, nsHalf, MaxItems); //left-back-top 63 | Branch[5] = new OctreeNode(Bounds.Right, ewHalf, fbHalf, Bounds.Back, Bounds.Top, nsHalf, MaxItems); 64 | Branch[6] = new OctreeNode(ewHalf, Bounds.Left, fbHalf, Bounds.Back, nsHalf, Bounds.Bottom, MaxItems); 65 | Branch[7] = new OctreeNode(Bounds.Right, ewHalf, fbHalf, Bounds.Back, nsHalf, Bounds.Bottom, MaxItems); 66 | 67 | var temp = (ArrayList)Items.Clone(); 68 | Items.Clear(); 69 | var things = temp.GetEnumerator(); 70 | while (things.MoveNext()) 71 | { 72 | AddNode((OctreeLeaf)things.Current); 73 | } 74 | } 75 | 76 | protected internal OctreeNode GetChild(float x, float y, float z) 77 | { 78 | return Bounds.PointWithinBounds(x, y, z) 79 | ? (Branch != null 80 | ? (from t in Branch where t.Bounds.PointWithinBounds(x, y, z) select t.GetChild(x, y, z)). 81 | FirstOrDefault() 82 | : this) 83 | : null; 84 | } 85 | 86 | #region Add Node 87 | 88 | public bool AddNode(float x, float y, float z, object obj) 89 | { 90 | return AddNode(new OctreeLeaf(x, y, z, obj)); 91 | } 92 | 93 | public bool AddNode(Vector3 vector, object obj) 94 | { 95 | return AddNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); 96 | } 97 | 98 | public bool AddNode(double x, double y, double z, object obj) 99 | { 100 | return AddNode(new OctreeLeaf(x, y, z, obj)); 101 | } 102 | 103 | public bool AddNode(OctreeLeaf leaf) 104 | { 105 | if (Branch == null) 106 | { 107 | Items.Add(leaf); 108 | if (Items.Count == 1) 109 | { 110 | AllTheSamePoint = true; 111 | FirstX = leaf.X; 112 | FirstY = leaf.Y; 113 | FirstZ = leaf.Z; 114 | } 115 | else 116 | { 117 | if (FirstX != leaf.X || FirstY != leaf.Y || FirstZ != leaf.Z) 118 | { 119 | AllTheSamePoint = false; 120 | } 121 | } 122 | 123 | if (Items.Count > MaxItems && !AllTheSamePoint) 124 | Split(); 125 | return true; 126 | } 127 | 128 | OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); 129 | return node != null && node.AddNode(leaf); 130 | } 131 | 132 | #endregion 133 | 134 | #region Remove Node 135 | 136 | public object RemoveNode(float x, float y, float z, object obj) 137 | { 138 | return RemoveNode(new OctreeLeaf(x, y, z, obj)); 139 | } 140 | 141 | public object RemoveNode(Vector3 vector, object obj) 142 | { 143 | return RemoveNode(new OctreeLeaf(vector.x, vector.y, vector.z, obj)); 144 | } 145 | 146 | public object RemoveNode(double x, double y, double z, object obj) 147 | { 148 | return RemoveNode(new OctreeLeaf(x, y, z, obj)); 149 | } 150 | 151 | public object RemoveNode(OctreeLeaf leaf) 152 | { 153 | if (Branch == null) 154 | { 155 | // This must be the node that has it... 156 | for (int i = 0; i < Items.Count; i++) 157 | { 158 | var qtl = (OctreeLeaf)Items[i]; 159 | if (leaf.LeafObject != qtl.LeafObject) continue; 160 | Items.RemoveAt(i); 161 | return qtl.LeafObject; 162 | } 163 | } 164 | else 165 | { 166 | OctreeNode node = GetChild(leaf.X, leaf.Y, leaf.Z); 167 | if (node != null) 168 | { 169 | return node.RemoveNode(leaf); 170 | } 171 | } 172 | return null; 173 | } 174 | 175 | #endregion 176 | 177 | #region Get Node 178 | 179 | public object GetNode(float x, float y, float z) 180 | { 181 | return GetNode(x, y, z, Double.PositiveInfinity); 182 | } 183 | 184 | public object GetNode(Vector3 vector) 185 | { 186 | return GetNode(vector.x, vector.y, vector.z, Double.PositiveInfinity); 187 | } 188 | 189 | public object GetNode(float x, float y, float z, double shortestDistance) 190 | { 191 | object closest = null; 192 | if (Branch == null) 193 | { 194 | // var childDistance = this.Bounds.BorderDistance(x, y, z); 195 | //if (childDistance > shortestDistance) 196 | // return null; 197 | foreach (OctreeLeaf leaf in Items) 198 | { 199 | var distance = Math.Sqrt( 200 | Math.Pow(x - leaf.X, 2.0) + 201 | Math.Pow(y - leaf.Y, 2.0) + 202 | Math.Pow(z - leaf.Z, 2.0)); 203 | 204 | if (!(distance < shortestDistance)) continue; 205 | shortestDistance = distance; 206 | closest = leaf.LeafObject; 207 | } 208 | return closest; 209 | } 210 | // Check the distance of the bounds of the branch, 211 | // versus the bestDistance. If there is a boundary that 212 | // is closer, then it is possible that another node has an 213 | // object that is closer. 214 | foreach (OctreeNode t in Branch) 215 | { 216 | var childDistance = t.Bounds.BorderDistance(x, y, z); 217 | if (!(childDistance < shortestDistance)) continue; 218 | object test = t.GetNode(x, y, z, shortestDistance); 219 | if (test != null) 220 | closest = test; 221 | } 222 | return closest; 223 | } 224 | 225 | public object GetNode(Vector3 vector, double shortestDistance) 226 | { 227 | return GetNode(vector.x, vector.y, vector.z, shortestDistance); 228 | } 229 | 230 | public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin) 231 | { 232 | return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), ArrayList.Synchronized(new ArrayList(10))); 233 | } 234 | 235 | public ArrayList GetNode(float xMax, float xMin, float yMax, float yMin, float zMax, float zMin, ArrayList nodes) 236 | { 237 | return GetNode(new OctreeBox(xMax, xMin, yMax, yMin, zMax, zMin), nodes); 238 | } 239 | 240 | public ArrayList GetNode(OctreeBox rect, ArrayList nodes) 241 | { 242 | if (Branch == null) 243 | { 244 | var things = Items.GetEnumerator(); 245 | while (things.MoveNext()) 246 | { 247 | var qtl = (OctreeLeaf)things.Current; 248 | if (qtl != null && rect.PointWithinBounds(qtl.X, qtl.Y, qtl.Z)) 249 | nodes.Add(qtl.LeafObject); 250 | } 251 | } 252 | else 253 | { 254 | foreach (var t in Branch.Where(t => t.Bounds.Within(rect))) 255 | { 256 | t.GetNode(rect, nodes); 257 | } 258 | } 259 | return nodes; 260 | } 261 | 262 | #endregion 263 | 264 | #region Get Nodes 265 | 266 | public ArrayList GetNodes(float x, float y, float z, double radius) 267 | { 268 | var nodes = new ArrayList(); 269 | if (Branch == null) 270 | { 271 | foreach (OctreeLeaf leaf in Items) 272 | { 273 | double distance = Math.Sqrt( 274 | Math.Pow(x - leaf.X, 2.0) + 275 | Math.Pow(y - leaf.Y, 2.0) + 276 | Math.Pow(z - leaf.Z, 2.0)); 277 | 278 | if (distance < radius) 279 | nodes.Add(leaf.LeafObject); 280 | } 281 | return nodes; 282 | } 283 | 284 | foreach (object test in from t in Branch let childDistance = t.Bounds.BorderDistance(x, y, z) where childDistance < radius select t.GetNode(x, y, z, radius) into test where test != null select test) 285 | { 286 | nodes.Add(test); 287 | } 288 | return nodes; 289 | } 290 | 291 | public ArrayList GetNodes(Vector3 vector, double radius) 292 | { 293 | return GetNodes(vector.x, vector.y, vector.z, radius); 294 | } 295 | 296 | public ArrayList GetNodes(float x, float y, float z, double minRadius, double maxRadius) 297 | { 298 | var nodes = new ArrayList(); 299 | if (Branch == null) 300 | { 301 | foreach (var leaf in from OctreeLeaf leaf in Items let distance = Math.Sqrt( 302 | Math.Pow(x - leaf.X, 2.0) + 303 | Math.Pow(y - leaf.Y, 2.0) + 304 | Math.Pow(z - leaf.Z, 2.0)) where distance >= minRadius && distance < maxRadius select leaf) 305 | { 306 | nodes.Add(leaf.LeafObject); 307 | } 308 | return nodes; 309 | } 310 | // Check the distance of the bounds of the branch, 311 | // versus the bestDistance. If there is a boundary that 312 | // is closer, then it is possible that another node has an 313 | // object that is closer. 314 | foreach (object test in from t in Branch let childDistance = t.Bounds.BorderDistance(x, y, z) where childDistance > minRadius && childDistance <= maxRadius select t.GetNode(x, y, z, minRadius) into test where test != null select test) 315 | { 316 | nodes.Add(test); 317 | } 318 | return nodes; 319 | } 320 | 321 | public ArrayList GetNodes(Vector3 vector, double minRadius, double maxRadius) 322 | { 323 | return GetNodes(vector.x, vector.y, vector.z, minRadius, maxRadius); 324 | } 325 | 326 | #endregion 327 | 328 | public void Clear() 329 | { 330 | Items.Clear(); 331 | if (Branch == null) return; 332 | foreach (var t in Branch) 333 | { 334 | t.Clear(); 335 | } 336 | Branch = null; 337 | } 338 | 339 | } -------------------------------------------------------------------------------- /Assets/Scripts/OctreeTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Linq; 3 | using UnityEditor; 4 | using UnityEngine; 5 | using System; 6 | 7 | public class OctreeTest:MonoBehaviour 8 | { 9 | public GameObject TestObject; 10 | private Octree ocTree; 11 | private Vector3 oldPos; 12 | private ArrayList result; 13 | 14 | private void Start () 15 | { 16 | var size = 1; 17 | ocTree = new Octree( size,-size,-size, 18 | size,size,-size,1); 19 | } 20 | 21 | void OnDrawGizmos() 22 | { 23 | if (result != null) 24 | foreach (var i in result.Cast()) 25 | Gizmos.DrawWireCube(i.Position, Vector3.one); 26 | 27 | if (ocTree == null) return; 28 | if (oldPos == TestObject.transform.position) return; 29 | 30 | result = ocTree.Top.GetNodes(TestObject.transform.position, TestObject.renderer.bounds.size.x/2); 31 | if (result.Count == 0) 32 | ocTree.AddNode(TestObject.transform.position, new OcTreeNodeObject(11, TestObject.transform.position)); 33 | 34 | Handles.Label(new Vector3(0, 0, 0), "result.Count :" + result.Count); 35 | oldPos = TestObject.transform.position; 36 | } 37 | } 38 | 39 | 40 | class OcTreeNodeObject 41 | { 42 | public Vector3 Position; 43 | public int Id; 44 | public Color Color; 45 | 46 | public OcTreeNodeObject(int id, Vector3 pos) 47 | { 48 | Id = id; 49 | Position = pos; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Octree/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /Octree/.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Bb]in 101 | [Oo]bj 102 | sql 103 | TestResults 104 | *.Cache 105 | ClientBin 106 | stylecop.* 107 | ~$* 108 | *.dbmdl 109 | Generated_Code #added for RIA/Silverlight projects 110 | 111 | # Backup & report files from converting an old project file to a newer 112 | # Visual Studio version. Backup files are not needed, because we have git ;-) 113 | _UpgradeReport_Files/ 114 | Backup*/ 115 | UpgradeLog*.XML 116 | 117 | 118 | 119 | ############ 120 | ## Windows 121 | ############ 122 | 123 | # Windows image file caches 124 | Thumbs.db 125 | 126 | # Folder config file 127 | Desktop.ini 128 | 129 | 130 | ############# 131 | ## Python 132 | ############# 133 | 134 | *.py[co] 135 | 136 | # Packages 137 | *.egg 138 | *.egg-info 139 | dist 140 | build 141 | eggs 142 | parts 143 | bin 144 | var 145 | sdist 146 | develop-eggs 147 | .installed.cfg 148 | 149 | # Installer logs 150 | pip-log.txt 151 | 152 | # Unit test / coverage reports 153 | .coverage 154 | .tox 155 | 156 | #Translations 157 | *.mo 158 | 159 | #Mr Developer 160 | .mr.developer.cfg 161 | 162 | # Mac crap 163 | .DS_Store 164 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshLayers.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/NavMeshLayers.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pixelstudio/Octree/78f3e6e8597fcf8b6396887eff9d9882e7655412/ProjectSettings/TimeManager.asset --------------------------------------------------------------------------------