/// <summary> /// Returns the node that the point belongs to /// </summary> /// <param name="rPoint"></param> /// <returns></returns> public MeshOctreeNode ClosestNode(Vector3 rPoint) { MeshOctreeNode lClosestNode = null; if (rPoint.x + EPSILON < Min.x) { return(lClosestNode); } if (rPoint.x - EPSILON > Max.x) { return(lClosestNode); } if (rPoint.y + EPSILON < Min.y) { return(lClosestNode); } if (rPoint.y - EPSILON > Max.y) { return(lClosestNode); } if (rPoint.z + EPSILON < Min.z) { return(lClosestNode); } if (rPoint.z - EPSILON > Max.z) { return(lClosestNode); } if (Children == null) { lClosestNode = this; } else { for (int i = 0; i < 8; i++) { MeshOctreeNode lTestClosestNode = Children[i].ClosestNode(rPoint); if (lTestClosestNode != null) { if (lClosestNode == null || lTestClosestNode.Size.sqrMagnitude < lClosestNode.Size.sqrMagnitude) { lClosestNode = lTestClosestNode; } } } } return(lClosestNode); }
/// <summary> /// Initializes the octree with the specific mesh /// </summary> /// <param name="rMesh"></param> public void Initialize(Mesh rMesh) { if (rMesh == null) { return; } Name = rMesh.name; float lSize = Mathf.Max(rMesh.bounds.size.x, Mathf.Max(rMesh.bounds.size.y, rMesh.bounds.size.z)); Root = new MeshOctreeNode(rMesh.bounds.center, new Vector3(lSize, lSize, lSize)); Root.MeshVertices = rMesh.vertices; Root.MeshTriangles = rMesh.triangles; // Build the octree with the triangles int lTriangleCount = Root.MeshTriangles.Length / 3; for (int i = 0; i < lTriangleCount; i++) { Root.Insert(i * 3); } }
/// <summary> /// Split the octree and distribute it's values /// </summary> public virtual void Split() { Vector3 lHalfSize = Size * 0.5f; Vector3 lQuarterSize = lHalfSize * 0.5f; // Split into eight children Children = new MeshOctreeNode[8]; Children[0] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y - lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom left back Children[1] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y - lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom right back Children[2] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y + lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top left back Children[3] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y + lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top right back Children[4] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y - lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom left forward Children[5] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y - lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom right forward Children[6] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y + lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top left forward Children[7] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y + lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top right forward // Distribute values to the children for (int lIndex = 0; lIndex < TriangleIndexes.Count; lIndex++) { //float lTriangleRadius; Vector3 lTriangleCenter; Vector3 lTriangleMin; Vector3 lTriangleMax; int lTriangleIndex = TriangleIndexes[lIndex]; //GetTriangleBounds(lTriangleIndex, out lTriangleCenter, out lTriangleRadius); GetTriangleBounds(lTriangleIndex, out lTriangleCenter, out lTriangleMin, out lTriangleMax); for (int i = 0; i < 8; i++) { //Children[i].Insert(lTriangleIndex, lTriangleCenter, lTriangleRadius); Children[i].Insert(lTriangleIndex, lTriangleCenter, lTriangleMin, lTriangleMax); } } // Since we have children, clear out values TriangleIndexes.Clear(); TriangleIndexes = null; }
/// <summary> /// Initializes the octree with the specific mesh /// </summary> /// <param name="rMesh"></param> public void Initialize(Mesh rMesh) { if (rMesh == null) { return; } Name = rMesh.name; float lSize = Mathf.Max(rMesh.bounds.size.x, Mathf.Max(rMesh.bounds.size.y, rMesh.bounds.size.z)); Root = new MeshOctreeNode(rMesh.bounds.center, new Vector3(lSize, lSize, lSize)); Root.MeshVertices = rMesh.vertices; Root.MeshTriangles = rMesh.triangles; // Build the octree with the triangles int lTriangleCount = Root.MeshTriangles.Length / 3; for (int i = 0; i < lTriangleCount; i++) { Root.Insert(i * 3); } }
/// <summary> /// Split the octree and distribute it's values /// </summary> public virtual void Split() { Vector3 lHalfSize = Size * 0.5f; Vector3 lQuarterSize = lHalfSize * 0.5f; // Split into eight children Children = new MeshOctreeNode[8]; Children[0] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y - lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom left back Children[1] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y - lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom right back Children[2] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y + lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top left back Children[3] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y + lQuarterSize.y, Center.z - lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top right back Children[4] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y - lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom left forward Children[5] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y - lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // bottom right forward Children[6] = new MeshOctreeNode(Center.x - lQuarterSize.x, Center.y + lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top left forward Children[7] = new MeshOctreeNode(Center.x + lQuarterSize.x, Center.y + lQuarterSize.y, Center.z + lQuarterSize.z, lHalfSize, MeshVertices, MeshTriangles); // top right forward // Distribute values to the children for (int lIndex = 0; lIndex < TriangleIndexes.Count; lIndex++) { //float lTriangleRadius; Vector3 lTriangleCenter; Vector3 lTriangleMin; Vector3 lTriangleMax; int lTriangleIndex = TriangleIndexes[lIndex]; //GetTriangleBounds(lTriangleIndex, out lTriangleCenter, out lTriangleRadius); GetTriangleBounds(lTriangleIndex, out lTriangleCenter, out lTriangleMin, out lTriangleMax); for (int i = 0; i < 8; i++) { //Children[i].Insert(lTriangleIndex, lTriangleCenter, lTriangleRadius); Children[i].Insert(lTriangleIndex, lTriangleCenter, lTriangleMin, lTriangleMax); } } // Since we have children, clear out values TriangleIndexes.Clear(); TriangleIndexes = null; }
/// <summary> /// Renders the octree to the scene /// </summary> public void OnSceneGUI() { if (!RenderOctree && !RenderMesh && !RenderTestNode && !RenderTestTriangle) { return; } Color lHandlesColor = Handles.color; if (MeshOctree == null || MeshOctree.Root == null) { Stopwatch lTimer = new Stopwatch(); lTimer.Start(); Mesh lMesh = ExtractMesh(); if (lMesh != null) { MeshOctree = new MeshOctree(lMesh); } lTimer.Stop(); ParseTime = lTimer.ElapsedTicks / (float)TimeSpan.TicksPerSecond; } if (MeshOctree != null && MeshOctree.Root != null) { if (RenderOctree) { MeshOctree.OnSceneGUI(transform); } if (RenderMesh) { Handles.color = new Color(0f, 1f, 0f, 0.5f); int[] lTriangles = MeshOctree.Root.MeshTriangles; Vector3[] lVertices = MeshOctree.Root.MeshVertices; int lTriangleCount = lTriangles.Length / 3; for (int i = 0; i < lTriangleCount; i++) { int lIndex = i * 3; Vector3 lVertex1 = transform.TransformPoint(lVertices[lTriangles[lIndex]]); Vector3 lVertex2 = transform.TransformPoint(lVertices[lTriangles[lIndex + 1]]); Vector3 lVertex3 = transform.TransformPoint(lVertices[lTriangles[lIndex + 2]]); Handles.DrawLine(lVertex1, lVertex2); Handles.DrawLine(lVertex2, lVertex3); Handles.DrawLine(lVertex3, lVertex1); } } if (RenderTestTriangle) { Handles.color = Color.magenta; Vector3 lLocalPoint = transform.InverseTransformPoint(TestTransform != null ? TestTransform.position : TestPosition); // First, let's see if our point is inside the root node. If not, make it so. if (!MeshOctree.ContainsPoint(lLocalPoint)) { if (lLocalPoint.x < MeshOctree.Root.Min.x) { lLocalPoint.x = MeshOctree.Root.Min.x; } else if (lLocalPoint.x > MeshOctree.Root.Max.x) { lLocalPoint.x = MeshOctree.Root.Max.x; } if (lLocalPoint.y < MeshOctree.Root.Min.y) { lLocalPoint.y = MeshOctree.Root.Min.y; } else if (lLocalPoint.y > MeshOctree.Root.Max.y) { lLocalPoint.y = MeshOctree.Root.Max.y; } if (lLocalPoint.z < MeshOctree.Root.Min.z) { lLocalPoint.z = MeshOctree.Root.Min.z; } else if (lLocalPoint.z > MeshOctree.Root.Max.z) { lLocalPoint.z = MeshOctree.Root.Max.z; } } // Grab the closest triangle int lTriangleIndex = MeshOctree.Root.ClosestTriangle(lLocalPoint); if (lTriangleIndex >= 0) { Vector3 lVertex1 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex]]); Vector3 lVertex2 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex + 1]]); Vector3 lVertex3 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex + 2]]); Handles.DrawLine(lVertex1, lVertex2); Handles.DrawLine(lVertex2, lVertex3); Handles.DrawLine(lVertex3, lVertex1); #if UNITY_4 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2 || UNITY_5_3 || UNITY_5_4 || UNITY_5_5 Handles.SphereCap(0, transform.TransformPoint(lLocalPoint), Quaternion.identity, 0.05f); #else Handles.SphereHandleCap(0, transform.TransformPoint(lLocalPoint), Quaternion.identity, 0.05f, EventType.Layout | EventType.Repaint); #endif } } if (RenderTestNode) { Vector3 lLocalPoint = transform.InverseTransformPoint(TestTransform != null ? TestTransform.position : TestPosition); // Grab the closest node MeshOctreeNode lNode = MeshOctree.Root.ClosestNode(lLocalPoint); if (lNode != null) { Handles.color = Color.white; lNode.OnSceneGUI(transform); if (lNode.TriangleIndexes != null) { Handles.color = Color.magenta; for (int i = 0; i < lNode.TriangleIndexes.Count; i++) { int lTriangleIndex = lNode.TriangleIndexes[i]; Vector3 lVertex1 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex]]); Vector3 lVertex2 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex + 1]]); Vector3 lVertex3 = transform.TransformPoint(MeshOctree.Root.MeshVertices[MeshOctree.Root.MeshTriangles[lTriangleIndex + 2]]); Handles.DrawLine(lVertex1, lVertex2); Handles.DrawLine(lVertex2, lVertex3); Handles.DrawLine(lVertex3, lVertex1); } } } } } Handles.color = lHandlesColor; }