|
2601 | 2601 |
|
2602 | 2602 | $$ \mathbf{P} = \mathbf{Q} + \alpha \mathbf{u} + \beta \mathbf{v} $$
|
2603 | 2603 |
|
2604 |
| -If $\mathbf{u}$ and $\mathbf{v}$ were guaranteed to be orthogonal to each other (forming a 90° angle |
2605 |
| -between them), then this would be a simple matter of using the dot product to project $\mathbf{P}$ |
2606 |
| -onto each of the basis vectors $\mathbf{u}$ and $\mathbf{v}$. However, since we are not restricting |
| 2604 | +Pulling a rabbit out of my hat, the planar coordinates $\alpha$ and $\beta$ are given by the |
| 2605 | +following equations: |
| 2606 | + |
| 2607 | + $$ \alpha = \mathbf{w} \cdot (\mathbf{p} \times \mathbf{v}) $$ |
| 2608 | + $$ \beta = \mathbf{w} \cdot (\mathbf{u} \times \mathbf{p}) $$ |
| 2609 | + |
| 2610 | +where |
| 2611 | + |
| 2612 | + $$ \mathbf{w} = \frac{\mathbf{n}}{\mathbf{n} \cdot (\mathbf{u} \times \mathbf{v})} |
| 2613 | + = \frac{\mathbf{n}}{\mathbf{n} \cdot \mathbf{n}}$$ |
| 2614 | + |
| 2615 | +The vector $\mathbf{w}$ is constant for a given quadrilateral, so we'll cache that value. |
| 2616 | + |
| 2617 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2618 | + class quad : public hittable { |
| 2619 | + public: |
| 2620 | + quad(const point3& _Q, const vec3& _u, const vec3& _v, shared_ptr<material> m) |
| 2621 | + : Q(_Q), u(_u), v(_v), mat(m) |
| 2622 | + { |
| 2623 | + auto n = cross(u, v); |
| 2624 | + normal = unit_vector(n); |
| 2625 | + D = dot(normal, Q); |
| 2626 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2627 | + w = n / dot(n,n); |
| 2628 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2629 | + |
| 2630 | + set_bounding_box(); |
| 2631 | + } |
| 2632 | + ... |
| 2633 | + |
| 2634 | + private: |
| 2635 | + point3 Q; |
| 2636 | + vec3 u, v; |
| 2637 | + shared_ptr<material> mat; |
| 2638 | + aabb bbox; |
| 2639 | + vec3 normal; |
| 2640 | + double D; |
| 2641 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
| 2642 | + vec3 w; |
| 2643 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
| 2644 | + }; |
| 2645 | + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 2646 | + [Listing [quad-w]: <kbd>[quad.h]</kbd> Caching the quadrilateral's w value] |
| 2647 | + |
| 2648 | + |
| 2649 | +Deriving the Planar Coordinates |
| 2650 | +-------------------------------- |
| 2651 | + |
| 2652 | +(This section covers the derivation of the equations above. Feel free to skip to the next section if |
| 2653 | +you're not interested.) |
| 2654 | + |
| 2655 | +Refer back to figure [ray-plane]. If the planar basis vectors $\mathbf{u}$ and $\mathbf{v}$ were |
| 2656 | +guaranteed to be orthogonal to each other (forming a 90° angle between them), then solving for |
| 2657 | +$\alpha$ and $\beta$ would be a simple matter of using the dot product to project $\mathbf{P}$ onto |
| 2658 | +each of the basis vectors $\mathbf{u}$ and $\mathbf{v}$. However, since we are not restricting |
2607 | 2659 | $\mathbf{u}$ and $\mathbf{v}$ to be orthogonal, the math's a little bit trickier.
|
2608 | 2660 |
|
| 2661 | +To set things up, consider that |
| 2662 | + |
2609 | 2663 | $$ \mathbf{P} = \mathbf{Q} + \alpha \mathbf{u} + \beta \mathbf{v}$$
|
2610 | 2664 |
|
2611 | 2665 | $$ \mathbf{p} = \mathbf{P} - \mathbf{Q} = \alpha \mathbf{u} + \beta \mathbf{v} $$
|
2612 | 2666 |
|
2613 | 2667 | Here, $\mathbf{P}$ is the _point_ of intersection, and $\mathbf{p}$ is the _vector_ from
|
2614 | 2668 | $\mathbf{Q}$ to $\mathbf{P}$.
|
2615 | 2669 |
|
2616 |
| -Cross the above equation with $\mathbf{u}$ and $\mathbf{v}$, respectively: |
| 2670 | +Cross the equation for $\mathbf{p}$ with $\mathbf{u}$ and $\mathbf{v}$, respectively: |
2617 | 2671 |
|
2618 | 2672 | $$ \begin{align*}
|
2619 | 2673 | \mathbf{u} \times \mathbf{p} &= \mathbf{u} \times (\alpha \mathbf{u} + \beta \mathbf{v}) \\
|
|
2671 | 2725 | $$ \alpha = \mathbf{w} \cdot (\mathbf{p} \times \mathbf{v}) $$
|
2672 | 2726 | $$ \beta = \mathbf{w} \cdot (\mathbf{u} \times \mathbf{p}) $$
|
2673 | 2727 |
|
2674 |
| -The vector $\mathbf{w}$ is constant for a given quadrilateral, so we'll cache that value. |
2675 |
| - |
2676 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2677 |
| - class quad : public hittable { |
2678 |
| - public: |
2679 |
| - quad(const point3& _Q, const vec3& _u, const vec3& _v, shared_ptr<material> m) |
2680 |
| - : Q(_Q), u(_u), v(_v), mat(m) |
2681 |
| - { |
2682 |
| - auto n = cross(u, v); |
2683 |
| - normal = unit_vector(n); |
2684 |
| - D = dot(normal, Q); |
2685 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
2686 |
| - w = n / dot(n,n); |
2687 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2688 |
| - |
2689 |
| - set_bounding_box(); |
2690 |
| - } |
2691 |
| - ... |
2692 |
| - |
2693 |
| - private: |
2694 |
| - point3 Q; |
2695 |
| - vec3 u, v; |
2696 |
| - shared_ptr<material> mat; |
2697 |
| - aabb bbox; |
2698 |
| - vec3 normal; |
2699 |
| - double D; |
2700 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ highlight |
2701 |
| - vec3 w; |
2702 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ C++ |
2703 |
| - }; |
2704 |
| - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
2705 |
| - [Listing [quad-w]: <kbd>[quad.h]</kbd> Caching the quadrilateral's w value] |
2706 |
| - |
2707 | 2728 |
|
2708 | 2729 | Interior Testing of The Intersection Using UV Coordinates
|
2709 | 2730 | ----------------------------------------------------------
|
|
2726 | 2747 |
|
2727 | 2748 | That's the last piece needed to implement quadrilateral primitives.
|
2728 | 2749 |
|
2729 |
| -Pause a bit here and consider that if you use the $(\alpha,\beta)$ coordinates to determine if a |
2730 |
| -point lies inside a quadrilateral (parallelogram), it's not too hard to imagine using these same 2D |
2731 |
| -coordinates to determine if the intersection point lies inside _any_ other 2D (planar) primitive! |
2732 |
| - |
2733 |
| -We'll leave these additional 2D shape possibilities as an exercise to the reader, depending on your |
2734 |
| -desire to explore. Consider triangles, disks, and rings (all of these are surprisingly easy). You |
2735 |
| -could even create cut-out stencils based on the pixels of a texture map, or a Mandelbrot shape! |
2736 |
| - |
2737 | 2750 | In order to make such experimentation a bit easier, we'll factor out the $(\alpha,\beta)$ interior
|
2738 | 2751 | test method from the hit method.
|
2739 | 2752 |
|
|
2866 | 2879 | 
|
2867 | 2880 |
|
2868 | 2881 |
|
| 2882 | +Additional 2D Primitives |
| 2883 | +------------------------- |
| 2884 | +Pause a bit here and consider that if you use the $(\alpha,\beta)$ coordinates to determine if a |
| 2885 | +point lies inside a quadrilateral (parallelogram), it's not too hard to imagine using these same 2D |
| 2886 | +coordinates to determine if the intersection point lies inside _any_ other 2D (planar) primitive! |
| 2887 | + |
| 2888 | +For example, suppose we change the `is_interior()` function to return true if `sqrt(a*a + b*b) < r`. |
| 2889 | +This would then implement disk primitives of radius `r`. For triangles, try |
| 2890 | +`a > 0 && b > 0 && a + b < 1`. |
| 2891 | + |
| 2892 | +We'll leave additional 2D shape possibilities as an exercise to the reader, depending on your desire |
| 2893 | +to explore. You could even create cut-out stencils based on the pixels of a texture map, or a |
| 2894 | +Mandelbrot shape! As a little Easter egg, check out the `alternate-2D-primitves` tag in the source |
| 2895 | +repository. This has solutions for triangles, ellipses and annuli (rings) in |
| 2896 | +`src/TheNextWeek/quad.h` |
| 2897 | + |
| 2898 | + |
2869 | 2899 |
|
2870 | 2900 | Lights
|
2871 | 2901 | ====================================================================================================
|
|
0 commit comments