protected void CreateChildren(APAOctree parent, int generations) { m_children = new List <APAOctree>(); Vector3 c = parent.bounds.center; float u = parent.bounds.extents.x * 0.5f; float v = parent.bounds.extents.y * 0.5f; float w = parent.bounds.extents.z * 0.5f; Vector3 childrenSize = parent.bounds.extents; Vector3[] childrenCenters = { new Vector3(c.x + u, c.y + v, c.z + w), new Vector3(c.x + u, c.y + v, c.z - w), new Vector3(c.x + u, c.y - v, c.z + w), new Vector3(c.x + u, c.y - v, c.z - w), new Vector3(c.x - u, c.y + v, c.z + w), new Vector3(c.x - u, c.y + v, c.z - w), new Vector3(c.x - u, c.y - v, c.z + w), new Vector3(c.x - u, c.y - v, c.z - w) }; for (int i = 0; i < childrenCenters.Length; i++) { APAOctree o = new APAOctree(); o.parent = parent; o.bounds = new Bounds(childrenCenters[i], childrenSize); m_children.Add(o); if (generations > 0) { o.CreateChildren(o, generations - 1); } } }
public APAOctree IndexTriangle(APAOctree parentNode, Triangle triangle) { // Compute triangle bounds (not using the param version of Mathf.Min() to avoid array allocation) float minX = Mathf.Min(triangle.pt0.x, Mathf.Min(triangle.pt1.x, triangle.pt2.x)); float minY = Mathf.Min(triangle.pt0.y, Mathf.Min(triangle.pt1.y, triangle.pt2.y)); float minZ = Mathf.Min(triangle.pt0.z, Mathf.Min(triangle.pt1.z, triangle.pt2.z)); float maxX = Mathf.Max(triangle.pt0.x, Mathf.Max(triangle.pt1.x, triangle.pt2.x)); float maxY = Mathf.Max(triangle.pt0.y, Mathf.Max(triangle.pt1.y, triangle.pt2.y)); float maxZ = Mathf.Max(triangle.pt0.z, Mathf.Max(triangle.pt1.z, triangle.pt2.z)); APAOctree finalNode = null; APAOctree currentNode = parentNode; while (currentNode != null && finalNode == null) { float boundsCenterX = currentNode.bounds.center.x; float boundsCenterY = currentNode.bounds.center.y; float boundsCenterZ = currentNode.bounds.center.z; // Test if the triangle crosses any of the mid planes of the node if ((minX < boundsCenterX && maxX >= boundsCenterX) || (minY < boundsCenterY && maxY >= boundsCenterY) || (minZ < boundsCenterZ && maxZ >= boundsCenterZ)) { // The triangle must be in the current node finalNode = currentNode; } else { // The triangle can be inside one of our children, if we have any if (currentNode.m_children != null && currentNode.m_children.Count > 0) { // Figure out which child based on which side of each mid plane the triangle sits on int childIndex = 0; if (minX < boundsCenterX) { childIndex |= 4; } if (minY < boundsCenterY) { childIndex |= 2; } if (minZ < boundsCenterZ) { childIndex |= 1; } // Continue iteration with the child node that contains the triangle currentNode = currentNode.m_children[childIndex]; } else { // Since we don't have children, even though the triangle *would* fit in one of our potential child, // we're the node that has to own the triangle. // Arguably, if you hit this code a lot, you could benefit from using more depth in your octree... finalNode = currentNode; } } } return(finalNode); }
public APAOctree(Bounds parentBounds, int generations) { this.bounds = parentBounds; this.m_children = new List <APAOctree>(); this.triangles = new List <Triangle>(); this.parent = null; CreateChildren(this, generations); }
void OnDestroy() { Debug.Log("Mem Before Clear: " + System.GC.GetTotalMemory(true) / 1024f / 1024f); octree.Clear(); octree = null; Destroy(singleton); Debug.Log("Mem After Clear: " + System.GC.GetTotalMemory(true) / 1024f / 1024f); }
void DrawOctree(APAOctree oct) { Gizmos.DrawWireCube(oct.bounds.center, oct.bounds.size); // foreach(APAOctree o in oct.m_children){ // DrawOctree(o); // } }
void OnDestroy() { Debug.Log("Mem Before APAOctree Clear: " + System.GC.GetTotalMemory(true) / 1024f / 1024f); if (octree != null) { octree.Clear(); } octree = null; Debug.Log("Mem After APAOctree Clear: " + System.GC.GetTotalMemory(true) / 1024f / 1024f); }
int GetTriangleCount(APAOctree o) { int count = o.triangles.Count; foreach (APAOctree oct in o.m_children) { count += GetTriangleCount(oct); } return(count); }
protected int ClearOctree(APAOctree o) { int count = 0; for (int i = 0; i < o.m_children.Count; i++) { count += ClearOctree(o.m_children[i]); } o.triangles.Clear(); o.triangles.TrimExcess(); o.parent = null; o.m_children.Clear(); o.m_children.TrimExcess(); count++; return(count); }
static List <APARaycastHit> INTERNAL_RaycastAll(Ray ray) { stopWatch = new System.Diagnostics.Stopwatch(); stopWatch.Start(); List <APARaycastHit> hits = new List <APARaycastHit>(); APAOctree octree = APAObjectDictionary.GetOctree(); if (octree.bounds.IntersectRay(ray)) { hits = RecurseOctreeBounds(octree, ray); } hits = SortResults(hits); stopWatch.Stop(); Debug.Log("Search Time: " + stopWatch.ElapsedMilliseconds + " ms"); return(hits); }
static bool INTERNAL_Raycast(Ray ray, out APARaycastHit hit) { hit = new APARaycastHit(); List <APARaycastHit> hits = new List <APARaycastHit>(); APAOctree octree = APAObjectDictionary.GetOctree(); if (octree.bounds.IntersectRay(ray)) { hits = RecurseOctreeBounds(octree, ray); } hits = SortResults(hits); if (hits.Count > 0) { hit = hits[0]; } return(hits.Count > 0); }
static List <APARaycastHit> RecurseOctreeBounds(APAOctree octree, Ray ray) { List <APARaycastHit> hits = new List <APARaycastHit>(); float dist = 0f; Vector2 baryCoord = new Vector2(); if (octree.bounds.IntersectRay(ray)) { for (int i = 0; i < octree.triangles.Count; i++) { if (TestIntersection(octree.triangles[i], ray, out dist, out baryCoord)) { hits.Add(BuildRaycastHit(octree.triangles[i], dist, baryCoord)); } } } for (int i = 0; i < octree.m_children.Count; i++) { hits.AddRange(RecurseOctreeBounds(octree.m_children[i], ray)); } return(hits); }
public void Init(Bounds bounds, List <GameObject> gameObjects) { octree = new APAOctree(bounds, octreeDepth); PopulateOctree(gameObjects); }
// ~APAOctree(){ // m_children.Clear(); // m_children.TrimExcess(); // parent = null; // triangles.Clear(); // triangles.TrimExcess(); // } public APAOctree() { this.m_children = new List <APAOctree>(); this.triangles = new List <Triangle>(); this.parent = null; }
public void Init(CallbackMethod del, Bounds bounds) { octree = new APAOctree(bounds, octreeDepth); StartCoroutine(PopulateOctree(del)); }