6.4 Disks
The disk is an interesting quadric since it has a particularly straightforward intersection routine that avoids solving the quadratic equation. In pbrt, a Disk is a circular disk of radius at height along the axis.
To describe partial disks, the user may specify a maximum value beyond which the disk is cut off (Figure 6.9). The disk can also be generalized to an annulus by specifying an inner radius, . In parametric form, it is described by
Figure 6.10 is a rendered image of two disks.
The Disk constructor directly initializes its various member variables from the values passed to it. We have omitted it here because it is trivial.
6.4.1 Area and Bounding
Disks have easily computed surface area, since they are just portions of an annulus:
The bounding method is also quite straightforward; it computes a bounding box centered at the height of the disk along , with extent of radius in both the and directions.
A disk has a single surface normal.
6.4.2 Intersection Tests
The Disk intersection test methods follow the same form as the earlier quadrics. We omit Intersect(), as it is exactly the same as Sphere::Intersect() and Cylinder::Intersect(), with calls to BasicIntersect() and then InteractionFromIntersection().
The basic intersection test for a ray with a disk is easy. The intersection of the ray with the plane that the disk lies in is found and then the intersection point is checked to see if it lies inside the disk.
The first step is to compute the parametric value where the ray intersects the plane that the disk lies in. We want to find such that the component of the ray’s position is equal to the height of the disk. Thus,
and so
The intersection method computes a value and checks to see if it is inside the range of values . If not, the routine can report that there is no intersection.
If the ray is parallel to the disk’s plane (i.e., the component of its direction is zero), no intersection is reported. The case where a ray is both parallel to the disk’s plane and lies within the plane is somewhat ambiguous, but it is most reasonable to define intersecting a disk edge-on as “no intersection.” This case must be handled explicitly so that not-a-number floating-point values are not generated by the following code.
Now the intersection method can compute the point pHit where the ray intersects the plane. Once the plane intersection is known, an invalid intersection is returned if the distance from the hit to the center of the disk is more than Disk::radius or less than Disk::innerRadius. This check can be optimized by computing the squared distance to the center, taking advantage of the fact that the and coordinates of the center point are zero, and the coordinate of pHit is equal to height.
If the distance check passes, a final test makes sure that the value of the hit point is between zero and , specified by the caller. Inverting the disk’s parameterization gives the same expression for as the other quadric shapes. Because a ray can only intersect a disk once, there is no need to consider a second intersection if this test fails, as was the case with the two earlier quadrics.
Finding the SurfaceInteraction corresponding to a disk intersection follows the same process of inverting the parametric representation we have seen before.
The parameter u is first scaled to reflect the partial disk specified by , and v is computed by inverting the parametric equation. The equations for the partial derivatives at the hit point can be derived with a process similar to that used for the previous quadrics. Because the normal of a disk is the same everywhere, the partial derivatives and are both trivially .
As usual, the implementation of IntersectP() is straightforward.
6.4.3 Sampling
The Disk area sampling method uses a utility routine, SampleUniformDiskConcentric(), that uniformly samples a unit disk. (It is defined in Section A.5.1.) The point that it returns is then scaled by the radius and offset in so that it lies on the disk of a given radius and height. Note that our implementation here does not account for partial disks due to Disk::innerRadius being nonzero or Disk::phiMax being less than . Fixing this bug is left for an exercise at the end of the chapter.
The same computation as in the Intersect() method gives the parametric for the sampled point.
We do not provide a specialized solid angle sampling method for disks, but follow the same approach that we did for cylinders, sampling uniformly by area and then computing the probability density to be with respect to solid angle. The implementations of those methods are not included here, as they are the same as they were for cylinders.