Putting It Together

Let’s wrap this up with an example of how you can use groups in your scenes. You are going to build a model of a hexagon using cylinders and spheres, like this:

images/groups/hexagon.png

You’ll build this by first defining a single instance of each component: one sphere (to become the corners of the hexagon), and one cylinder (to become the edges). You’ll transform each into place once, and add them to a group. Then, you’ll create duplicates of that group, rotating each duplicate around the y axis until the whole hexagon is constructed.

Start by writing a function that creates the prototypical sphere component, scaling it by 25% and translating it -1 unit in z. The following pseudocode shows this as a function named hexagon_corner.

 function​ hexagon_corner()
  corner ← sphere()
  set_transform(corner, translation(0, 0, -1) *
  scaling(0.25, 0.25, 0.25))
 return​ corner
 end​ ​function
images/aside-icons/tip.png

Remember that when you combine matrix transformations, you do so in reverse order. Thus, though the pseudocode for hexagon_corner multiplies the translation by the scaling, the result is that the sphere is scaled first and then translated.

Next, write a function that creates the prototypical cylinder component. Limit it to a minimum of y=0 and a maximum of y=1, and scale it by 25% in x and z. Rotate it -π/2 radians in z (to tip it over) and -π/6 radians in y (to orient it as an edge). Then, translate it -1 unit in z. In pseudocode, this hexagon_edge function might look like this:

 function​ hexagon_edge()
  edge ← cylinder()
  edge.minimum ← 0
  edge.maximum ← 1
  set_transform(edge, translation(0, 0, -1) *
  rotation_y(-​π​/6) *
  rotation_z(-​π​/2) *
  scaling(0.25, 1, 0.25))
 return​ edge
 end​ ​function

The next step is to join those two primitives into a group, forming one side of the hexagon. The following hexagon_side function demonstrates this in pseudocode.

 function​ hexagon_side()
  side ← group()
 
  add_child(side, hexagon_corner())
  add_child(side, hexagon_edge())
 
 return​ side
 end​ ​function

Once you’ve got a function that can return a single side of the hexagon, you can write the final function, hexagon, which calls hexagon_side six times and rotates each piece into place, like so:

 function​ hexagon()
  hex ← group()
 
 for​ n ← 0 to 5
  side ← hexagon_side()
  set_transform(side, rotation_y(n*​π​/3))
  add_child(hex, side)
 end​ ​for
 
 return​ hex
 end​ ​function

From there, you can add a light source and a camera, and go nuts with it!

What other composite shapes can you build? Try creating a stick figure or an automobile. Trees and plants are definitely possible, too, and lend themselves well to fractal algorithms like Lindenmayer systems.

Also, you may soon realize that materials applied to a group have no effect at all on the shapes it contains. What if you wanted the shapes in your ray tracer to be able to “inherit” materials from their parents? How might you extend your code to make that happen?

Give it some thought. Then, once you’ve played with this new feature enough, read on. You’ll add your final primitive in the next chapter: the triangle.

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

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