add 2d primitives

main
jbb01 6 months ago
parent 86b6f1891c
commit b5acbd1b6c

@ -1,5 +1,6 @@
package eu.jonahbauer.raytracing;
import eu.jonahbauer.raytracing.render.camera.Camera;
import eu.jonahbauer.raytracing.render.material.DielectricMaterial;
import eu.jonahbauer.raytracing.render.material.LambertianMaterial;
import eu.jonahbauer.raytracing.render.material.Material;
@ -12,8 +13,11 @@ import eu.jonahbauer.raytracing.render.canvas.LiveCanvas;
import eu.jonahbauer.raytracing.render.canvas.Image;
import eu.jonahbauer.raytracing.render.renderer.SimpleRenderer;
import eu.jonahbauer.raytracing.scene.Hittable;
import eu.jonahbauer.raytracing.scene.flat.Ellipse;
import eu.jonahbauer.raytracing.scene.flat.Parallelogram;
import eu.jonahbauer.raytracing.scene.Scene;
import eu.jonahbauer.raytracing.scene.Sphere;
import eu.jonahbauer.raytracing.scene.flat.Triangle;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@ -24,16 +28,9 @@ import java.util.Random;
public class Main {
public static void main(String[] args) throws IOException {
var scene = getScene();
var camera = SimpleCamera.builder()
.withImage(1200, 675)
.withPosition(new Vec3(13, 2, 3))
.withTarget(new Vec3(0, 0, 0))
.withFieldOfView(Math.toRadians(20))
.withFocusDistance(10.0)
.withBlurAngle(Math.toRadians(0.6))
.build();
var example = getSquares();
var scene = example.scene();
var camera = example.camera();
var renderer = SimpleRenderer.builder()
.withSamplesPerPixel(500)
@ -51,7 +48,7 @@ public class Main {
ImageFormat.PNG.write(image, Path.of("scene-" + System.currentTimeMillis() + ".png"));
}
private static @NotNull Scene getScene() {
private static @NotNull Example getSpheres() {
var rng = new Random(1);
var objects = new ArrayList<Hittable>();
objects.add(new Sphere(new Vec3(0, -1000, 0), 1000, new LambertianMaterial(new Color(0.5, 0.5, 0.5))));
@ -85,7 +82,34 @@ public class Main {
objects.add(new Sphere(new Vec3(-4, 1, 0), 1.0, new LambertianMaterial(new Color(0.4, 0.2, 0.1))));
objects.add(new Sphere(new Vec3(4, 1, 0), 1.0, new MetallicMaterial(new Color(0.7, 0.6, 0.5))));
return new Scene(objects);
var camera = SimpleCamera.builder()
.withImage(1200, 675)
.withPosition(new Vec3(13, 2, 3))
.withTarget(new Vec3(0, 0, 0))
.withFieldOfView(Math.toRadians(20))
.withFocusDistance(10.0)
.withBlurAngle(Math.toRadians(0.6))
.build();
return new Example(new Scene(objects), camera);
}
private static @NotNull Example getSquares() {
return new Example(
new Scene(List.of(
new Parallelogram(new Vec3(-3, -2, 5), new Vec3(0, 0, -4), new Vec3(0, 4, 0), new LambertianMaterial(new Color(1.0, 0.2, 0.2))),
new Parallelogram(new Vec3(-2, -2, 0), new Vec3(4, 0, 0), new Vec3(0, 4, 0), new LambertianMaterial(new Color(0.2, 1.0, 0.2))),
new Parallelogram(new Vec3(3, -2, 1), new Vec3(0, 0, 4), new Vec3(0, 4, 0), new LambertianMaterial(new Color(0.2, 0.2, 1.0))),
new Parallelogram(new Vec3(-2, 3, 1), new Vec3(4, 0, 0), new Vec3(0, 0, 4), new LambertianMaterial(new Color(1.0, 0.5, 0.0))),
new Parallelogram(new Vec3(-2, -3, 5), new Vec3(4, 0, 0), new Vec3(0, 0, -4), new LambertianMaterial(new Color(0.2, 0.8, 0.8)))
)),
SimpleCamera.builder()
.withImage(400, 400)
.withFieldOfView(Math.toRadians(80))
.withPosition(new Vec3(0, 0, 9))
.withTarget(new Vec3(0, 0, 0))
.build()
);
}
private static @NotNull Scene getSimpleScene() {
@ -97,4 +121,6 @@ public class Main {
new Sphere(new Vec3(1.0, 0, -1.2), 0.5, new MetallicMaterial(new Color(0.8, 0.6, 0.2), 0.0))
));
}
private record Example(@NotNull Scene scene, @NotNull Camera camera) {}
}

@ -0,0 +1,26 @@
package eu.jonahbauer.raytracing.scene.flat;
import eu.jonahbauer.raytracing.math.BoundingBox;
import eu.jonahbauer.raytracing.math.Vec3;
import eu.jonahbauer.raytracing.render.material.Material;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public final class Ellipse extends Hittable2D {
public Ellipse(@NotNull Vec3 origin, @NotNull Vec3 u, @NotNull Vec3 v, @NotNull Material material) {
super(origin, u, v, material);
}
@Override
protected boolean isInterior(double alpha, double beta) {
return alpha * alpha + beta * beta < 1;
}
@Override
public @NotNull Optional<BoundingBox> getBoundingBox() {
var a = origin.minus(u).minus(v);
var b = origin.plus(u).plus(v);
return Optional.of(new BoundingBox(Vec3.min(a, b), Vec3.max(a, b)));
}
}

@ -0,0 +1,64 @@
package eu.jonahbauer.raytracing.scene.flat;
import eu.jonahbauer.raytracing.math.Range;
import eu.jonahbauer.raytracing.math.Ray;
import eu.jonahbauer.raytracing.math.Vec3;
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 java.util.Objects;
import java.util.Optional;
public abstract class Hittable2D implements Hittable {
protected final @NotNull Vec3 origin;
protected final @NotNull Vec3 u;
protected final @NotNull Vec3 v;
private final @NotNull Material material;
// internal
private final @NotNull Vec3 normal;
private final double d;
private final @NotNull Vec3 w;
protected Hittable2D(@NotNull Vec3 origin, @NotNull Vec3 u, @NotNull Vec3 v, @NotNull Material material) {
this.origin = Objects.requireNonNull(origin);
this.u = Objects.requireNonNull(u);
this.v = Objects.requireNonNull(v);
this.material = Objects.requireNonNull(material);
var n = u.cross(v);
if (n.squared() < 1e-8) throw new IllegalArgumentException();
this.normal = n.unit();
this.d = origin.times(normal);
this.w = n.div(n.squared());
}
@Override
public @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
var denominator = ray.direction().times(normal);
if (Math.abs(denominator) < 1e-8) return Optional.empty(); // parallel
var t = (d - ray.origin().times(normal)) / denominator;
if (!range.surrounds(t)) return Optional.empty();
var position = ray.at(t);
var p = position.minus(origin);
if (!isInterior(p)) return Optional.empty();
var frontFace = denominator < 0;
return Optional.of(new HitResult(t, position, frontFace ? normal : normal.neg(), material, frontFace));
}
protected boolean isInterior(@NotNull Vec3 p) {
var alpha = w.times(p.cross(v));
var beta = w.times(u.cross(p));
return isInterior(alpha, beta);
}
protected boolean isInterior(double alpha, double beta) {
return false;
}
}

@ -0,0 +1,27 @@
package eu.jonahbauer.raytracing.scene.flat;
import eu.jonahbauer.raytracing.math.BoundingBox;
import eu.jonahbauer.raytracing.math.Vec3;
import eu.jonahbauer.raytracing.render.material.Material;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public final class Parallelogram extends Hittable2D {
public Parallelogram(@NotNull Vec3 origin, @NotNull Vec3 u, @NotNull Vec3 v, @NotNull Material material) {
super(origin, u, v, material);
}
@Override
protected boolean isInterior(double alpha, double beta) {
return 0 <= alpha && alpha < 1 && 0 <= beta && beta < 1;
}
@Override
public @NotNull Optional<BoundingBox> getBoundingBox() {
var a = origin;
var b = origin.plus(u).plus(v);
return Optional.of(new BoundingBox(Vec3.min(a, b), Vec3.max(a, b)));
}
}

@ -0,0 +1,16 @@
package eu.jonahbauer.raytracing.scene.flat;
import eu.jonahbauer.raytracing.math.Vec3;
import eu.jonahbauer.raytracing.render.material.Material;
import org.jetbrains.annotations.NotNull;
public final class Plane extends Hittable2D {
public Plane(@NotNull Vec3 origin, @NotNull Vec3 u, @NotNull Vec3 v, @NotNull Material material) {
super(origin, u, v, material);
}
@Override
protected boolean isInterior(@NotNull Vec3 p) {
return true;
}
}

@ -0,0 +1,27 @@
package eu.jonahbauer.raytracing.scene.flat;
import eu.jonahbauer.raytracing.math.BoundingBox;
import eu.jonahbauer.raytracing.math.Vec3;
import eu.jonahbauer.raytracing.render.material.Material;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public final class Triangle extends Hittable2D {
public Triangle(@NotNull Vec3 origin, @NotNull Vec3 u, @NotNull Vec3 v, @NotNull Material material) {
super(origin, u, v, material);
}
@Override
protected boolean isInterior(double alpha, double beta) {
return 0 <= alpha && 0 <= beta && alpha + beta <= 1;
}
@Override
public @NotNull Optional<BoundingBox> getBoundingBox() {
var a = origin;
var b = origin.plus(u).plus(v);
return Optional.of(new BoundingBox(Vec3.min(a, b), Vec3.max(a, b)));
}
}
Loading…
Cancel
Save