/// <summary> /// Recursive splitting procedure /// </summary> /// <param name="parent">This is where root node goes</param> /// <param name="depth"></param> /// void SplitNode(KDNode parent) { // center of bounding box KDBounds parentBounds = parent.bounds; Vector3 parentBoundsSize = parentBounds.size; // Find axis where bounds are largest int splitAxis = 0; float axisSize = parentBoundsSize.x; if (axisSize < parentBoundsSize.y) { splitAxis = 1; axisSize = parentBoundsSize.y; } if (axisSize < parentBoundsSize.z) { splitAxis = 2; } // Our axis min-max bounds float boundsStart = parentBounds.min[splitAxis]; float boundsEnd = parentBounds.max[splitAxis]; // Calculate the spliting coords float splitPivot = CalculatePivot(parent.start, parent.end, boundsStart, boundsEnd, splitAxis); parent.partitionAxis = splitAxis; parent.partitionCoordinate = splitPivot; // 'Spliting' array to two subarrays int splittingIndex = Partition(parent.start, parent.end, splitPivot, splitAxis); // Negative / Left node Vector3 negMax = parentBounds.max; negMax[splitAxis] = splitPivot; KDNode negNode = GetKDNode(); negNode.bounds = parentBounds; negNode.bounds.max = negMax; negNode.start = parent.start; negNode.end = splittingIndex; parent.negativeChild = negNode; // Positive / Right node Vector3 posMin = parentBounds.min; posMin[splitAxis] = splitPivot; KDNode posNode = GetKDNode(); posNode.bounds = parentBounds; posNode.bounds.min = posMin; posNode.start = splittingIndex; posNode.end = parent.end; parent.positiveChild = posNode; // check if we are actually splitting it anything // this if check enables duplicate coordinates, but makes construction a bit slower #if KDTREE_DUPLICATES if (negNode.Count != 0 && posNode.Count != 0) { #endif // Constraint function deciding if split should be continued if (ContinueSplit(negNode)) { SplitNode(negNode); } if (ContinueSplit(posNode)) { SplitNode(posNode); } #if KDTREE_DUPLICATES } #endif }
/// <summary> /// For calculating root node bounds /// </summary> /// <returns>Boundary of all Vector3 points</returns> KDBounds MakeBounds() { Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue); Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); int even = Count & ~1; // calculate even Length // min, max calculations // 3n/2 calculations instead of 2n for (int i0 = 0; i0 < even; i0 += 2) { int i1 = i0 + 1; // X Coords if (points[i0].x > points[i1].x) { // i0 is bigger, i1 is smaller if (points[i1].x < min.x) { min.x = points[i1].x; } if (points[i0].x > max.x) { max.x = points[i0].x; } } else { // i1 is smaller, i0 is bigger if (points[i0].x < min.x) { min.x = points[i0].x; } if (points[i1].x > max.x) { max.x = points[i1].x; } } // Y Coords if (points[i0].y > points[i1].y) { // i0 is bigger, i1 is smaller if (points[i1].y < min.y) { min.y = points[i1].y; } if (points[i0].y > max.y) { max.y = points[i0].y; } } else { // i1 is smaller, i0 is bigger if (points[i0].y < min.y) { min.y = points[i0].y; } if (points[i1].y > max.y) { max.y = points[i1].y; } } // Z Coords if (points[i0].z > points[i1].z) { // i0 is bigger, i1 is smaller if (points[i1].z < min.z) { min.z = points[i1].z; } if (points[i0].z > max.z) { max.z = points[i0].z; } } else { // i1 is smaller, i0 is bigger if (points[i0].z < min.z) { min.z = points[i0].z; } if (points[i1].z > max.z) { max.z = points[i1].z; } } } // if array was odd, calculate also min/max for the last element if (even != Count) { // X if (min.x > points[even].x) { min.x = points[even].x; } if (max.x < points[even].x) { max.x = points[even].x; } // Y if (min.y > points[even].y) { min.y = points[even].y; } if (max.y < points[even].y) { max.y = points[even].y; } // Z if (min.z > points[even].z) { min.z = points[even].z; } if (max.z < points[even].z) { max.z = points[even].z; } } KDBounds b = new KDBounds(); b.min = min; b.max = max; return(b); }