diff --git a/src/main/java/eu/jonahbauer/raytracing/Examples.java b/src/main/java/eu/jonahbauer/raytracing/Examples.java index 2e39a32..3842977 100644 --- a/src/main/java/eu/jonahbauer/raytracing/Examples.java +++ b/src/main/java/eu/jonahbauer/raytracing/Examples.java @@ -1,5 +1,6 @@ package eu.jonahbauer.raytracing; +import eu.jonahbauer.raytracing.math.AABB; import eu.jonahbauer.raytracing.math.Vec3; import eu.jonahbauer.raytracing.render.texture.CheckerTexture; import eu.jonahbauer.raytracing.render.texture.Color; @@ -162,12 +163,11 @@ public class Examples { return new Example( new Scene( - new Parallelogram(new Vec3(555, 0, 0), new Vec3(0, 555, 0), new Vec3(0, 0, 555), green), - new Parallelogram(new Vec3(0, 0, 0), new Vec3(0, 555, 0), new Vec3(0, 0, 555), red), + new Box( + new AABB(new Vec3(0, 0, 0), new Vec3(555, 555, 555)), + white, white, red, green, white, null + ), new Parallelogram(new Vec3(343, 554, 332), new Vec3(-130, 0, 0), new Vec3(0, 0, -105), light), - new Parallelogram(new Vec3(0, 0, 0), new Vec3(555, 0, 0), new Vec3(0, 0, 555), white), - new Parallelogram(new Vec3(555, 555, 555), new Vec3(-555, 0, 0), new Vec3(0, 0, -555), white), - new Parallelogram(new Vec3(0, 0, 555), new Vec3(555, 0, 0), new Vec3(0, 555, 0), white), new Box(new Vec3(0, 0, 0), new Vec3(165, 330, 165), white).rotateY(Math.toRadians(15)).translate(new Vec3(265, 0, 295)), new Box(new Vec3(0, 0, 0), new Vec3(165, 165, 165), white).rotateY(Math.toRadians(-18)).translate(new Vec3(130, 0, 65)) ), @@ -189,12 +189,11 @@ public class Examples { return new Example( new Scene( - new Parallelogram(new Vec3(555, 0, 0), new Vec3(0, 555, 0), new Vec3(0, 0, 555), green), - new Parallelogram(new Vec3(0, 0, 0), new Vec3(0, 555, 0), new Vec3(0, 0, 555), red), + new Box( + new AABB(new Vec3(0, 0, 0), new Vec3(555, 555, 555)), + white, white, red, green, white, null + ), new Parallelogram(new Vec3(113, 554, 127), new Vec3(330, 0, 0), new Vec3(0, 0, 305), light), - new Parallelogram(new Vec3(0, 0, 0), new Vec3(555, 0, 0), new Vec3(0, 0, 555), white), - new Parallelogram(new Vec3(555, 555, 555), new Vec3(-555, 0, 0), new Vec3(0, 0, -555), white), - new Parallelogram(new Vec3(0, 0, 555), new Vec3(555, 0, 0), new Vec3(0, 555, 0), white), new ConstantMedium( new Box(new Vec3(0, 0, 0), new Vec3(165, 330, 165), white).rotateY(Math.toRadians(15)).translate(new Vec3(265, 0, 295)), 0.01, new IsotropicMaterial(Color.BLACK) diff --git a/src/main/java/eu/jonahbauer/raytracing/scene/hittable3d/Box.java b/src/main/java/eu/jonahbauer/raytracing/scene/hittable3d/Box.java index 5675318..d1ccbaa 100644 --- a/src/main/java/eu/jonahbauer/raytracing/scene/hittable3d/Box.java +++ b/src/main/java/eu/jonahbauer/raytracing/scene/hittable3d/Box.java @@ -8,21 +8,33 @@ import eu.jonahbauer.raytracing.render.material.Material; import eu.jonahbauer.raytracing.scene.HitResult; import eu.jonahbauer.raytracing.scene.Hittable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Objects; import java.util.Optional; -public record Box(@NotNull AABB box, @NotNull Material material) implements Hittable { - - public Box { - Objects.requireNonNull(box, "box"); - Objects.requireNonNull(material, "material"); - } +public final class Box implements Hittable { + private final @NotNull AABB box; + private final @Nullable Material @NotNull[] materials; public Box(@NotNull Vec3 a, @NotNull Vec3 b, @NotNull Material material) { this(new AABB(a, b), material); } + public Box(@NotNull AABB box, @NotNull Material material) { + this(box, Objects.requireNonNull(material, "material"), material, material, material, material, material); + } + + public Box( + @NotNull AABB box, + @Nullable Material top, @Nullable Material bottom, + @Nullable Material left, @Nullable Material right, + @Nullable Material front, @Nullable Material back + ) { + this.box = Objects.requireNonNull(box, "box"); + this.materials = new Material[] { left, bottom, back, right, top, front }; + } + @Override public @NotNull Optional hit(@NotNull Ray ray, @NotNull Range range) { // based on AABB#hit with additional detection of the side hit @@ -70,22 +82,29 @@ public record Box(@NotNull AABB box, @NotNull Material material) implements Hitt } private @NotNull Optional hit0(double tmin, double tmax, @NotNull Side entry, @NotNull Side exit, @NotNull Ray ray, @NotNull Range range) { - boolean frontFace; double t; - if (range.surrounds(tmin)) { - frontFace = true; + Side side; + boolean frontFace; + Material material; + Vec3 normal; + if (range.surrounds(tmin) && materials[entry.ordinal()] != null) { t = tmin; - } else if (range.surrounds(tmax)) { - frontFace = false; + side = entry; + frontFace = true; + material = materials[side.ordinal()]; + normal = side.normal; + } else if (range.surrounds(tmax) && materials[exit.ordinal()] != null) { t = tmax; + side = exit; + frontFace = false; + material = materials[side.ordinal()]; + normal = side.normal.neg(); } else { return Optional.empty(); } - var side = frontFace ? entry : exit; - var normal = frontFace ? side.normal : side.normal.neg(); var position = ray.at(t); - var uv = material().texture().isUVRequired(); + var uv = material.texture().isUVRequired(); var u = uv ? side.getTextureU(box, position) : Double.NaN; var v = uv ? side.getTextureV(box, position) : Double.NaN; return Optional.of(new HitResult(t, position, normal, material, u, v, frontFace));