|
163 | 163 |
|
164 | 164 | Adding Moving Spheres
|
165 | 165 | ----------------------
|
166 |
| -Now to create a moving object. |
167 |
| -I’ll update the sphere class so that its center moves linearly from `center1` at time=0 to `center2` |
168 |
| -at time=1. |
169 |
| -(It continues on indefinitely outside that time interval, so it really can be sampled at any time.) |
| 166 | +Now to create a moving object. I’ll update the sphere class so that its center moves linearly from |
| 167 | +`center1` at time=0 to `center2` at time=1. (It continues on indefinitely outside that time |
| 168 | +interval, so it really can be sampled at any time.) |
170 | 169 |
|
171 | 170 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
172 | 171 | class sphere : public hittable {
|
|
508 | 507 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
509 | 508 |
|
510 | 509 | <div class='together'>
|
511 |
| -That is awesomely simple, and the fact that the 3D version also works is why people love the |
512 |
| -slab method: |
| 510 | +That is awesomely simple, and the fact that the 3D version also works is why people love the slab |
| 511 | +method: |
513 | 512 |
|
514 | 513 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
515 | 514 | compute (tx0, tx1)
|
|
764 | 763 | [Listing [moving-sphere-bbox]: <kbd>[sphere.h]</kbd> Moving sphere with bounding box]
|
765 | 764 |
|
766 | 765 | <div class='together'>
|
767 |
| -Now we need a new `aabb` constructor that takes two boxes as input. |
768 |
| -First, we'll add a new interval constructor that takes two intervals as input: |
| 766 | +Now we need a new `aabb` constructor that takes two boxes as input. First, we'll add a new interval |
| 767 | +constructor that takes two intervals as input: |
769 | 768 |
|
770 | 769 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
771 | 770 | class interval {
|
|
910 | 909 | 2. sort the primitives (`using std::sort`)
|
911 | 910 | 3. put half in each subtree
|
912 | 911 |
|
913 |
| - |
914 | 912 | When the list coming in is two elements, I put one in each subtree and end the recursion. The
|
915 | 913 | traversal algorithm should be smooth and not have to check for null pointers, so if I just have one
|
916 | 914 | element I duplicate it in each subtree. Checking explicitly for three elements and just following
|
|
1142 | 1140 | To accomplish the checkered pattern, we'll first compute the floor of each component of the input
|
1143 | 1141 | point. We could truncate the coordinates, but that would pull values toward zero, which would give
|
1144 | 1142 | us the same color on both sides of zero. The floor function will always shift values to the integer
|
1145 |
| -value on the left (toward negative infinity). Given these three integer results |
1146 |
| -($\lfloor x \rfloor, \lfloor y \rfloor, \lfloor z \rfloor$) we take their sum and compute the |
1147 |
| -result modulo two, which gives us either 0 or 1. Zero maps to the even color, and one to the odd |
1148 |
| -color. |
| 1143 | +value on the left (toward negative infinity). Given these three integer results ($\lfloor x \rfloor, |
| 1144 | +\lfloor y \rfloor, \lfloor z \rfloor$) we take their sum and compute the result modulo two, which |
| 1145 | +gives us either 0 or 1. Zero maps to the even color, and one to the odd color. |
1149 | 1146 |
|
1150 | 1147 | Finally, we add a scaling factor to the texture, to allow us to control the size of the checker
|
1151 | 1148 | pattern in the scene.
|
|
1486 | 1483 | </div>
|
1487 | 1484 |
|
1488 | 1485 | From the hitpoint $\mathbf{P}$, we compute the surface coordinates $(u,v)$. We then use these to
|
1489 |
| -index into our procedural solid texture (like marble). We can also read in an image and use the |
1490 |
| -2D $(u,v)$ texture coordinate to index into the image. |
| 1486 | +index into our procedural solid texture (like marble). We can also read in an image and use the 2D |
| 1487 | +$(u,v)$ texture coordinate to index into the image. |
1491 | 1488 |
|
1492 | 1489 | A direct way to use scaled $(u,v)$ in an image is to round the $u$ and $v$ to integers, and use that
|
1493 | 1490 | as $(i,j)$ pixels. This is awkward, because we don’t want to have to change the code when we change
|
|
2601 | 2598 |
|
2602 | 2599 | $$ \mathbf{P} = \mathbf{Q} + \alpha \mathbf{u} + \beta \mathbf{v} $$
|
2603 | 2600 |
|
2604 |
| -If $\mathbf{u}$ and $\mathbf{v}$ were guaranteed to be orthogonal to each other (forming a 90° |
2605 |
| -angle between them), then this would be a simple matter of using the dot product to project |
2606 |
| -$\mathbf{P}$ onto each of the basis vectors $\mathbf{u}$ and $\mathbf{v}$. However, since we are not |
2607 |
| -restricting $\mathbf{u}$ and $\mathbf{v}$ to be orthogonal, the math's a little bit trickier. |
| 2601 | +If $\mathbf{u}$ and $\mathbf{v}$ were guaranteed to be orthogonal to each other (forming a 90° angle |
| 2602 | +between them), then this would be a simple matter of using the dot product to project $\mathbf{P}$ |
| 2603 | +onto each of the basis vectors $\mathbf{u}$ and $\mathbf{v}$. However, since we are not restricting |
| 2604 | +$\mathbf{u}$ and $\mathbf{v}$ to be orthogonal, the math's a little bit trickier. |
2608 | 2605 |
|
2609 | 2606 | $$ \mathbf{P} = \mathbf{Q} + \alpha \mathbf{u} + \beta \mathbf{v}$$
|
2610 | 2607 |
|
|
2707 | 2704 |
|
2708 | 2705 | Interior Testing of The Intersection Using UV Coordinates
|
2709 | 2706 | ----------------------------------------------------------
|
2710 |
| -Now that we have the intersection point's planar coordinates $\alpha$ and $\beta$, we can easily |
2711 |
| -use these to determine if the intersection point is inside the quadrilateral -- that is, if the ray |
| 2707 | +Now that we have the intersection point's planar coordinates $\alpha$ and $\beta$, we can easily use |
| 2708 | +these to determine if the intersection point is inside the quadrilateral -- that is, if the ray |
2712 | 2709 | actually hit the quadrilateral.
|
2713 | 2710 |
|
2714 | 2711 | <div class='together'>
|
|
3284 | 3281 | </div>
|
3285 | 3282 |
|
3286 | 3283 | Now that we have boxes, we need to rotate them a bit to have them match the _real_ Cornell box. In
|
3287 |
| -ray tracing, this is usually done with an _instance_. An instance is a copy of a geometric |
3288 |
| -primitive that has been placed into the scene. This instance is entirely independent of the other |
3289 |
| -copies of the primitive and can be moved or rotated. In this case, our geometric primitive is our |
3290 |
| -hittable `box` object, and we want to rotate it. This is especially easy in ray tracing because we |
3291 |
| -don’t actually need to move objects in the scene; instead we move the rays in the opposite |
3292 |
| -direction. For example, consider a _translation_ (often called a _move_). We could take the pink box |
3293 |
| -at the origin and add two to all its x components, or (as we almost always do in ray tracing) leave |
3294 |
| -the box where it is, but in its hit routine subtract two off the x-component of the ray origin. |
| 3284 | +ray tracing, this is usually done with an _instance_. An instance is a copy of a geometric primitive |
| 3285 | +that has been placed into the scene. This instance is entirely independent of the other copies of |
| 3286 | +the primitive and can be moved or rotated. In this case, our geometric primitive is our hittable |
| 3287 | +`box` object, and we want to rotate it. This is especially easy in ray tracing because we don’t |
| 3288 | +actually need to move objects in the scene; instead we move the rays in the opposite direction. For |
| 3289 | +example, consider a _translation_ (often called a _move_). We could take the pink box at the origin |
| 3290 | +and add two to all its x components, or (as we almost always do in ray tracing) leave the box where |
| 3291 | +it is, but in its hit routine subtract two off the x-component of the ray origin. |
3295 | 3292 |
|
3296 | 3293 | ![Figure [ray-box]: Ray-box intersection with moved ray vs box](../images/fig-2.08-ray-box.jpg)
|
3297 | 3294 |
|
|
3377 | 3374 | </div>
|
3378 | 3375 |
|
3379 | 3376 | We also need to remember to offset the bounding box, otherwise the incident ray might be looking in
|
3380 |
| - the wrong place and trivially reject the intersection. |
3381 |
| -The expression `object->bounding_box() + offset` above requires some additional support. |
| 3377 | +the wrong place and trivially reject the intersection. The expression `object->bounding_box() + |
| 3378 | +offset` above requires some additional support. |
3382 | 3379 |
|
3383 | 3380 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++
|
3384 | 3381 | class aabb {
|
|
3460 | 3457 |
|
3461 | 3458 | The pseudocode for the `translate::hit` function above describes the function in terms of _moving_:
|
3462 | 3459 |
|
3463 |
| -1. Move the ray backwards by the offset |
3464 |
| -2. Determine whether an intersection exists along the offset ray (and if so, where) |
3465 |
| -3. Move the intersection point forwards by the offset |
| 3460 | + 1. Move the ray backwards by the offset |
| 3461 | + 2. Determine whether an intersection exists along the offset ray (and if so, where) |
| 3462 | + 3. Move the intersection point forwards by the offset |
3466 | 3463 |
|
3467 | 3464 | But this can also be thought of in terms of a _changing of coordinates_:
|
3468 | 3465 |
|
3469 |
| -1. Change the ray from world space to object space |
3470 |
| -2. Determine whether an intersection exists in object space (and if so, where) |
3471 |
| -3. Change the intersection point from object space to world space |
| 3466 | + 1. Change the ray from world space to object space |
| 3467 | + 2. Determine whether an intersection exists in object space (and if so, where) |
| 3468 | + 3. Change the intersection point from object space to world space |
3472 | 3469 |
|
3473 | 3470 | Rotating an object will not only change the point of intersection, but will also change the surface
|
3474 | 3471 | normal vector, which will change the direction of reflections and refractions. So we need to change
|
|
0 commit comments