use of suite.math.R3 in project suite by stupidsing.
the class BoundingBox method bound.
public static BoundingBox bound(Collection<R3> points, RtObject object) {
double min = Double.NEGATIVE_INFINITY, max = Double.POSITIVE_INFINITY;
double minX = max, minY = max, minZ = max;
double maxX = min, maxY = min, maxZ = min;
for (R3 point : points) {
double x = point.x, y = point.y, z = point.z;
minX = min(minX, x);
minY = min(minY, y);
minZ = min(minZ, z);
maxX = max(maxX, x);
maxY = max(maxY, y);
maxZ = max(maxZ, z);
}
return new BoundingBox(new R3(minX, minY, minZ), new R3(maxX, maxY, maxZ), object);
}
use of suite.math.R3 in project suite by stupidsing.
the class Sphere method hit.
@Override
public List<RayHit> hit(Ray ray) {
R3 start0 = R3.sub(ray.startPoint, center);
double a = ray.dir.abs2();
double b = 2f * R3.dot(start0, ray.dir);
double c = start0.abs2() - radius * radius;
double discriminant = b * b - 4f * a * c;
List<RayHit> rayHits;
if (0 < discriminant) {
// hit?
double sqrt = Math.sqrt(discriminant);
double denom = 1d / (2d * a);
rayHits = List.of(rayHit(ray, (-b - sqrt) * denom), rayHit(ray, (-b + sqrt) * denom));
} else
rayHits = List.of();
return rayHits;
}
use of suite.math.R3 in project suite by stupidsing.
the class Planar method hit.
@Override
public List<RayHit> hit(Ray ray) {
List<RayHit> rayHits = new ArrayList<>();
for (RayHit rayHit : plane.hit(ray)) {
R3 planarDir = R3.sub(rayHit.intersection().hitPoint(), origin);
double x = R3.dot(planarDir, axis0) * invAxis0;
double y = R3.dot(planarDir, axis1) * invAxis1;
if (isHit.isHit(x, y))
rayHits.add(rayHit);
}
return rayHits;
}
use of suite.math.R3 in project suite by stupidsing.
the class Triangle method c.
public static RtObject c(R3 origin, R3 axis0, R3 axis1, Material material) {
R3 v0 = R3.add(origin, axis0);
R3 v1 = R3.add(origin, axis1);
Triangle triangle = new Triangle(origin, axis0, axis1, material);
return BoundingBox.bound(List.of(origin, v0, v1), triangle);
}
use of suite.math.R3 in project suite by stupidsing.
the class RayTracer method traceRay.
private R3 traceRay(int depth, Ray ray) {
RayHit rayHit = nearestHit(scene.hit(ray));
R3 color1;
if (rayHit != null) {
RayIntersection i = rayHit.intersection();
R3 hitPoint = i.hitPoint();
R3 normal0 = i.normal().norm();
double dot0 = R3.dot(ray.dir, normal0);
boolean isInside = 0d < dot0;
R3 normal;
double dot;
if (!isInside) {
normal = normal0;
dot = dot0;
} else {
normal = normal0.neg();
dot = -dot0;
}
Material material = i.material();
boolean reflective = material.isReflective();
double transparency = material.transparency();
R3 color;
if ((reflective || transparency < 0d) && 0 < depth) {
double cos = -dot / ray.dir.mag();
// account reflection
R3 reflectDir = R3.add(ray.dir, normal.scale(-2d * dot));
R3 reflectPoint = R3.add(hitPoint, negligible(normal));
R3 reflectColor = traceRay(depth - 1, new Ray(reflectPoint, reflectDir));
// account refraction
double eta = isInside ? glassRefractiveIndex / airRefractiveIndex : airRefractiveIndex / glassRefractiveIndex;
double k = 1d - eta * eta * (1d - cos * cos);
R3 refractColor;
if (0 <= k) {
R3 refractDir = R3.add(ray.dir.scale(eta / ray.dir.mag()), normal.scale(eta * cos - Math.sqrt(k)));
R3 refractPoint = R3.sub(hitPoint, negligible(normal));
refractColor = traceRay(depth - 1, new Ray(refractPoint, refractDir));
} else
refractColor = R3.origin;
// accurate Fresnel equation
// double cos1 = Math.sqrt(k);
// double f0 = (eta * cos - cos1) / (eta * cos + cos1);
// double f1 = (cos - eta * cos1) / (cos + eta * cos1);
// double fresnel = (f0 * f0 + f1 * f1) / 2d;
// schlick approximation
boolean isDramaticMix = true;
double r = (airRefractiveIndex - glassRefractiveIndex) / (airRefractiveIndex + glassRefractiveIndex);
double mix = isDramaticMix ? .1d : r * r;
double cos1 = 1d - cos;
double cos2 = cos1 * cos1;
double fresnel = mix + (1d - mix) * cos1 * cos2 * cos2;
// fresnel is often too low. Mark it up for visual effect.
double fresnel1 = adjustFresnel + fresnel * (1d - adjustFresnel);
color = R3.add(reflectColor.scale(fresnel1), refractColor.scale((1d - fresnel1) * transparency));
} else {
color = R3.origin;
// account light sources
for (LightSource lightSource : lightSources) {
R3 lightDir = R3.sub(lightSource.source(), hitPoint);
double lightDot = R3.dot(lightDir, normal);
if (0d < lightDot) {
// facing the light
R3 lightPoint = R3.add(hitPoint, negligible(normal));
RayHit lightRayHit = nearestHit(scene.hit(new Ray(lightPoint, lightDir)));
if (lightRayHit == null || 1d < lightRayHit.advance()) {
R3 lightColor = lightSource.lit(hitPoint);
double cos = lightDot / lightDir.mag();
color = R3.add(color, lightColor.scale(cos));
}
}
}
}
color1 = mc(color, material.surfaceColor());
} else
color1 = ambient;
return color1;
}
Aggregations