int GetKdNode(KdNodeBounds bounds, int start, int end) { m_nodes.Add(new KdNode { Bounds = bounds, Start = start, End = end, PartitionAxis = -1, PartitionCoordinate = 0.0f, PositiveChildIndex = -1, NegativeChildIndex = -1 }); return(m_nodes.Length - 1); }
/// <summary> /// For calculating root node bounds /// </summary> /// <returns>Boundary of all Vector3 points</returns> KdNodeBounds MakeBounds() { var max = new float3(float.MinValue, float.MinValue, float.MinValue); var min = new float3(float.MaxValue, float.MaxValue, float.MaxValue); int even = Points.Length & ~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 != Points.Length) { // 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; } } var b = new KdNodeBounds(); b.Min = min; b.Max = max; return(b); }
// TODO: When multiple points overlap exactly this function breaks. /// <summary> /// Recursive splitting procedure /// </summary> void SplitNode(int parentIndex, out int posNodeIndex, out int negNodeIndex) { KdNode parent = m_nodes[parentIndex]; // center of bounding box KdNodeBounds parentBounds = parent.Bounds; float3 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 spiting coords float splitPivot = CalculatePivot(parent.Start, parent.End, boundsStart, boundsEnd, splitAxis); // 'Spiting' array to two sub arrays int splittingIndex = Partition(parent.Start, parent.End, splitPivot, splitAxis); // Negative / Left node float3 negMax = parentBounds.Max; negMax[splitAxis] = splitPivot; var bounds = parentBounds; bounds.Max = negMax; negNodeIndex = GetKdNode(bounds, parent.Start, splittingIndex); parent.PartitionAxis = splitAxis; parent.PartitionCoordinate = splitPivot; // Positive / Right node float3 posMin = parentBounds.Min; posMin[splitAxis] = splitPivot; bounds = parentBounds; bounds.Min = posMin; posNodeIndex = GetKdNode(bounds, splittingIndex, parent.End); parent.NegativeChildIndex = negNodeIndex; parent.PositiveChildIndex = posNodeIndex; // Write back node to array to update those values m_nodes[parentIndex] = parent; }