Tracking Intersections

Currently, your intersect function returns a set of t values, but imagine for a moment a beautifully complex scene, full of spheres, cubes, cylinders, cones and dozens of creative combinations. You cast your ray into that scene and get back a double handful of intersections. You now know where the intersections occurred (thanks to the t values), but you have no idea how to draw them. What object was intersected at that point? What color is it? What are its material properties? Should there be a reflection or not? You just don’t know.

With the addition of one more property, you’ll have the foundation of what you need to answer those questions. You’re going to create a new data structure, called an intersection, which will (for now) aggregate two things:

  1. The t value of the intersection, and
  2. The object that was intersected.

You’ll add additional properties in later chapters, but these will suffice for now. Go ahead and add the following test to show both how to create an intersection and how its properties are accessed.

 Scenario​: An intersection encapsulates t and object
 Given​ s ← sphere()
 When​ i ← intersection(3.5, s)
 Then​ i.t = 3.5
 And​ i.object = s

You’ll also need a way to aggregate these intersection objects so you can work with multiple intersections at once. (Consider your sphere intersection routine, which can return zero, one, or two intersections.) Write the following test, which introduces a new function called intersections(i1, i2, ...). This should return a new collection of the given intersection objects.

 Scenario​: Aggregating intersections
 Given​ s ← sphere()
 And​ i1 ← intersection(1, s)
 And​ i2 ← intersection(2, s)
 When​ xs ← intersections(i1, i2)
 Then​ xs.count = 2
 And​ xs[0].t = 1
 And​ xs[1].t = 2

This list of intersections could just be an array primitive in your implementation language, but note that you’ll be adding a function shortly (in Identifying Hits) that operates on these lists of intersections.

Now it’s time to break some code! Modify your existing tests so that they assume your intersect function returns a list of these intersection records, instead of bare t values. Also, add the following test, which will show that the object property is being set by intersect.

 Scenario​: Intersect sets the object on the intersection
 Given​ r ← ray(point(0, 0, -5), vector(0, 0, 1))
 And​ s ← sphere()
 When​ xs ← intersect(s, r)
 Then​ xs.count = 2
 And​ xs[0].object = s
 And​ xs[1].object = s

Make your tests pass again by modifying your intersect function so it creates a record for each intersection, instead of returning the t values directly. All you need now is to be able to decide which of all those intersections you actually care about, which introduces the hit.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.144.197