add transforms
parent
27e3fc0990
commit
580d8eca12
@ -0,0 +1,91 @@
|
||||
package eu.jonahbauer.raytracing.scene.transform;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.BoundingBox;
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class RotateY extends Transform {
|
||||
private final double cos;
|
||||
private final double sin;
|
||||
|
||||
private final @NotNull Optional<BoundingBox> bbox;
|
||||
|
||||
public RotateY(@NotNull Hittable object, double angle) {
|
||||
super(object);
|
||||
this.cos = Math.cos(angle);
|
||||
this.sin = Math.sin(angle);
|
||||
|
||||
this.bbox = object.getBoundingBox().map(bbox -> {
|
||||
var min = new Vec3(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
|
||||
var max = new Vec3(- Double.MAX_VALUE, - Double.MAX_VALUE, - Double.MAX_VALUE);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
for (int k = 0; k < 2; k++) {
|
||||
var x = i * bbox.max().x() + (1 - i) * bbox.min().x();
|
||||
var y = j * bbox.max().y() + (1 - j) * bbox.min().y();
|
||||
var z = k * bbox.max().z() + (1 - k) * bbox.min().z();
|
||||
|
||||
var newx = cos * x + sin * z;
|
||||
var newz = -sin * x + cos * z;
|
||||
|
||||
var temp = new Vec3(newx, y, newz);
|
||||
|
||||
min = Vec3.min(min, temp);
|
||||
max = Vec3.max(max, temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new BoundingBox(min, max);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Ray transform(@NotNull Ray ray) {
|
||||
var origin = ray.origin();
|
||||
var direction = ray.direction();
|
||||
|
||||
var newOrigin = new Vec3(
|
||||
cos * origin.x() - sin * origin.z(),
|
||||
origin.y(),
|
||||
sin * origin.x() + cos * origin.z()
|
||||
);
|
||||
var newDirection = new Vec3(
|
||||
cos * direction.x() - sin * direction.z(),
|
||||
direction.y(),
|
||||
sin * direction.x() + cos * direction.z()
|
||||
);
|
||||
|
||||
return new Ray(newOrigin, newDirection);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull HitResult transform(@NotNull HitResult result) {
|
||||
var position = result.position();
|
||||
var newPosition = new Vec3(
|
||||
cos * position.x() + sin * position.z(),
|
||||
position.y(),
|
||||
- sin * position.x() + cos * position.z()
|
||||
);
|
||||
|
||||
var normal = result.normal();
|
||||
var newNormal = new Vec3(
|
||||
cos * normal.x() + sin * normal.z(),
|
||||
normal.y(),
|
||||
-sin * normal.x() + cos * normal.z()
|
||||
);
|
||||
|
||||
return new HitResult(result.t(), newPosition, newNormal, result.material(), result.frontFace());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<BoundingBox> getBoundingBox() {
|
||||
return bbox;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package eu.jonahbauer.raytracing.scene.transform;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.Range;
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
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 Transform implements Hittable {
|
||||
protected final @NotNull Hittable object;
|
||||
|
||||
protected Transform(@NotNull Hittable object) {
|
||||
this.object = Objects.requireNonNull(object);
|
||||
}
|
||||
|
||||
protected abstract @NotNull Ray transform(@NotNull Ray ray);
|
||||
|
||||
protected abstract @NotNull HitResult transform(@NotNull HitResult result);
|
||||
|
||||
@Override
|
||||
public final @NotNull Optional<HitResult> hit(@NotNull Ray ray, @NotNull Range range) {
|
||||
return object.hit(transform(ray), range).map(this::transform);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package eu.jonahbauer.raytracing.scene.transform;
|
||||
|
||||
import eu.jonahbauer.raytracing.math.BoundingBox;
|
||||
import eu.jonahbauer.raytracing.math.Ray;
|
||||
import eu.jonahbauer.raytracing.math.Vec3;
|
||||
import eu.jonahbauer.raytracing.scene.HitResult;
|
||||
import eu.jonahbauer.raytracing.scene.Hittable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class Translate extends Transform {
|
||||
private final @NotNull Vec3 offset;
|
||||
|
||||
private final @NotNull Optional<BoundingBox> bbox;
|
||||
|
||||
public Translate(@NotNull Hittable object, @NotNull Vec3 offset) {
|
||||
super(object);
|
||||
this.offset = offset;
|
||||
this.bbox = object.getBoundingBox().map(bbox -> new BoundingBox(
|
||||
bbox.min().plus(offset),
|
||||
bbox.max().plus(offset)
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Ray transform(@NotNull Ray ray) {
|
||||
return new Ray(ray.origin().minus(offset), ray.direction());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull HitResult transform(@NotNull HitResult result) {
|
||||
return new HitResult(
|
||||
result.t(),
|
||||
result.position().plus(offset),
|
||||
result.normal(),
|
||||
result.material(),
|
||||
result.frontFace()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Optional<BoundingBox> getBoundingBox() {
|
||||
return bbox;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue