|
176 | 176 | ----------------------
|
177 | 177 | Now to create a moving object. I’ll update the sphere class so that its center moves linearly from
|
178 | 178 | `center1` at time=0 to `center2` at time=1. (It continues on indefinitely outside that time
|
179 |
| -interval, so it really can be sampled at any time.) |
| 179 | +interval, so it really can be sampled at any time.) We'll do this by replacing the 3D center point |
| 180 | +with a 3D ray that describes the original position at time=0 and the displacement to the end |
| 181 | +position at time=1. |
180 | 182 |
|
181 | 183 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
182 | 184 | class sphere : public hittable {
|
183 | 185 | public:
|
184 | 186 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
185 | 187 | // Stationary Sphere
|
186 |
| - sphere(const point3& center, double radius, shared_ptr<material> mat) |
187 |
| - : center1(center), radius(std::fmax(0,radius)), mat(mat), is_moving(false) {} |
| 188 | + sphere(const point3& static_center, double radius, shared_ptr<material> mat) |
| 189 | + : center(static_center, vec3(0,0,0)), radius(std::fmax(0,radius)), mat(mat) {} |
188 | 190 |
|
189 | 191 | // Moving Sphere
|
190 | 192 | sphere(const point3& center1, const point3& center2, double radius,
|
191 | 193 | shared_ptr<material> mat)
|
192 |
| - : center1(center1), radius(std::fmax(0,radius)), mat(mat), is_moving(true) |
193 |
| - { |
194 |
| - center_vec = center2 - center1; |
195 |
| - } |
| 194 | + : center(center1, center2 - center1), radius(std::fmax(0,radius)), mat(mat) {} |
196 | 195 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
197 | 196 |
|
198 | 197 | ...
|
199 | 198 |
|
200 | 199 | private:
|
201 | 200 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
202 |
| - point3 center1; |
| 201 | + ray center; |
203 | 202 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
204 | 203 | double radius;
|
205 | 204 | shared_ptr<material> mat;
|
206 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
207 |
| - bool is_moving; |
208 |
| - vec3 center_vec; |
209 | 205 |
|
210 |
| - point3 sphere_center(double time) const { |
211 |
| - // Linearly interpolate from center1 to center2 according to time, where t=0 yields |
212 |
| - // center1, and t=1 yields center2. |
213 |
| - return center1 + time*center_vec; |
214 |
| - } |
215 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
216 | 206 | };
|
217 |
| - |
218 | 207 | #endif
|
219 | 208 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
220 | 209 | [Listing [moving-sphere]: <kbd>[sphere.h]</kbd> A moving sphere]
|
221 | 210 |
|
222 |
| -An alternative to making special stationary spheres is to just make them all move, but stationary |
223 |
| -spheres have the same begin and end position. I’m on the fence about that trade-off between simpler |
224 |
| -code and more efficient stationary spheres, so let your design taste guide you. |
225 |
| - |
226 | 211 | <div class='together'>
|
227 | 212 | The updated `sphere::hit()` function is almost identical to the old `sphere::hit()` function:
|
228 |
| -`center` just needs to query a function `sphere_center(time)`: |
| 213 | +we just need to now determine the current position of the animated center: |
229 | 214 |
|
230 | 215 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
231 | 216 | class sphere : public hittable {
|
232 | 217 | public:
|
233 | 218 | ...
|
234 | 219 | bool hit(const ray& r, interval ray_t, hit_record& rec) const override {
|
235 | 220 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
236 |
| - point3 center = is_moving ? sphere_center(r.time()) : center1; |
| 221 | + point3 current_center = center.at(r.time()); |
| 222 | + vec3 oc = current_center - r.origin(); |
237 | 223 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
238 |
| - vec3 oc = center - r.origin(); |
239 | 224 | auto a = r.direction().length_squared();
|
240 | 225 | auto h = dot(r.direction(), oc);
|
241 | 226 | auto c = oc.length_squared() - radius*radius;
|
| 227 | + |
242 | 228 | ...
|
| 229 | + |
| 230 | + rec.t = root; |
| 231 | + rec.p = r.at(rec.t); |
| 232 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 233 | + vec3 outward_normal = (rec.p - current_center) / radius; |
| 234 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 235 | + rec.set_face_normal(r, outward_normal); |
| 236 | + get_sphere_uv(outward_normal, rec.u, rec.v); |
| 237 | + rec.mat = mat; |
| 238 | + |
| 239 | + return true; |
243 | 240 | }
|
244 | 241 | ...
|
245 | 242 | };
|
|
711 | 708 | class sphere : public hittable {
|
712 | 709 | public:
|
713 | 710 | // Stationary Sphere
|
714 |
| - sphere(const point3& center, double radius, shared_ptr<material> mat) |
| 711 | + sphere(const point3& static_center, double radius, shared_ptr<material> mat) |
715 | 712 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
716 |
| - : center1(center), radius(std::fmax(0,radius)), mat(mat), is_moving(false) |
| 713 | + : center(static_center, vec3(0,0,0)), radius(std::fmax(0,radius)), mat(mat) |
717 | 714 | {
|
718 | 715 | auto rvec = vec3(radius, radius, radius);
|
719 |
| - bbox = aabb(center1 - rvec, center1 + rvec); |
| 716 | + bbox = aabb(static_center - rvec, static_center + rvec); |
720 | 717 | }
|
721 | 718 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
722 | 719 |
|
|
728 | 725 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
729 | 726 |
|
730 | 727 | private:
|
731 |
| - point3 center1; |
| 728 | + ray center; |
732 | 729 | double radius;
|
733 | 730 | shared_ptr<material> mat;
|
734 |
| - bool is_moving; |
735 |
| - vec3 center_vec; |
736 | 731 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
737 | 732 | aabb bbox;
|
738 | 733 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
|
754 | 749 | // Moving Sphere
|
755 | 750 | sphere(const point3& center1, const point3& center2, double radius,
|
756 | 751 | shared_ptr<material> mat)
|
757 |
| - : center1(center1), radius(std::fmax(0,radius)), mat(mat), is_moving(true) |
758 |
| - { |
759 | 752 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
| 753 | + : center(center1, center2 - center1), radius(std::fmax(0,radius)), mat(mat) |
| 754 | + { |
760 | 755 | auto rvec = vec3(radius, radius, radius);
|
761 |
| - aabb box1(center1 - rvec, center1 + rvec); |
762 |
| - aabb box2(center2 - rvec, center2 + rvec); |
| 756 | + aabb box1(center.at(0) - rvec, center.at(0) + rvec); |
| 757 | + aabb box2(center.at(1) - rvec, center.at(1) + rvec); |
763 | 758 | bbox = aabb(box1, box2);
|
764 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
765 |
| - |
766 |
| - center_vec = _center2 - _center1; |
767 | 759 | }
|
| 760 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
768 | 761 |
|
769 | 762 | ...
|
770 | 763 | };
|
|
1649 | 1642 |
|
1650 | 1643 | rec.t = root;
|
1651 | 1644 | rec.p = r.at(rec.t);
|
1652 |
| - vec3 outward_normal = (rec.p - center) / radius; |
| 1645 | + vec3 outward_normal = (rec.p - current_center) / radius; |
1653 | 1646 | rec.set_face_normal(r, outward_normal);
|
1654 | 1647 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight
|
1655 | 1648 | get_sphere_uv(outward_normal, rec.u, rec.v);
|
|
0 commit comments