TC_Octree.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace TerrainComposer2
  5. {
  6. public class Octree
  7. {
  8. public Cell cell;
  9. public class SpawnedObject
  10. {
  11. public int objectIndex;
  12. public int listIndex;
  13. public Vector3 position;
  14. public MaxCell cell;
  15. public SpawnedObject(int objectIndex, Vector3 position)
  16. {
  17. this.objectIndex = objectIndex;
  18. this.position = position;
  19. }
  20. public void Remove()
  21. {
  22. cell.objects[listIndex] = cell.objects[cell.objects.Count - 1];
  23. cell.objects.RemoveAt(cell.objects.Count - 1);
  24. if (cell.objects.Count == 0)
  25. {
  26. cell.parent.RemoveCell(cell.cellIndex);
  27. }
  28. }
  29. }
  30. public class MaxCell : Cell
  31. {
  32. public List<SpawnedObject> objects = new List<SpawnedObject>();
  33. public MaxCell(Cell parent, int cellIndex, Bounds bounds): base(parent, cellIndex, bounds) { }
  34. ~MaxCell()
  35. {
  36. objects.Clear();
  37. objects = null;
  38. }
  39. }
  40. public class Cell
  41. {
  42. public Cell mainParent;
  43. public Cell parent;
  44. public Cell[] cells;
  45. public bool[] cellsUsed;
  46. public Bounds bounds;
  47. public int cellIndex;
  48. public int cellCount;
  49. public int level;
  50. public int maxLevels;
  51. public Cell(Cell parent, int cellIndex, Bounds bounds)
  52. {
  53. if (parent != null)
  54. {
  55. maxLevels = parent.maxLevels;
  56. mainParent = parent.mainParent;
  57. level = parent.level + 1;
  58. }
  59. this.parent = parent;
  60. this.cellIndex = cellIndex;
  61. this.bounds = bounds;
  62. }
  63. ~Cell()
  64. {
  65. mainParent = parent = null;
  66. cells = null;
  67. }
  68. int AddCell(Vector3 position)
  69. {
  70. Vector3 localPos = position - bounds.min;
  71. int x = (int)(localPos.x / bounds.extents.x);
  72. int y = (int)(localPos.y / bounds.extents.y);
  73. int z = (int)(localPos.z / bounds.extents.z);
  74. int index = x + (y * 4) + (z * 2);
  75. if (cells == null) { cells = new Cell[8]; cellsUsed = new bool[8]; }
  76. // Reporter.Log("index "+index+" position "+localPos+" x: "+x+" y: "+y+" z: "+z+" extents "+bounds.extents);
  77. if (!cellsUsed[index])
  78. {
  79. Bounds subBounds = new Bounds(new Vector3(bounds.min.x + (bounds.extents.x * (x + 0.5f)), bounds.min.y + (bounds.extents.y * (y + 0.5f)), bounds.min.z + (bounds.extents.z * (z + 0.5f))), bounds.extents);
  80. if (level == maxLevels - 1) cells[index] = new MaxCell(this, index, subBounds); else cells[index] = new Cell(this, index, subBounds);
  81. cellsUsed[index] = true;
  82. ++cellCount;
  83. }
  84. return index;
  85. }
  86. public void RemoveCell(int index)
  87. {
  88. cells[index] = null;
  89. cellsUsed[index] = false;
  90. --cellCount;
  91. if (cellCount == 0)
  92. {
  93. if (parent != null) parent.RemoveCell(cellIndex);
  94. }
  95. }
  96. public bool InsideBounds(Vector3 position)
  97. {
  98. position -= bounds.min;
  99. if (position.x >= bounds.size.x || position.y >= bounds.size.y || position.z >= bounds.size.z || position.x < 0 || position.y < 0 || position.z < 0) { return false; }
  100. return true;
  101. } //===============================================================================================================================
  102. public void AddObject(SpawnedObject obj)
  103. {
  104. if (bounds.Contains(obj.position)) AddObjectInternal(obj);
  105. }
  106. void AddObjectInternal(SpawnedObject obj)
  107. {
  108. if (level == maxLevels)
  109. {
  110. obj.cell = (MaxCell)this;
  111. obj.cell.objects.Add(obj);
  112. obj.listIndex = obj.cell.objects.Count - 1;
  113. }
  114. else
  115. {
  116. int index = AddCell(obj.position);
  117. cells[index].AddObjectInternal(obj);
  118. }
  119. }
  120. public void Reset()
  121. {
  122. if (cells == null) return;
  123. for (int i = 0; i < 8; i++)
  124. {
  125. cells[i] = null;
  126. cellsUsed[i] = false;
  127. }
  128. }
  129. public void Draw(bool onlyMaxLevel)
  130. {
  131. if (!onlyMaxLevel || level == maxLevels)
  132. {
  133. Gizmos.DrawWireCube(bounds.center, bounds.size);
  134. if (level == maxLevels) return;
  135. }
  136. for (int i = 0; i < 8; i++)
  137. {
  138. if (cellsUsed[i]) cells[i].Draw(onlyMaxLevel);
  139. }
  140. }
  141. }
  142. }
  143. }