Skip to content

Commit

Permalink
Refactor aabb to use intervals
Browse files Browse the repository at this point in the history
- Fixed some missing interval code in the books
- Added interval::operator+=, aabb::operator+=
- Reordered interval constructors from simplest to most complex

Resolves #796
  • Loading branch information
hollasch committed Dec 8, 2020
1 parent fb066d0 commit 272499b
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 80 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Change Log -- Ray Tracing in One Weekend
some global utility functions as either private static, or in better locations.
- Fix: Remove redundant `virtual` keyword for methods with `override` (#805)
- Change: `aabb` class constructor treats two params as extreme points in any orientation (#733)
- Change: `aabb` class uses intervals for each axis (#796)

### In One Weekend
- Added: More commentary about the choice between `double` and `float` (#752)
Expand Down
14 changes: 8 additions & 6 deletions books/RayTracingInOneWeekend.html
Original file line number Diff line number Diff line change
Expand Up @@ -1292,24 +1292,26 @@

class interval {
public:
double min, max;
interval() : min(+infinity), max(-infinity) {} // Default interval is empty

interval(double _min, double _max) : min(_min), max(_max) {}
interval() : min(+infinity), max(-infinity) {} // Default interval is empty

bool contains(double x) const {
return min <= x && x <= max;
}

public:
double min, max;
};

const static interval empty (+infinity, -infinity);
const static interval universe(-infinity, +infinity);


#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [interval-initial]: <kbd>[interval.h]</kbd> Introducing the new interval class]


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class hittable {
public:
Expand All @@ -1321,7 +1323,6 @@
[Listing [hittable-with-interval]: <kbd>[hittable.h]</kbd> hittable::hit() using interval]



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class hittable_list : public hittable {
...
Expand Down Expand Up @@ -1358,7 +1359,6 @@
hittable_list::hit() using interval]



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class sphere : public hittable {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
Expand Down Expand Up @@ -1390,7 +1390,6 @@
[Listing [sphere-with-interval]: <kbd>[sphere.h]</kbd> sphere using interval]



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
...
color ray_color(const ray& r, const hittable& world) {
Expand All @@ -1405,6 +1404,7 @@
[Listing [main-with-interval]: <kbd>[main.cc]</kbd> The new main using interval]



Antialiasing
====================================================================================================

Expand Down Expand Up @@ -1520,12 +1520,14 @@

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class interval {
public:
...
double clamp(double x) const {
if (x < min) return min;
if (x > max) return max;
return x;
}
...
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [clamp]: <kbd>[interval.h]</kbd> The interval::clamp() utility function]
Expand Down
110 changes: 77 additions & 33 deletions books/RayTracingTheNextWeek.html
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,20 @@
[Listing [moving-sphere-hit]: <kbd>[moving_sphere.h]</kbd> Moving sphere hit function]
</div>

We need to implement the `interval::contains()` method mentioned above:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class interval {
public:
...
bool contains(double x) const {
return min <= x && x <= max;
}
...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [interval-contains]: <kbd>interval.h</kbd> interval::contains() method]


Tracking the Time of Ray Intersection
--------------------------------------
Expand Down Expand Up @@ -614,30 +628,33 @@
aabb(const point3& a, const point3& b) {
// Treat the two points a and b as extrema for the bounding box, so we don't require a
// particular minimum/maximum coordinate order.
minimum = point3(fmin(a[0],b[0]), fmin(a[1],b[1]), fmin(a[2],b[2]));
maximum = point3(fmax(a[0],b[0]), fmax(a[1],b[1]), fmax(a[2],b[2]));
x = interval(fmin(a[0],b[0]), fmax(a[0],b[0]));
y = interval(fmin(a[1],b[1]), fmax(a[1],b[1]));
z = interval(fmin(a[2],b[2]), fmax(a[2],b[2]));
}

point3 min() const { return minimum; }
point3 max() const { return maximum; }

bool hit(const ray& r, interval ray_t) const {
for (int a = 0; a < 3; a++) {
auto t0 = fmin((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
auto t1 = fmax((minimum[a] - r.origin()[a]) / r.direction()[a],
(maximum[a] - r.origin()[a]) / r.direction()[a]);
auto ray_tmin = fmax(t0, ray_t.min);
auto ray_tmax = fmin(t1, ray_t.max);
if (ray_tmax <= ray_tmin)
auto t0 = fmin((axis(a).min - r.origin()[a]) / r.direction()[a],
(axis(a).max - r.origin()[a]) / r.direction()[a]);
auto t1 = fmax((axis(a).min - r.origin()[a]) / r.direction()[a],
(axis(a).max - r.origin()[a]) / r.direction()[a]);
ray_t.min = fmax(t0, ray_t.min);
ray_t.max = fmin(t1, ray_t.max);
if (ray_t.max <= ray_t.min)
return false;
}
return true;
}

const interval& axis(int n) const {
if (n == 1) return y;
if (n == 2) return z;
return x;
}

public:
point3 minimum;
point3 maximum;
interval x, y, z;
};

#endif
Expand Down Expand Up @@ -671,6 +688,8 @@
}
return true;
}
...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [aabb-hit]: <kbd>[aabb.h]</kbd> Axis-aligned bounding box hit function]
</div>
Expand Down Expand Up @@ -829,19 +848,13 @@
class aabb {
public:
...
aabb(aabb box0, aabb box1) {
minimum = {
fmin(box0.min().x(), box1.min().x()),
fmin(box0.min().y(), box1.min().y()),
fmin(box0.min().z(), box1.min().z())
};

maximum = {
fmax(box0.max().x(), box1.max().x()),
fmax(box0.max().y(), box1.max().y()),
fmax(box0.max().z(), box1.max().z())
};
aabb(const aabb& box0, const aabb& box1) {
x = interval(box0.x, box1.x);
y = interval(box0.y, box1.y);
z = interval(box0.z, box1.z);
}
...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [box-of-boxes]: <kbd>[aabb.h]</kbd> aabb from two boxes]
</div>
Expand Down Expand Up @@ -1024,7 +1037,7 @@
if (!a->bounding_box(0,0, box_a) || !b->bounding_box(0,0, box_b))
std::cerr << "No bounding box in bvh_node constructor.\n";

return box_a.min().e[axis] < box_b.min().e[axis];
return box_a.axis(axis).min < box_b.axis(axis).min;
}


Expand Down Expand Up @@ -2778,16 +2791,47 @@
if (!ptr->bounding_box(time_start, time_end, output_box))
return false;

output_box = aabb(
output_box.min() + offset,
output_box.max() + offset);
output_box += offset;

return true;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [translate-class]: <kbd>[hittable.h]</kbd> Hittable translation class]
</div>

The line `output_box += offset` in the `bounding_box()` method above requires some additional
support.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class aabb {
public:
...
aabb& operator+=(vec3 offset) {
x += offset.x();
y += offset.y();
z += offset.z();
return *this;
}
...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [aabb-plus-eq]: <kbd>[aabb.h]</kbd> The aabb::operator+= method]


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
class interval {
public:
...
interval& operator+=(double offset) {
min += offset;
max += offset;
return *this;
}
...
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[Listing [interval-plus-eq]: <kbd>[interval.h]</kbd> The interval::operator+= method]


Instance Rotation
------------------
Expand Down Expand Up @@ -2874,9 +2918,9 @@
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
auto x = i*bbox.max().x() + (1-i)*bbox.min().x();
auto y = j*bbox.max().y() + (1-j)*bbox.min().y();
auto z = k*bbox.max().z() + (1-k)*bbox.min().z();
auto x = i*bbox.x.max + (1-i)*bbox.x.min;
auto y = j*bbox.y.max + (1-j)*bbox.y.min;
auto z = k*bbox.z.max + (1-k)*bbox.z.min;

auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
Expand Down
2 changes: 1 addition & 1 deletion src/TheNextWeek/bvh.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ inline bool box_compare(const shared_ptr<hittable> a, const shared_ptr<hittable>
if (!a->bounding_box(0,0, box_a) || !b->bounding_box(0,0, box_b))
std::cerr << "No bounding box in bvh_node constructor.\n";

return box_a.min().e[axis] < box_b.min().e[axis];
return box_a.axis(axis).min < box_b.axis(axis).min;
}


Expand Down
10 changes: 4 additions & 6 deletions src/TheNextWeek/hittable.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,7 @@ bool translate::bounding_box(double time_start, double time_end, aabb& output_bo
if (!ptr->bounding_box(time_start, time_end, output_box))
return false;

output_box = aabb(
output_box.min() + offset,
output_box.max() + offset);
output_box += offset;

return true;
}
Expand Down Expand Up @@ -114,9 +112,9 @@ rotate_y::rotate_y(shared_ptr<hittable> p, double angle) : ptr(p) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
auto x = i*bbox.max().x() + (1-i)*bbox.min().x();
auto y = j*bbox.max().y() + (1-j)*bbox.min().y();
auto z = k*bbox.max().z() + (1-k)*bbox.min().z();
auto x = i*bbox.x.max + (1-i)*bbox.x.min;
auto y = j*bbox.y.max + (1-j)*bbox.y.min;
auto z = k*bbox.z.max + (1-k)*bbox.z.min;

auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
Expand Down
2 changes: 1 addition & 1 deletion src/TheRestOfYourLife/bvh.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ inline bool box_compare(const shared_ptr<hittable> a, const shared_ptr<hittable>
if (!a->bounding_box(0,0, box_a) || !b->bounding_box(0,0, box_b))
std::cerr << "No bounding box in bvh_node constructor.\n";

return box_a.min().e[axis] < box_b.min().e[axis];
return box_a.axis(axis).min < box_b.axis(axis).min;
}


Expand Down
10 changes: 4 additions & 6 deletions src/TheRestOfYourLife/hittable.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,7 @@ bool translate::bounding_box(double time_start, double time_end, aabb& output_bo
if (!ptr->bounding_box(time_start, time_end, output_box))
return false;

output_box = aabb(
output_box.min() + offset,
output_box.max() + offset);
output_box += offset;

return true;
}
Expand Down Expand Up @@ -144,9 +142,9 @@ rotate_y::rotate_y(shared_ptr<hittable> p, double angle) : ptr(p) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
auto x = i*bbox.max().x() + (1-i)*bbox.min().x();
auto y = j*bbox.max().y() + (1-j)*bbox.min().y();
auto z = k*bbox.max().z() + (1-k)*bbox.min().z();
auto x = i*bbox.x.max + (1-i)*bbox.x.min;
auto y = j*bbox.y.max + (1-j)*bbox.y.min;
auto z = k*bbox.z.max + (1-k)*bbox.z.min;

auto newx = cos_theta*x + sin_theta*z;
auto newz = -sin_theta*x + cos_theta*z;
Expand Down
Loading

0 comments on commit 272499b

Please sign in to comment.