' '

Difficulty

3

Prerequisites

ray-tracers/v2

Reading material

design/primitives/ray-intersections

primitives/cone

def scene_at(now)
{
  var eye_position = Animations.circular( [ "position": pos(0, 0, 10),
                                            "around": pos(0, 0, 0),
                                            "duration": seconds(5) ] )

  var camera = Cameras.perspective( [ "eye": eye_position[now],
                                      "look_at": pos(0,0,0) ] )

  var material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                      "diffuse": Colors.blue() * 0.8,
                                      "specular": Colors.white() * 0.5,
                                      "specular_exponent": 10 ] )

  var cone1 = decorate(material, crop_along_x(cone_along_x(), interval(-1,1)))
  var cone2 = translate(vec(-3, 0, 0), decorate(material, crop_along_y(cone_along_y(), interval(-1,1))))
  var cone3 = translate(vec(3, 0, 0), decorate(material, crop_along_z(cone_along_z(), interval(-1,1))))

  var root = union( [ cone1, cone2, cone3 ] )

  var lights = [ Lights.omnidirectional( pos(5,5,5), Colors.white() * 0.5 ),
                 Lights.omnidirectional( pos(-5,5,-5), Colors.white() * 0.5 )
               ]

  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

For this extension, you will implement three cones:

  • One that is directed along the X-axis.

  • One that is directed along the Y-axis.

  • One that is directed along the Z-axis.

All three are infinitely long, make an angle of 45° and go through \((0, 0, 0)\).

  • Create new files primitives/cone-primitive.cpp and primitives/cone-primitive.h.

  • Write the necessary class(es) that model these three cylinders.

  • Provide factory functions cone_along_x(), cone_along_y(), cone_along_z().

  • Add bindings so as to make cones available in the scripting language.

Tip

You are given a class QuadraticEquation which can come in handy.

Tip

You can start off with copying the Sphere primitive code and change the code so that it models a cylinder.

2. Evaluation

Show how you prevented code duplication in your implementation of the three cylinders.

Render the scene below:

def scene_at(now)
{
  var t = Animations.animate(0, 1, seconds(5))[now]

  var camera = Cameras.perspective( [ "eye": pos(-5,0,0),
                                      "look_at": pos(0,0,0) ] )

  var cone_material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                           "diffuse": Colors.red() * 0.8 ] )

  var plane_material = Materials.uniform( [ "ambient": Colors.white() * 0.1,
                                            "diffuse": Colors.white() * 0.8 ] )

  var cone = decorate(cone_material, cone_along_z())
  var back_plane = translate(vec(0,0,-1), xy_plane())
  var front_plane = translate(vec(0,0,1), xy_plane())
  var planes = decorate(plane_material, union( [ back_plane, front_plane ] ))

  var root = union( [ cone, planes ] )

  var lights = [ Lights.omnidirectional( pos(-5,-5+10*t,0), Colors.white() * 0.5 ) ]

  create_scene(camera, root, lights)
}

var raytracer   = Raytracers.v6()

var renderer    = Renderers.standard( [ "width": 500,
                                       "height": 500,
                                       "sampler": Samplers.single(),
                                       "ray_tracer": raytracer ] )

pipeline( scene_animation(scene_at, seconds(5)),
          [ Pipeline.animation(30),
            Pipeline.renderer(renderer),
            Pipeline.studio() ] )