|
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