Transforming Patterns

Right now, your stripes implementation has one small problem. If you’ve played around with it at all, you may have seen it: the stripes are completely fixed, frozen in place. It’s as if you were to shine a flashlight on your scene, with a stripe filter over the bulb. You’d find that every object that has a stripe pattern is covered with stripes of exactly the same size and orientation, regardless of how the objects themselves are arranged, as in this scene:

images/patterns/fixed-stripes.png

Because the point being passed to the stripe_at function is in world space, the patterns completely ignore the transformations of the objects to which they are applied.

This is unfortunate, because we expect a pattern to move when its object moves. If you make an object bigger or smaller, the pattern on it should get bigger or smaller. Rotating an object ought to rotate the pattern, too.

Further, it makes sense to be able to transform the patterns themselves, independently of the object. Want your stripes closer together or farther apart? Scale them. Want to change how they are oriented on the object? Rotate them. What to change their phase? Translate them to shift them to one side or the other.

Write the following three tests to sketch out how this behavior should look, and introduce a new method called stripe_at_object(pattern, object, point). It should return the color for the given pattern, on the given object, at the given world-space point, and it should respect the transformations on both the pattern and the object while doing so.

 Scenario​: Stripes with an object transformation
 Given​ object ← sphere()
 And​ set_transform(object, scaling(2, 2, 2))
 And​ pattern ← stripe_pattern(white, black)
 When​ c ← stripe_at_object(pattern, object, point(1.5, 0, 0))
 Then​ c = white
 
 Scenario​: Stripes with a pattern transformation
 Given​ object ← sphere()
 And​ pattern ← stripe_pattern(white, black)
 And​ set_pattern_transform(pattern, scaling(2, 2, 2))
 When​ c ← stripe_at_object(pattern, object, point(1.5, 0, 0))
 Then​ c = white
 
 Scenario​: Stripes with both an object and a pattern transformation
 Given​ object ← sphere()
 And​ set_transform(object, scaling(2, 2, 2))
 And​ pattern ← stripe_pattern(white, black)
 And​ set_pattern_transform(pattern, translation(0.5, 0, 0))
 When​ c ← stripe_at_object(pattern, object, point(2.5, 0, 0))
 Then​ c = white

Make these tests pass by implementing the stripe_at_object function. It should do the following:

  1. Multiply the given world-space point by the inverse of the object’s transformation matrix, to convert the point to object space.
  2. Then, multiply the object-space point by the inverse of the pattern’s transformation matrix to convert that point to pattern space.
  3. Pass the resulting point to your original stripe_at function, and return the result.

It’ll look like this in pseudocode:

 function​ stripe_at_object(pattern, object, world_point)
  object_point ← inverse(object.transform) * world_point
  pattern_point ← inverse(pattern.transform) * object_point
 
 return​ stripe_at(pattern, pattern_point)
 end​ ​function

Almost there! Now make your program actually use this new function by changing your lighting and shade_hit functions as follows:

  1. Add object as yet another parameter for your lighting function. The tests and pseudocode in this book assume the new function signature is lighting(material, object, light, point, eyev, normalv, in_shadow).
  2. Modify the implementation of the lighting function so that it calls stripe_at_object instead of stripe_at.
  3. Modify shade_hit so that it passes the hit’s object property to lighting.
  4. Fix your lighting tests so that they create an object (a sphere is fine—it’s just a placeholder for those tests, anyway) and pass it to lighting.

All of your tests should be passing now. Celebrate by giving the stripes pattern another try! See what happens if you rotate the stripes, or scale them, or transform the object they’re attached to.

When you’re ready, let’s talk about how to generalize all of this, in preparation for adding more patterns.

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

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