| Difficulty | 2 | 
| Reading material | |
def material(c)
{
  Materials.uniform( [ "ambient": Colors.white() * 0.1,
                       "diffuse": c * 0.8,
                       "specular": Colors.white() * 0.5,
                       "specular_exponent": 10,
                       "reflectivity": 0.0,
                       "transparency": 0,
                       "refractive_index": 0 ] )
}
def scene_at(now)
{
  var eye_position = Animations.lissajous( [ "x_amplitude": 5,
                                             "x_frequency": 1,
                                             "x_phase": degrees(90),
                                             "y_amplitude": 5,
                                             "y_frequency": 1,
                                             "y_phase": degrees(0),
                                             "z_amplitude": 5,
                                             "z_frequency": 1,
                                             "z_phase": degrees(0),
                                             "duration": seconds(5) ] )
  var camera = Cameras.perspective( [ "eye": eye_position[now],
                                      "look_at": pos(0,0,0) ] )
  var p1 = Pos.spherical(1, degrees(0), degrees(90))
  var p2 = Pos.spherical(1, degrees(60), degrees(-30))
  var p3 = Pos.spherical(1, degrees(180), degrees(-30))
  var p4 = Pos.spherical(1, degrees(-60), degrees(-30))
  var root = union( [ decorate( material(Colors.red()), triangle(p1, p2, p3) ),
                      decorate( material(Colors.green()), triangle(p1, p3, p4) ),
                      decorate( material(Colors.blue()), triangle(p1, p4, p2) ),
                      decorate( material(Colors.yellow()), triangle(p2, p4, p3) ) ] )
  var lights = [ Lights.omnidirectional( pos(0, 5, 0), Colors.white() ), Lights.omnidirectional( pos(0, -5, 0), Colors.white() ) ]
  create_scene(camera, root, lights)
}
var raytracer   = Raytracers.v6()
var renderer    = Renderers.standard( [ "width": 500,
                                        "height": 500,
                                        "sampler": Samplers.multijittered(2),
                                        "ray_tracer": raytracer ] )
pipeline( scene_animation(scene_at, seconds(5)),
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.studio() ] )1. Implementation
1.1. Setting Things Up
| Create new files  Since you have no  | 
1.2. TriangleImplementation
| In   | 
Now that we have a class TriangleImplementation with a constructor, we can finish our factory function.
| Give the factory function its body. | 
1.3. find_all_hits
In order to be able to render triangles, we need to implement the ray intersection algorithm.
| Implement the method  Optionally, for better performance (which will make a big difference when used in the context of meshes), implement  | 
1.4. bounding_box
The bounding_box method will be crucial when implementing meshes as the bounding box accelerator depends on it.
As a reminder: this method should compute a minimally sized math::Box that still fully contains the triangle.
 
The box must be axis aligned, which means its edges must be horizontal or vertical. Given a triangle, you need to find
- 
The x-coordinate of the left side. 
- 
The x-coordinate of the right side. 
- 
This forms the box’s x-interval. 
- 
The same needs to be done for the y- and z-dimension. 
| Note | Don’t confuse  
 | 
| Implement the method  | 
1.5. Finishing Touches
| Add a binding for the scripting language. | 
2. Evaluation
| Render the scene below:  |