make Vec3#random generate unit vectors by default
This commit is contained in:
parent
c0dccbbd0c
commit
89c4340821
@ -17,29 +17,33 @@ public record Vec3(double x, double y, double z) {
|
|||||||
assert Double.isFinite(x) && Double.isFinite(y) && Double.isFinite(z) : "x, y and z must be finite";
|
assert Double.isFinite(x) && Double.isFinite(y) && Double.isFinite(z) : "x, y and z must be finite";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@return a uniformly random vector with components in the range [-1, 1)}
|
|
||||||
*/
|
|
||||||
public static @NotNull Vec3 random(@NotNull RandomGenerator random) {
|
|
||||||
return new Vec3(
|
|
||||||
Math.fma(2, random.nextDouble(), -1),
|
|
||||||
Math.fma(2, random.nextDouble(), -1),
|
|
||||||
Math.fma(2, random.nextDouble(), -1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@return a uniformly random unit vector}
|
* {@return a uniformly random unit vector}
|
||||||
*/
|
*/
|
||||||
public static @NotNull Vec3 random(@NotNull RandomGenerator random, boolean unit) {
|
public static @NotNull Vec3 random(@NotNull RandomGenerator random) {
|
||||||
if (!unit) return random(random);
|
double x, y, z;
|
||||||
Vec3 vec;
|
|
||||||
double squared;
|
double squared;
|
||||||
do {
|
do {
|
||||||
vec = random(random);
|
x = Math.fma(2, random.nextDouble(), -1);
|
||||||
squared = vec.squared();
|
y = Math.fma(2, random.nextDouble(), -1);
|
||||||
|
z = Math.fma(2, random.nextDouble(), -1);
|
||||||
|
squared = x * x + y * y + z * z;
|
||||||
} while (squared > 1);
|
} while (squared > 1);
|
||||||
return vec.div(Math.sqrt(squared));
|
var factor = 1 / Math.sqrt(squared);
|
||||||
|
return new Vec3(x * factor, y * factor, z * factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull Vec3 randomOppositeHemisphere(@NotNull RandomGenerator random, @NotNull Vec3 direction) {
|
||||||
|
double x, y, z;
|
||||||
|
double squared;
|
||||||
|
do {
|
||||||
|
x = Math.fma(2, random.nextDouble(), -1);
|
||||||
|
y = Math.fma(2, random.nextDouble(), -1);
|
||||||
|
z = Math.fma(2, random.nextDouble(), -1);
|
||||||
|
squared = x * x + y * y + z * z;
|
||||||
|
} while (squared > 1 || direction.x() * x + direction.y() * y + direction.z() * z >= 0);
|
||||||
|
var factor = 1 / Math.sqrt(squared);
|
||||||
|
return new Vec3(x * factor, y * factor, z * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static @NotNull Vec3 reflect(@NotNull Vec3 vec, @NotNull Vec3 normal) {
|
public static @NotNull Vec3 reflect(@NotNull Vec3 vec, @NotNull Vec3 normal) {
|
||||||
|
@ -25,7 +25,7 @@ public record MetallicMaterial(@NotNull Texture texture, double fuzz) implements
|
|||||||
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
public @NotNull Optional<ScatterResult> scatter(@NotNull Ray ray, @NotNull HitResult hit, @NotNull RandomGenerator random) {
|
||||||
var newDirection = Vec3.reflect(ray.direction(), hit.normal());
|
var newDirection = Vec3.reflect(ray.direction(), hit.normal());
|
||||||
if (fuzz > 0) {
|
if (fuzz > 0) {
|
||||||
newDirection = newDirection.unit().plus(Vec3.random(random, true).times(fuzz));
|
newDirection = newDirection.unit().plus(Vec3.random(random).times(fuzz));
|
||||||
}
|
}
|
||||||
var attenuation = texture.get(hit);
|
var attenuation = texture.get(hit);
|
||||||
return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection)));
|
return Optional.of(new SpecularScatterResult(attenuation, new Ray(hit.position(), newDirection)));
|
||||||
|
@ -21,7 +21,7 @@ public record CosineProbabilityDensityFunction(@NotNull Vec3 normal) implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Vec3 generate(@NotNull RandomGenerator random) {
|
public @NotNull Vec3 generate(@NotNull RandomGenerator random) {
|
||||||
var out = normal().plus(Vec3.random(random, true));
|
var out = normal().plus(Vec3.random(random));
|
||||||
return out.isNearZero() ? normal() : out;
|
return out.isNearZero() ? normal() : out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,6 @@ public record SphereProbabilityDensityFunction() implements ProbabilityDensityFu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Vec3 generate(@NotNull RandomGenerator random) {
|
public @NotNull Vec3 generate(@NotNull RandomGenerator random) {
|
||||||
return Vec3.random(random, true);
|
return Vec3.random(random);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public final class PerlinTexture implements Texture {
|
|||||||
this.mask = count - 1;
|
this.mask = count - 1;
|
||||||
this.randvec = new Vec3[count];
|
this.randvec = new Vec3[count];
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
this.randvec[i] = Vec3.random(random, true);
|
this.randvec[i] = Vec3.random(random);
|
||||||
}
|
}
|
||||||
this.permX = generatePerm(count, random);
|
this.permX = generatePerm(count, random);
|
||||||
this.permY = generatePerm(count, random);
|
this.permY = generatePerm(count, random);
|
||||||
|
@ -143,7 +143,7 @@ public final class Box implements Hittable, Target {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Vec3 getTargetingDirection(@NotNull Vec3 origin, @NotNull RandomGenerator random) {
|
public @NotNull Vec3 getTargetingDirection(@NotNull Vec3 origin, @NotNull RandomGenerator random) {
|
||||||
if (contains(origin)) return Vec3.random(random, true);
|
if (contains(origin)) return Vec3.random(random);
|
||||||
|
|
||||||
// determine sides facing the origin and their solid angles
|
// determine sides facing the origin and their solid angles
|
||||||
int visible = 0;
|
int visible = 0;
|
||||||
|
@ -89,13 +89,12 @@ public final class Sphere implements Hittable, Target {
|
|||||||
@Override
|
@Override
|
||||||
public @NotNull Vec3 getTargetingDirection(@NotNull Vec3 origin, @NotNull RandomGenerator random) {
|
public @NotNull Vec3 getTargetingDirection(@NotNull Vec3 origin, @NotNull RandomGenerator random) {
|
||||||
var direction = center.minus(origin);
|
var direction = center.minus(origin);
|
||||||
|
var out = Vec3.randomOppositeHemisphere(random, direction);
|
||||||
Vec3 target;
|
return new Vec3(
|
||||||
do {
|
Math.fma(radius, out.x(), center.x() - origin.x()),
|
||||||
target = Vec3.random(random, true);
|
Math.fma(radius, out.y(), center.y() - origin.y()),
|
||||||
} while (target.times(direction) >= 0);
|
Math.fma(radius, out.z(), center.z() - origin.z())
|
||||||
|
);
|
||||||
return target.times(radius).plus(center).minus(origin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user