Skip to content

Commit 56af3b2

Browse files
committed
Raytracing: The Next Week features added
1 parent 0124d64 commit 56af3b2

32 files changed

+1306
-82
lines changed

src/RayTracing/Camera.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ Ray get_ray(double s, double t) {
3636

3737
Point o = origin.add(offset);
3838
Vec3 l = lower_left_corner.add(horizontal.multiply(s)).add(vertical.multiply(1-t)).minus(origin).minus(offset);
39+
double time = Utility.randomDouble(0,1);
3940

40-
return new Ray(o,l);
41+
return new Ray(o, l, time);
4142
}
4243
}

src/RayTracing/HitInfo/HitRecord.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@
88
public class HitRecord {
99
public double t;
1010
public Point p;
11+
public double u;
12+
public double v;
1113
public Vec3 normal;
12-
public boolean front_face;
14+
public boolean frontFace;
1315
public Material mat;
1416

1517

16-
public void set_face_normal(Ray r, Vec3 outward_normal)
18+
public void setFaceNormal(Ray r, Vec3 outward_normal)
1719
{
18-
front_face = r.dir().dot(outward_normal) < 0;
19-
normal = front_face ? outward_normal : outward_normal.negative();
20+
frontFace = r.dir().dot(outward_normal) < 0;
21+
normal = frontFace ? outward_normal : outward_normal.negative();
2022
}
2123
}

src/RayTracing/HitInfo/Interval.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ public Interval expand(double delta) {
1515
return new Interval(min - padding, max + padding);
1616
}
1717

18+
public Interval addOffset(double offset) {
19+
return new Interval(min + offset, max + offset);
20+
}
21+
1822
public boolean contains(double x) {
1923
return min <= x && x <= max;
2024
}

src/RayTracing/HitInfo/Radiance.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ public class Radiance {
1010
public Ray scattered;
1111

1212
public Radiance(){
13-
scattered = new Ray(new Point(0), new Vec3(0));
13+
scattered = new Ray(new Point(0), new Vec3(0), 0);
1414
attenuation = new Color(0);
1515
}
1616
}

src/RayTracing/Hittable/AABB.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package RayTracing.Hittable;
2+
3+
import RayTracing.HitInfo.Interval;
4+
import RayTracing.Point;
5+
import RayTracing.Ray;
6+
7+
public class AABB {
8+
Interval x, y, z;
9+
10+
AABB(){
11+
this.x = new Interval(0,0);
12+
this.y = new Interval(0,0);
13+
this.z = new Interval(0,0);
14+
}
15+
16+
AABB(Interval x, Interval y, Interval z){
17+
this.x = x;
18+
this.y = y;
19+
this.z = z;
20+
}
21+
22+
AABB(Point a, Point b){
23+
this.x = new Interval(Math.min(a.x, b.x), Math.max(a.x, b.x));
24+
this.y = new Interval(Math.min(a.y, b.y), Math.max(a.y, b.y));
25+
this.z = new Interval(Math.min(a.z, b.z), Math.max(a.z, b.z));
26+
}
27+
28+
AABB(AABB a, AABB b){
29+
this.x = a.x.merge(b.x);
30+
this.y = a.y.merge(b.y);
31+
this.z = a.z.merge(b.z);
32+
}
33+
34+
AABB pad(){
35+
double delta = 0.0001;
36+
Interval x = this.x.size() >= delta ? this.x : this.x.expand(delta);
37+
Interval y = this.y.size() >= delta ? this.y : this.y.expand(delta);
38+
Interval z = this.z.size() >= delta ? this.z : this.z.expand(delta);
39+
return new AABB(x, y, z);
40+
}
41+
42+
Interval axis(int i){
43+
if(i == 1)
44+
return y;
45+
else if(i == 2)
46+
return z;
47+
else
48+
return x;
49+
}
50+
51+
AABB addOffset(Point offset){
52+
return new AABB(x.addOffset(offset.x), y.addOffset(offset.y), z.addOffset(offset.z));
53+
}
54+
55+
boolean greaterThan(AABB b, int axis){
56+
return axis(axis).min() > b.axis(axis).min();
57+
}
58+
59+
boolean lessThan(AABB b, int axis){
60+
return axis(axis).max() < b.axis(axis).max();
61+
}
62+
63+
// AABB Pixar`s algorithm
64+
boolean hit(Ray r, Interval t){
65+
for(int a = 0; a < 3; a++){
66+
double invD = 1.0 / r.dir().toArray()[a];
67+
double t0 = (axis(a).min() - r.orig().toArray()[a]) * invD;
68+
double t1 = (axis(a).max() - r.orig().toArray()[a]) * invD;
69+
if (invD < 0.0f){
70+
double s = t1;
71+
t1 = t0;
72+
t0 = s;
73+
}
74+
t = new Interval(Math.max(t0, t.min()), Math.min(t1, t.max()));
75+
if (t.max() <= t.min())
76+
return false;
77+
}
78+
return true;
79+
}
80+
}

src/RayTracing/Hittable/BVH.java

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package RayTracing.Hittable;
2+
3+
import RayTracing.HitInfo.HitRecord;
4+
import RayTracing.HitInfo.Interval;
5+
import RayTracing.Ray;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
10+
import static RayTracing.Utility.randomInt;
11+
12+
public class BVH implements Hittable{
13+
Hittable left;
14+
Hittable right;
15+
AABB box;
16+
Hittable object;
17+
18+
public BVH(List<Hittable> objects){
19+
box = new AABB();
20+
int axis = randomInt(0,2);
21+
int objectSpan = objects.size();
22+
23+
if (objectSpan == 1)
24+
{
25+
object = objects.get(0);
26+
box = object.boundingBox();
27+
}else if (objectSpan == 2)
28+
{
29+
if (boxLessThan(objects.get(0), objects.get(1), axis)) {
30+
left = objects.get(0);
31+
right = objects.get(1);
32+
} else {
33+
left = objects.get(1);
34+
right = objects.get(0);
35+
}
36+
box = new AABB(left.boundingBox(), right.boundingBox());
37+
}else
38+
{
39+
objects.sort((a, b) -> {
40+
if(boxLessThan(a, b, axis)) // if a < b
41+
return 1;
42+
else if (boxGreaterThan(a, b, axis)) // if a > b
43+
return -1;
44+
else
45+
return 0;
46+
});
47+
48+
int mid = objectSpan/2;
49+
left = new BVH(objects.subList(0, mid));
50+
right = new BVH(objects.subList(mid, objectSpan));
51+
box = new AABB(left.boundingBox(), right.boundingBox());
52+
}
53+
}
54+
55+
boolean boxLessThan(Hittable a, Hittable b, int axis_index) {
56+
return a.boundingBox().axis(axis_index).min() < b.boundingBox().axis(axis_index).min();
57+
}
58+
59+
boolean boxGreaterThan(Hittable a, Hittable b, int axis_index) {
60+
return a.boundingBox().axis(axis_index).min() > b.boundingBox().axis(axis_index).min();
61+
}
62+
63+
@Override
64+
public boolean hit(Ray r, Interval t, HitRecord rec) {
65+
if (object != null)
66+
return object.hit(r, t, rec);
67+
68+
if (!box.hit(r, t))
69+
return false;
70+
71+
rec.t = t.max();
72+
boolean hit_left = left.hit(r, new Interval(t.min(), rec.t), rec);
73+
boolean hit_right = right.hit(r, new Interval(t.min(), rec.t), rec);
74+
75+
return hit_left || hit_right;
76+
}
77+
78+
@Override
79+
public AABB boundingBox() {
80+
return box;
81+
}
82+
}
Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
1-
package RayTracing.HitTable;
1+
package RayTracing.Hittable;
22

33
import RayTracing.HitInfo.HitRecord;
44
import RayTracing.HitInfo.Interval;
55
import RayTracing.Ray;
66

77
import java.util.ArrayList;
88

9-
public class HitList implements HitTable {
10-
11-
public ArrayList<HitTable> objects;
9+
public class HitList implements Hittable {
10+
public ArrayList<Hittable> objects;
11+
AABB box;
1212

1313
public HitList(){
1414
objects = new ArrayList<>();
15+
box = new AABB();
16+
}
17+
18+
public HitList(Hittable object){
19+
objects = new ArrayList<>();
20+
objects.add(object);
21+
box = new AABB();
1522
}
1623

17-
public void add(HitTable object)
24+
public void add(Hittable object)
1825
{
1926
objects.add(object);
27+
box = new AABB(box, object.boundingBox());
2028
}
2129

2230
public void clear()
@@ -27,12 +35,17 @@ public void clear()
2735
@Override
2836
public boolean hit(Ray r, Interval t, HitRecord rec) {
2937
boolean hit_anything = false;
30-
for (HitTable object : objects) {
38+
for (Hittable object : objects) {
3139
if (object.hit(r, t, rec)) {
3240
t = new Interval(t.min(), rec.t);
3341
hit_anything = true;
3442
}
3543
}
3644
return hit_anything;
3745
}
46+
47+
@Override
48+
public AABB boundingBox() {
49+
return box;
50+
}
3851
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
package RayTracing.HitTable;
1+
package RayTracing.Hittable;
22

33
import RayTracing.HitInfo.HitRecord;
44
import RayTracing.HitInfo.Interval;
55
import RayTracing.Ray;
66

77

8-
public interface HitTable {
8+
public interface Hittable {
99
boolean hit(Ray r, Interval t, HitRecord rec);
10+
11+
AABB boundingBox();
1012
}

src/RayTracing/Hittable/Medium.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package RayTracing.Hittable;
2+
3+
import RayTracing.Color;
4+
import RayTracing.HitInfo.HitRecord;
5+
import RayTracing.HitInfo.Interval;
6+
import RayTracing.Material.Isotropic;
7+
import RayTracing.Material.Material;
8+
import RayTracing.Ray;
9+
import RayTracing.Texture.Texture;
10+
import RayTracing.Vec3;
11+
12+
import static RayTracing.Utility.randomDouble;
13+
14+
public class Medium implements Hittable{
15+
Hittable boundary;
16+
Material phaseFunction;
17+
double negInvDensity;
18+
19+
public Medium(Hittable boundary, double density, Color c) {
20+
this.boundary = boundary;
21+
negInvDensity = -1.0 / density;
22+
phaseFunction = new Isotropic(c);
23+
}
24+
25+
public Medium(Hittable boundary, double density, Texture t) {
26+
this.boundary = boundary;
27+
negInvDensity = -1.0 / density;
28+
phaseFunction = new Isotropic(t);
29+
}
30+
31+
@Override
32+
public boolean hit(Ray r, Interval t, HitRecord rec) {
33+
HitRecord point1 = new HitRecord(), point2 = new HitRecord();
34+
if (!boundary.hit(r, new Interval(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), point1))
35+
return false;
36+
37+
if (!boundary.hit(r, new Interval(point1.t+0.0001, Double.POSITIVE_INFINITY), point2))
38+
return false;
39+
40+
if (point1.t < t.min()) point1.t = t.min();
41+
if (point2.t > t.max()) point2.t = t.max();
42+
43+
if (point1.t >= point2.t)
44+
return false;
45+
46+
if (point1.t < 0)
47+
point1.t = 0;
48+
49+
double rayLength = r.dir().length();
50+
double distanceInsideBoundary = (point2.t - point1.t) * rayLength;
51+
double hitDistance = negInvDensity * Math.log(randomDouble());
52+
53+
if (hitDistance > distanceInsideBoundary)
54+
return false;
55+
56+
rec.t = point1.t + hitDistance / rayLength;
57+
rec.p = r.at(rec.t);
58+
rec.normal = new Vec3(1,0,0); // arbitrary
59+
rec.frontFace = true; // also arbitrary
60+
rec.mat = phaseFunction;
61+
62+
return true;
63+
}
64+
65+
@Override
66+
public AABB boundingBox() {
67+
return boundary.boundingBox();
68+
}
69+
}

0 commit comments

Comments
 (0)