public void CalculateStatistic(BvhNode node) { if (node.IsLeaf) { _minCount = Math.Min(_minCount, node.Objects.Length); _maxCount = Math.Max(_maxCount, node.Objects.Length); _totalCount += node.Objects.Length; _leafCount++; } else { if (node.Left != null) CalculateStatistic(node.Left); if (node.Right != null) CalculateStatistic(node.Right); } if (_leafCount != 0) { _avrCount = _totalCount / _leafCount; } }
public BvhTree BuildBvhTree(IEnumerable<Geomertry> geomertries, int maxDepth, int minObjPerLeaf, float triangleCost, float boxCost) { _maxDepth = maxDepth; _minObjectsPerLeaf = minObjPerLeaf; _triangleCost = triangleCost; _boxCost = boxCost; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); _objects = geomertries.Select(Intersectable.CreateIntersectable).ToArray(); // BoundingBox rootBoundingBox = OptimisationUtils.GetBoundingBox(geomertries); BoundingBox rootBoundingBox = CalculateBoundingBox(_objects); BvhNode root = new BvhNode(rootBoundingBox); BuildRecursive(root, _objects, 0); stopwatch.Stop(); _loger.Log(Level.Info, string.Format("BVH tree build time: {0} ms", stopwatch.ElapsedMilliseconds)); return new BvhTree(root); }
public BvhTree(BvhNode root) { _root = root; }
private void GetObjects(Ray ray, BvhNode node, List<Intersectable[]> result) { if (!ray.Intersects(node.BoundingBox).HasValue) return; float? leftIntersection = null; float? rightIntersection = null; BvhNode leftNode = node.Left; BvhNode rightNode = node.Right; if (leftNode != null) { leftIntersection = ray.Intersects(leftNode.BoundingBox); if (leftIntersection.HasValue) { if (leftNode.IsLeaf) { result.Add(leftNode.Objects); } else { GetObjects(ray, leftNode, result); } } } if (rightNode != null) { rightIntersection = ray.Intersects(rightNode.BoundingBox); if (rightIntersection.HasValue) { if (rightNode.IsLeaf) { result.Add(rightNode.Objects); } else { GetObjects(ray, rightNode, result); } } } }
private float? FindSplit(BvhNode node, Intersectable[] objects, out int axisIndexa) { float sP = BoxSurface(node.BoundingBox); int bestAxis = MaxAxisIndex(node.BoundingBox); float? bestSplit = null; float minC = float.MaxValue; for (int axis = 0; axis < 3; axis++) { Array.Sort(objects, (objA, objB) => objA.Center.AxisValue(axis).CompareTo(objB.Center.AxisValue(axis))); float[] centers = objects.Select(intersectable => intersectable.Center.AxisValue(axis)).ToArray(); float min = node.BoundingBox.Min.AxisValue(axis); float max = node.BoundingBox.Max.AxisValue(axis); float step = (max - min)/10; for (float split = min + step; split < max; split += step) { int splitIndex = Array.BinarySearch(centers, split); splitIndex = splitIndex < 0 ? ~splitIndex : splitIndex; int nL = splitIndex; int nR = objects.Length - splitIndex; float sL = BoxSurface(CalculateBoundingBox(objects, 0, nL)); float sR = BoxSurface(CalculateBoundingBox(objects, splitIndex, nR)); float c = _boxCost + (sL/sP)*nL*_triangleCost + (sR/sP)*nR*_triangleCost; if (c < minC) { minC = c; bestSplit = split; bestAxis = axis; } } } if (minC < objects.Length*_triangleCost) { axisIndexa = bestAxis; return bestSplit; } else { axisIndexa = 1; return null; } }
private void CreateAndSplitChildNode(BvhNode node, Intersectable[] objects, int splitIndex, long lenght, int depht) { var right = CopyArraySection(objects, splitIndex, lenght); node.BoundingBox = CalculateBoundingBox(right); BuildRecursive(node, right, depht); }
private void BuildRecursive(BvhNode node, Intersectable[] objects, int depht) { //var axisIndex = MaxAxisIndex(node.BoundingBox); int axisIndex; float? splitPoint = FindSplit(node, objects, out axisIndex); if (!splitPoint.HasValue || objects.Length < _minObjectsPerLeaf || depht > _maxDepth) { node.IsLeaf = true; node.Objects = objects; //Console.WriteLine("{2} {1} {0}", depht, objects.Length, Math.Max(Math.Max(node.BoundingBox.Max.X - node.BoundingBox.Min.X,node.BoundingBox.Max.Y - node.BoundingBox.Min.Y),node.BoundingBox.Max.Z - node.BoundingBox.Min.Z)); return; } Array.Sort(objects, (objA, objB) => objA.Center.AxisValue(axisIndex).CompareTo(objB.Center.AxisValue(axisIndex))); float[] centers = objects.Select(intersectable => intersectable.Center.AxisValue(axisIndex)).ToArray(); int splitIndex = Array.BinarySearch(centers, splitPoint); splitIndex = splitIndex < 0 ? ~splitIndex : splitIndex; long leftLenght = splitIndex; if (leftLenght > 0) { node.Left = new BvhNode(); CreateAndSplitChildNode(node.Left, objects, 0, leftLenght, depht + 1); } long rightLenght = objects.LongLength - splitIndex; if (rightLenght > 0) { node.Right = new BvhNode(); CreateAndSplitChildNode(node.Right, objects, splitIndex, rightLenght, depht + 1); } }