private int BoxCompare(IHittable a, IHittable b, int axis) { var boxA = a.BoundingBox(); var boxB = b.BoundingBox(); return(boxA.Min[axis].CompareTo(boxB.Min[axis])); }
private static int BoxCompare(IHittable a, IHittable b, int axis) { if (!a.BoundingBox(0, 1, out var boxA) || !b.BoundingBox(0, 1, out var boxB)) { throw new Exception("No bounding box found in BoxCompare!"); } return(boxA.Min[axis].CompareTo(boxB.Min[axis])); }
public bool BoundingBox(double t0, double t1, out Aabb outputBox) { if (!Child.BoundingBox(t0, t1, out outputBox)) { return(false); } outputBox = new Aabb { Min = outputBox.Min + Offset, Max = outputBox.Max + Offset }; return(true); }
public RotateY(IHittable child, double angle) { Child = child; var radians = MathUtils.Deg2Rad(angle); SinTheta = Math.Sin(radians); CosTheta = Math.Cos(radians); HasBox = Child.BoundingBox(0, 1, out var box); var min = new Vec3(MathUtils.Infinity, MathUtils.Infinity, MathUtils.Infinity); var max = new Vec3(-MathUtils.Infinity, -MathUtils.Infinity, -MathUtils.Infinity); for (var i = 0; i < 2; i++) { for (var j = 0; j < 2; j++) { for (var k = 0; k < 2; k++) { var x = i * box.Max.x + (1 - i) * box.Min.x; var y = j * box.Max.y + (1 - j) * box.Min.y; var z = k * box.Max.z + (1 - k) * box.Min.z; var newX = CosTheta * x + SinTheta * z; var newZ = -SinTheta * x + CosTheta * z; var tester = new Vec3(newX, y, newZ); for (int c = 0; c < 3; c++) { min[c] = Math.Min(min[c], tester[c]); max[c] = Math.Max(max[c], tester[c]); } } } } BBox = new Aabb { Min = min, Max = max }; }
// https://raytracing.github.io/books/RayTracingTheNextWeek.html#boundingvolumehierarchies public BvhNode(List <IHittable> srcObjects, int start, int end, AbstractSampler <int> sampler = null) { sampler ??= new ThreadSafeSampler <int>(count => IntSampling.Random(count, 0, 3), SAMPLES); var objects = srcObjects; int axis = sampler.GetSample(); int Comparator(IHittable a, IHittable b) => BoxCompare(a, b, axis); int objectSpan = end - start; switch (objectSpan) { case 1: _left = _right = objects[start]; break; case 2 when Comparator(objects[start], objects[start + 1]) < 0: _left = objects[start]; _right = objects[start + 1]; break; case 2: _left = objects[start + 1]; _right = objects[start]; break; default: objects.Sort(start, objectSpan - 1, new FuncComparer <IHittable>(Comparator)); int mid = start + objectSpan / 2; _left = new BvhNode(objects, start, mid, sampler); _right = new BvhNode(objects, mid, end, sampler); break; } var boxLeft = _left.BoundingBox(); var boxRight = _right.BoundingBox(); _box = boxLeft + boxRight; }
public BvhNode(List <IHittable> srcObjects, int start, int end, double t0, double t1) { var min = new Vec3(MathUtils.Infinity, MathUtils.Infinity, MathUtils.Infinity); var max = new Vec3(-MathUtils.Infinity, -MathUtils.Infinity, -MathUtils.Infinity); for (var i = start; i < end; i++) { srcObjects[i].BoundingBox(t0, t1, out var box); if (box.Min.x < min.x) { min.x = box.Min.x; } if (box.Min.y < min.y) { min.y = box.Min.y; } if (box.Min.z < min.z) { min.z = box.Min.z; } if (box.Max.x > max.x) { max.x = box.Max.x; } if (box.Max.y > max.y) { max.y = box.Max.y; } if (box.Max.z > max.z) { max.z = box.Max.z; } } var diffs = max - min; var axis = 0; if (diffs.y > diffs.x && diffs.y > diffs.z) { axis = 1; } if (diffs.z > diffs.x && diffs.z > diffs.y) { axis = 2; } IComparer <IHittable> comparator; switch (axis) { case 0: comparator = new BoxCompareX(); break; case 1: comparator = new BoxCompareY(); break; default: comparator = new BoxCompareZ(); break; } var objSpan = end - start; if (objSpan == 1) { Left = srcObjects[start]; Right = srcObjects[start]; } else if (objSpan == 2) { if (comparator.Compare(srcObjects[start], srcObjects[start + 1]) < 0) { Left = srcObjects[start]; Right = srcObjects[start + 1]; } else { Left = srcObjects[start + 1]; Right = srcObjects[start]; } } else { srcObjects.Sort(start, objSpan, comparator); var mid = start + objSpan / 2; Left = new BvhNode(srcObjects, start, mid, t0, t1); Right = new BvhNode(srcObjects, mid, end, t0, t1); } if (!Left.BoundingBox(t0, t1, out var boxLeft) || !Right.BoundingBox(t0, t1, out var boxRight)) { throw new Exception("No bounding box in BvhNode constructor"); } Box = Aabb.SurroundingBox(boxLeft, boxRight); }
public bool BoundingBox(double t0, double t1, out Aabb outputBox) { return(Boundary.BoundingBox(t0, t1, out outputBox)); }