refactor AABB intersection

main
jbb01 6 months ago
parent 9b617a82a8
commit 1d48a49987

@ -316,7 +316,7 @@ public class Examples {
var x1 = x0 + w; var x1 = x0 + w;
var y1 = random.nextInt(1, 101); var y1 = random.nextInt(1, 101);
var z1 = z0 + w; var z1 = z0 + w;
boxes.add(new Box(new Vec3(x0, y0, z0), new Vec3(x1, y1, z1), ground)); boxes.add(Hittables.box(new Vec3(x0, y0, z0), new Vec3(x1, y1, z1), ground));
} }
} }
objects.add(new HittableBinaryTree(boxes)); objects.add(new HittableBinaryTree(boxes));

@ -2,6 +2,7 @@ package eu.jonahbauer.raytracing.math;
import eu.jonahbauer.raytracing.scene.Hittable; import eu.jonahbauer.raytracing.scene.Hittable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
@ -11,7 +12,6 @@ import java.util.Optional;
* An axis-aligned bounding box. * An axis-aligned bounding box.
*/ */
public record AABB(@NotNull Vec3 min, @NotNull Vec3 max) { public record AABB(@NotNull Vec3 min, @NotNull Vec3 max) {
public static final AABB UNIVERSE = new AABB(Vec3.MIN, Vec3.MAX);
public static final AABB EMPTY = new AABB(Vec3.ZERO, Vec3.ZERO); public static final AABB EMPTY = new AABB(Vec3.ZERO, Vec3.ZERO);
public static final Comparator<AABB> X_AXIS = Comparator.comparing(AABB::min, Comparator.comparingDouble(Vec3::x)); public static final Comparator<AABB> X_AXIS = Comparator.comparing(AABB::min, Comparator.comparingDouble(Vec3::x));
public static final Comparator<AABB> Y_AXIS = Comparator.comparing(AABB::min, Comparator.comparingDouble(Vec3::y)); public static final Comparator<AABB> Y_AXIS = Comparator.comparing(AABB::min, Comparator.comparingDouble(Vec3::y));
@ -57,17 +57,13 @@ public record AABB(@NotNull Vec3 min, @NotNull Vec3 max) {
} }
public boolean hit(@NotNull Ray ray) { public boolean hit(@NotNull Ray ray) {
return intersect(ray).isPresent(); return intersect(ray) != null;
} }
public @NotNull Optional<Range> intersect(@NotNull Ray ray) { public @Nullable Range intersect(@NotNull Ray ray) {
if (this == UNIVERSE) return Optional.of(Range.UNIVERSE);
if (this == EMPTY) return Optional.empty();
int vmask = ray.vmask();
var origin = ray.origin(); var origin = ray.origin();
var invDirection = ray.direction().inv(); var direction = ray.direction();
var invDirection = direction.inv();
// calculate t values for intersection points of ray with planes through min // calculate t values for intersection points of ray with planes through min
var tmin = intersect(min(), origin, invDirection); var tmin = intersect(min(), origin, invDirection);
@ -78,19 +74,27 @@ public record AABB(@NotNull Vec3 min, @NotNull Vec3 max) {
double tlmax = Double.NEGATIVE_INFINITY; // lower limit maximum double tlmax = Double.NEGATIVE_INFINITY; // lower limit maximum
double tumin = Double.POSITIVE_INFINITY; // upper limit minimum double tumin = Double.POSITIVE_INFINITY; // upper limit minimum
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
// classify t values as lower or upper limit based on vmask // classify t values as lower or upper limit based on ray direction
if ((vmask & (1 << i)) == 0) { if (direction.get(i) >= 0) {
// min is lower limit and max is upper limit // min is lower limit and max is upper limit
tlmax = Math.max(tlmax, tmin[i]); if (tmin[i] > tlmax) {
tumin = Math.min(tumin, tmax[i]); tlmax = tmin[i];
}
if (tmax[i] < tumin) {
tumin = tmax[i];
}
} else { } else {
// max is lower limit and min is upper limit // max is lower limit and min is upper limit
tlmax = Math.max(tlmax, tmax[i]); if (tmax[i] > tlmax) {
tumin = Math.min(tumin, tmin[i]); tlmax = tmax[i];
}
if (tmin[i] < tumin) {
tumin = tmin[i];
}
} }
} }
return tlmax < tumin ? Optional.of(new Range(tlmax, tumin)) : Optional.empty(); return tlmax < tumin ? new Range(tlmax, tumin) : null;
} }
public static double @NotNull[] intersect(@NotNull Vec3 corner, @NotNull Ray ray) { public static double @NotNull[] intersect(@NotNull Vec3 corner, @NotNull Ray ray) {

@ -146,6 +146,15 @@ public record Vec3(double x, double y, double z) {
return div(length()); return div(length());
} }
public double get(int axis) {
return switch (axis) {
case 0 -> x;
case 1 -> y;
case 2 -> z;
default -> throw new IndexOutOfBoundsException(axis);
};
}
public @NotNull Vec3 withX(double x) { public @NotNull Vec3 withX(double x) {
return new Vec3(x, y, z); return new Vec3(x, y, z);
} }

Loading…
Cancel
Save