Skip to content

Commit e8d03a9

Browse files
author
Peter Shirley
committed
First commit of code from Ray Tracing the Next Week
1 parent 1c6891f commit e8d03a9

19 files changed

+8659
-0
lines changed

aabb.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#ifndef AABBH
2+
#define AABBH
3+
#include "ray.h"
4+
#include "hitable.h"
5+
6+
inline float ffmin(float a, float b) { return a < b ? a : b; }
7+
inline float ffmax(float a, float b) { return a > b ? a : b; }
8+
9+
class aabb {
10+
public:
11+
aabb() {}
12+
aabb(const vec3& a, const vec3& b) { _min = a; _max = b;}
13+
14+
vec3 min() const {return _min; }
15+
vec3 max() const {return _max; }
16+
17+
bool hit(const ray& r, float tmin, float tmax) const {
18+
for (int a = 0; a < 3; a++) {
19+
float t0 = ffmin((_min[a] - r.origin()[a]) / r.direction()[a],
20+
(_max[a] - r.origin()[a]) / r.direction()[a]);
21+
float t1 = ffmax((_min[a] - r.origin()[a]) / r.direction()[a],
22+
(_max[a] - r.origin()[a]) / r.direction()[a]);
23+
tmin = ffmax(t0, tmin);
24+
tmax = ffmin(t1, tmax);
25+
if (tmax <= tmin)
26+
return false;
27+
}
28+
return true;
29+
}
30+
31+
vec3 _min;
32+
vec3 _max;
33+
};
34+
35+
aabb surrounding_box(aabb box0, aabb box1) {
36+
vec3 small( fmin(box0.min().x(), box1.min().x()),
37+
fmin(box0.min().y(), box1.min().y()),
38+
fmin(box0.min().z(), box1.min().z()));
39+
vec3 big ( fmax(box0.max().x(), box1.max().x()),
40+
fmax(box0.max().y(), box1.max().y()),
41+
fmax(box0.max().z(), box1.max().z()));
42+
return aabb(small,big);
43+
}
44+
45+
46+
#endif
47+
48+
49+
50+
51+

aarect.h

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#ifndef AARECTH
2+
#define AARECTH
3+
4+
#include "hitable.h"
5+
6+
class xy_rect: public hitable {
7+
public:
8+
xy_rect() {}
9+
xy_rect(float _x0, float _x1, float _y0, float _y1, float _k, material *mat) : x0(_x0), x1(_x1), y0(_y0), y1(_y1), k(_k), mp(mat) {};
10+
virtual bool hit(const ray& r, float t0, float t1, hit_record& rec) const;
11+
virtual bool bounding_box(float t0, float t1, aabb& box) const {
12+
box = aabb(vec3(x0,y0, k-0.0001), vec3(x1, y1, k+0.0001));
13+
return true; }
14+
material *mp;
15+
float x0, x1, y0, y1, k;
16+
};
17+
18+
class xz_rect: public hitable {
19+
public:
20+
xz_rect() {}
21+
xz_rect(float _x0, float _x1, float _z0, float _z1, float _k, material *mat) : x0(_x0), x1(_x1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
22+
virtual bool hit(const ray& r, float t0, float t1, hit_record& rec) const;
23+
virtual bool bounding_box(float t0, float t1, aabb& box) const {
24+
box = aabb(vec3(x0,k-0.0001,z0), vec3(x1, k+0.0001, z1));
25+
return true; }
26+
material *mp;
27+
float x0, x1, z0, z1, k;
28+
};
29+
30+
class yz_rect: public hitable {
31+
public:
32+
yz_rect() {}
33+
yz_rect(float _y0, float _y1, float _z0, float _z1, float _k, material *mat) : y0(_y0), y1(_y1), z0(_z0), z1(_z1), k(_k), mp(mat) {};
34+
virtual bool hit(const ray& r, float t0, float t1, hit_record& rec) const;
35+
virtual bool bounding_box(float t0, float t1, aabb& box) const {
36+
box = aabb(vec3(k-0.0001, y0, z0), vec3(k+0.0001, y1, z1));
37+
return true; }
38+
material *mp;
39+
float y0, y1, z0, z1, k;
40+
};
41+
42+
43+
44+
45+
bool xy_rect::hit(const ray& r, float t0, float t1, hit_record& rec) const {
46+
float t = (k-r.origin().z()) / r.direction().z();
47+
if (t < t0 || t > t1)
48+
return false;
49+
float x = r.origin().x() + t*r.direction().x();
50+
float y = r.origin().y() + t*r.direction().y();
51+
if (x < x0 || x > x1 || y < y0 || y > y1)
52+
return false;
53+
rec.u = (x-x0)/(x1-x0);
54+
rec.v = (y-y0)/(y1-y0);
55+
rec.t = t;
56+
rec.mat_ptr = mp;
57+
rec.p = r.point_at_parameter(t);
58+
rec.normal = vec3(0, 0, 1);
59+
return true;
60+
}
61+
62+
63+
bool xz_rect::hit(const ray& r, float t0, float t1, hit_record& rec) const {
64+
float t = (k-r.origin().y()) / r.direction().y();
65+
if (t < t0 || t > t1)
66+
return false;
67+
float x = r.origin().x() + t*r.direction().x();
68+
float z = r.origin().z() + t*r.direction().z();
69+
if (x < x0 || x > x1 || z < z0 || z > z1)
70+
return false;
71+
rec.u = (x-x0)/(x1-x0);
72+
rec.v = (z-z0)/(z1-z0);
73+
rec.t = t;
74+
rec.mat_ptr = mp;
75+
rec.p = r.point_at_parameter(t);
76+
rec.normal = vec3(0, 1, 0);
77+
return true;
78+
}
79+
80+
bool yz_rect::hit(const ray& r, float t0, float t1, hit_record& rec) const {
81+
float t = (k-r.origin().x()) / r.direction().x();
82+
if (t < t0 || t > t1)
83+
return false;
84+
float y = r.origin().y() + t*r.direction().y();
85+
float z = r.origin().z() + t*r.direction().z();
86+
if (y < y0 || y > y1 || z < z0 || z > z1)
87+
return false;
88+
rec.u = (y-y0)/(y1-y0);
89+
rec.v = (z-z0)/(z1-z0);
90+
rec.t = t;
91+
rec.mat_ptr = mp;
92+
rec.p = r.point_at_parameter(t);
93+
rec.normal = vec3(1, 0, 0);
94+
return true;
95+
}
96+
97+
#endif

box.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef BOXH
2+
#define BOXH
3+
4+
#include "aarect.h"
5+
#include "hitable_list.h"
6+
7+
class box: public hitable {
8+
public:
9+
box() {}
10+
box(const vec3& p0, const vec3& p1, material *ptr);
11+
virtual bool hit(const ray& r, float t0, float t1, hit_record& rec) const;
12+
virtual bool bounding_box(float t0, float t1, aabb& box) const {
13+
box = aabb(pmin, pmax);
14+
return true; }
15+
vec3 pmin, pmax;
16+
hitable *list_ptr;
17+
};
18+
19+
box::box(const vec3& p0, const vec3& p1, material *ptr) {
20+
pmin = p0;
21+
pmax = p1;
22+
hitable **list = new hitable*[6];
23+
list[0] = new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p1.z(), ptr);
24+
list[1] = new flip_normals(new xy_rect(p0.x(), p1.x(), p0.y(), p1.y(), p0.z(), ptr));
25+
list[2] = new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p1.y(), ptr);
26+
list[3] = new flip_normals(new xz_rect(p0.x(), p1.x(), p0.z(), p1.z(), p0.y(), ptr));
27+
list[4] = new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p1.x(), ptr);
28+
list[5] = new flip_normals(new yz_rect(p0.y(), p1.y(), p0.z(), p1.z(), p0.x(), ptr));
29+
list_ptr = new hitable_list(list,6);
30+
}
31+
32+
bool box::hit(const ray& r, float t0, float t1, hit_record& rec) const {
33+
return list_ptr->hit(r, t0, t1, rec);
34+
}
35+
36+
#endif

bvh.h

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#ifndef BVHH
2+
#define BVHH
3+
4+
#include "hitable.h"
5+
6+
class bvh_node : public hitable {
7+
public:
8+
bvh_node() {}
9+
bvh_node(hitable **l, int n, float time0, float time1);
10+
virtual bool hit(const ray& r, float tmin, float tmax, hit_record& rec) const;
11+
virtual bool bounding_box(float t0, float t1, aabb& box) const;
12+
hitable *left;
13+
hitable *right;
14+
aabb box;
15+
};
16+
17+
18+
bool bvh_node::bounding_box(float t0, float t1, aabb& b) const {
19+
b = box;
20+
return true;
21+
}
22+
23+
bool bvh_node::hit(const ray& r, float t_min, float t_max, hit_record& rec) const {
24+
if (box.hit(r, t_min, t_max)) {
25+
hit_record left_rec, right_rec;
26+
bool hit_left = left->hit(r, t_min, t_max, left_rec);
27+
bool hit_right = right->hit(r, t_min, t_max, right_rec);
28+
if (hit_left && hit_right) {
29+
if (left_rec.t < right_rec.t)
30+
rec = left_rec;
31+
else
32+
rec = right_rec;
33+
return true;
34+
}
35+
else if (hit_left) {
36+
rec = left_rec;
37+
return true;
38+
}
39+
else if (hit_right) {
40+
rec = right_rec;
41+
return true;
42+
}
43+
else
44+
return false;
45+
}
46+
else return false;
47+
}
48+
49+
50+
int box_x_compare (const void * a, const void * b) {
51+
aabb box_left, box_right;
52+
hitable *ah = *(hitable**)a;
53+
hitable *bh = *(hitable**)b;
54+
if(!ah->bounding_box(0,0, box_left) || !bh->bounding_box(0,0, box_right))
55+
std::cerr << "no bounding box in bvh_node constructor\n";
56+
if ( box_left.min().x() - box_right.min().x() < 0.0 )
57+
return -1;
58+
else
59+
return 1;
60+
}
61+
62+
int box_y_compare (const void * a, const void * b)
63+
{
64+
aabb box_left, box_right;
65+
hitable *ah = *(hitable**)a;
66+
hitable *bh = *(hitable**)b;
67+
if(!ah->bounding_box(0,0, box_left) || !bh->bounding_box(0,0, box_right))
68+
std::cerr << "no bounding box in bvh_node constructor\n";
69+
if ( box_left.min().y() - box_right.min().y() < 0.0 )
70+
return -1;
71+
else
72+
return 1;
73+
}
74+
int box_z_compare (const void * a, const void * b)
75+
{
76+
aabb box_left, box_right;
77+
hitable *ah = *(hitable**)a;
78+
hitable *bh = *(hitable**)b;
79+
if(!ah->bounding_box(0,0, box_left) || !bh->bounding_box(0,0, box_right))
80+
std::cerr << "no bounding box in bvh_node constructor\n";
81+
if ( box_left.min().z() - box_right.min().z() < 0.0 )
82+
return -1;
83+
else
84+
return 1;
85+
}
86+
87+
88+
bvh_node::bvh_node(hitable **l, int n, float time0, float time1) {
89+
int axis = int(3*drand48());
90+
if (axis == 0)
91+
qsort(l, n, sizeof(hitable *), box_x_compare);
92+
else if (axis == 1)
93+
qsort(l, n, sizeof(hitable *), box_y_compare);
94+
else
95+
qsort(l, n, sizeof(hitable *), box_z_compare);
96+
if (n == 1) {
97+
left = right = l[0];
98+
}
99+
else if (n == 2) {
100+
left = l[0];
101+
right = l[1];
102+
}
103+
else {
104+
left = new bvh_node(l, n/2, time0, time1);
105+
right = new bvh_node(l + n/2, n - n/2, time0, time1);
106+
}
107+
aabb box_left, box_right;
108+
if(!left->bounding_box(time0,time1, box_left) || !right->bounding_box(time0,time1, box_right))
109+
std::cerr << "no bounding box in bvh_node constructor\n";
110+
box = surrounding_box(box_left, box_right);
111+
}
112+
113+
#endif
114+

camera.h

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#ifndef CAMERAH
2+
#define CAMERAH
3+
#include "ray.h"
4+
5+
vec3 random_in_unit_disk() {
6+
vec3 p;
7+
do {
8+
p = 2.0*vec3(drand48(),drand48(),0) - vec3(1,1,0);
9+
} while (dot(p,p) >= 1.0);
10+
return p;
11+
}
12+
13+
class camera {
14+
public:
15+
// new: add t0 and t1
16+
camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist, float t0, float t1) { // vfov is top to bottom in degrees
17+
time0 = t0;
18+
time1 = t1;
19+
lens_radius = aperture / 2;
20+
float theta = vfov*M_PI/180;
21+
float half_height = tan(theta/2);
22+
float half_width = aspect * half_height;
23+
origin = lookfrom;
24+
w = unit_vector(lookfrom - lookat);
25+
u = unit_vector(cross(vup, w));
26+
v = cross(w, u);
27+
lower_left_corner = origin - half_width*focus_dist*u -half_height*focus_dist*v - focus_dist*w;
28+
horizontal = 2*half_width*focus_dist*u;
29+
vertical = 2*half_height*focus_dist*v;
30+
}
31+
32+
// new: add time to construct ray
33+
ray get_ray(float s, float t) {
34+
vec3 rd = lens_radius*random_in_unit_disk();
35+
vec3 offset = u * rd.x() + v * rd.y();
36+
float time = time0 + drand48()*(time1-time0);
37+
return ray(origin + offset, lower_left_corner + s*horizontal + t*vertical - origin - offset, time);
38+
}
39+
40+
vec3 origin;
41+
vec3 lower_left_corner;
42+
vec3 horizontal;
43+
vec3 vertical;
44+
vec3 u, v, w;
45+
float time0, time1; // new variables for shutter open/close times
46+
float lens_radius;
47+
};
48+
#endif
49+
50+
51+
52+

0 commit comments

Comments
 (0)