public KdTree(Triangle[] triangles) { var minX = float.MaxValue; var minY = float.MaxValue; var minZ = float.MaxValue; var maxX = float.MinValue; var maxY = float.MinValue; var maxZ = float.MinValue; foreach (var triangle in triangles) { if (minX > triangle.BoxMin.X) { minX = triangle.BoxMin.X; } if (minY > triangle.BoxMin.Y) { minY = triangle.BoxMin.Y; } if (minZ > triangle.BoxMin.Z) { minZ = triangle.BoxMin.Z; } if (maxX < triangle.BoxMax.X) { maxX = triangle.BoxMax.X; } if (maxY < triangle.BoxMax.Y) { maxY = triangle.BoxMax.Y; } if (maxZ < triangle.BoxMax.Z) { maxZ = triangle.BoxMax.Z; } } var boxMax = new Vector3(maxX, maxY, maxZ); var boxMin = new Vector3(minX, minY, minZ); HeadNode = new KdTreeNode(triangles, boxMin, boxMax, 1); HeadNode.SplitNode(); }
public void SplitNode() { if (_splitted) { return; } _splitted = true; if (Triangles == null || Triangles.Length == 0) { return; } CalculateElementsAmountInPossibleSubsections(); var lowestSah = float.MaxValue; var boxSplits = CalculateSplits(); var parentSquare = CalculateSquare(BoxMin, BoxMax); var bestBoxSplitIndex = 0; var axis = 0; int nLeft = 0, nRight = 0; for (var i = 0; i < SplitsNumber; i++) { var xRightN = Triangles.Length - _xHigh[i]; var xLeftN = Triangles.Length - _xLow[i + 1]; var yRightN = Triangles.Length - _yHigh[i]; var yLeftN = Triangles.Length - _yLow[i + 1]; var zRightN = Triangles.Length - _zHigh[i]; var zLeftN = Triangles.Length - _zLow[i + 1]; var xLeftSquare = CalculateSquare(BoxMin, boxSplits[i].LBoxMax); var xRightSquare = CalculateSquare(boxSplits[i].RBoxMin, BoxMax); var yLeftSquare = CalculateSquare(BoxMin, boxSplits[i + SplitsNumber].LBoxMax); var yRightSquare = CalculateSquare(boxSplits[i + SplitsNumber].RBoxMin, BoxMax); var zLeftSquare = CalculateSquare(BoxMin, boxSplits[i + SplitsNumber * 2].LBoxMax); var zRightSquare = CalculateSquare(boxSplits[i + SplitsNumber * 2].RBoxMin, BoxMax); var tmpSah = CalculateSah(xLeftSquare, xLeftN, xRightSquare, xRightN, parentSquare); if (tmpSah < lowestSah) { bestBoxSplitIndex = i; lowestSah = tmpSah; axis = 0; nLeft = xLeftN; nRight = xRightN; } tmpSah = CalculateSah(yLeftSquare, yLeftN, yRightSquare, yRightN, parentSquare); if (tmpSah < lowestSah) { bestBoxSplitIndex = i + SplitsNumber; lowestSah = tmpSah; axis = 1; nLeft = yLeftN; nRight = yRightN; } tmpSah = CalculateSah(zLeftSquare, zLeftN, zRightSquare, zRightN, parentSquare); if (tmpSah < lowestSah) { bestBoxSplitIndex = i + SplitsNumber * 2; lowestSah = tmpSah; axis = 2; nLeft = zLeftN; nRight = zRightN; } } if (Ci * lowestSah > Triangles.Length || Depth > MaxDepth) { return; } Split = boxSplits[bestBoxSplitIndex]; SplitAxis = axis; var splitTriangles = SplitTriangles(Split, axis, nLeft, nRight); LeftNode = new KdTreeNode(splitTriangles[0], BoxMin, Split.LBoxMax, Depth + 1); LeftNode.SplitNode(); RightNode = new KdTreeNode(splitTriangles[1], Split.RBoxMin, BoxMax, Depth + 1); RightNode.SplitNode(); Triangles = null; }