add 2d primitives
This commit is contained in:
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)));
|
||||
}
|
||||
}
|
16
src/main/java/eu/jonahbauer/raytracing/scene/flat/Plane.java
Normal file
16
src/main/java/eu/jonahbauer/raytracing/scene/flat/Plane.java
Normal file
@ -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…
x
Reference in New Issue
Block a user