/// <summary> /// Utility method to build KDTreeNode variables, as long as min and max /// </summary> public void Build() { Leaf = new VertexKDTree(new Vector3(maxV + minV) / 2.0f, -1); rangeV = maxV - minV; SplitAxis = rangeV.LargestAxis(); BoundingBox = new BoundingBoxAxisAligned(minV, maxV); IsBuilt = true; }
/// <summary> /// BoundingBox intersects another BoundingBox /// </summary> /// <param name="aabb"></param> /// <returns></returns> public bool Intersects(BoundingBoxAxisAligned aabb) { Vector3 v1 = aabb.MinCorner; Vector3 v2 = aabb.MaxCorner; Vector3 v3 = MinCorner; Vector3 v4 = MaxCorner; return((v4.X >= v1.X) && (v3.X <= v2.X) && //x-axis overlap (v4.Y >= v1.Y) && (v3.Y <= v2.Y) && //y-axis overlap (v4.Y >= v1.Y) && (v3.Y <= v2.Y)); //z-axis overlap }
/// <summary> /// Find the closest matching vertex /// </summary> /// <param name="vertex">Vertex to find closest match.</param> /// <param name="distance">Search distance.</param> /// <param name="nearest_index">Index of matching vertex in the KDTree vertex array</param> /// <returns>Nearest matching vertex</returns> public VertexKDTree FindClosestPoint(VertexKDTree vertex, ref float distance, ref int nearest_index) { if (root == null) { Console.WriteLine("Null root, Build() must be called before using the KDTree."); return(new VertexKDTree(new Vector3(0, 0, 0), -1)); } BoundingBoxAxisAligned search_bounds = null; if (distance != 0) { Vector3 distance_vector = new Vector3(distance, distance, distance); search_bounds = new BoundingBoxAxisAligned(vertex.Vector - distance_vector, vertex.Vector + distance_vector); } return(FindClosestPoint_Recursive(Root, vertex, search_bounds, ref nearest_index)); }
/// <summary> /// Does BoundingSphere intersect BoundingBoxAxisAligned /// </summary> /// <notes> /// Code modified from: http://tog.acm.org/resources/GraphicsGems/gems/BoxSphere.c /// Support for mixed hollow/solid intersections was dropped. Only hollow-hollow and solid-solid /// are supported /// </notes> /// <param name="intersection_type">Defines intersection method</param> /// <returns>True if sphere intersects bounding box, else FALSE</returns> public bool Intersects(BoundingBoxAxisAligned aabb, IntersectionTypes intersection_type) { float a, b; float r2 = Radius2; bool face; switch (intersection_type) { case IntersectionTypes.HOLLOW: // Hollow Box - Hollow Sphere { float dmin = 0; float dmax = 0; face = false; for (int i = 0; i < 3; i++) { a = (float)Math.Pow(Center[i] - aabb.MinCorner[i], 2.0); b = (float)Math.Pow(Center[i] - aabb.MaxCorner[i], 2.0); dmax += Math.Max(a, b); if (Center[i] < aabb.MinCorner[i]) { face = true; dmin += a; } else if (Center[i] > aabb.MaxCorner[i]) { face = true; dmin += b; } else if (Math.Min(a, b) <= r2) { face = true; } } if (face && (dmin <= r2) && (r2 <= dmax)) { return(true); } break; } case IntersectionTypes.SOLID: // Solid Box - Solid Sphere { float dmin = 0; for (int i = 0; i < 3; i++) { if (Center[i] < aabb.MinCorner[i]) { dmin += (float)Math.Pow(Center[i] - aabb.MinCorner[i], 2.0); } else if (Center[i] > aabb.MaxCorner[i]) { dmin += (float)Math.Pow(Center[i] - aabb.MaxCorner[i], 2.0); } } if (dmin <= r2) { return(true); } break; } } return(false); }
public bool Intersects(BoundingBoxAxisAligned aabb, IntersectionTypes type) { return(Intersects(aabb)); }
public BoundingBoxAxisAligned(BoundingBoxAxisAligned aabb) { MinCorner = aabb.MinCorner; MaxCorner = aabb.MaxCorner; }
/// <summary> /// Find closest point using an axis aligned search boundary /// </summary> /// <param name="node"></param> /// <param name="point"></param> /// <returns></returns> VertexKDTree FindClosestPoint_Recursive(KDNodeJeremyC node, VertexKDTree vertex, BoundingBoxAxisAligned search_bounds, ref int nearest_index) { int tmp_index = -1; if (node.IsLeaf) { tmp_index = -1; VertexKDTree result = GetClosestVertexFromIndices(node.Indices, vertex, ref tmp_index); if (result != null) { nearest_index = tmp_index; return(result); } else { return(null); } } tmp_index = -1; KDNodeJeremyC near_child = node.GetSplitNode(vertex); VertexKDTree retV = FindClosestPoint_Recursive(near_child, vertex, search_bounds, ref tmp_index); //Edgar - TakenVector implementation - have to go one level up if vector is taken float near_distance = float.MaxValue; if (retV != null) { //near_distance = retV.Vector.Distance(vertex.Vector); near_distance = retV.Vector.DistanceSquared(vertex.Vector); nearest_index = tmp_index; } KDNodeJeremyC far_child = near_child.Sibling; if (search_bounds != null && far_child.BoundingBox.Intersects(search_bounds)) { VertexKDTree far_result = FindClosestPoint_Recursive(far_child, vertex, search_bounds, ref tmp_index); //Edgar - TakenVector implementation - have to go one level up if vector is taken if (far_result != null) { //float far_distance = far_result.Vector.Distance(vertex.Vector); float far_distance = far_result.Vector.DistanceSquared(vertex.Vector); if (far_distance < near_distance) { nearest_index = tmp_index; retV = far_result; } } } if (retV == null) { } return(retV); }