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));
 }