Difficulty |
2 |
Prerequisites |
|
Reading material |
def colored_material(color) {
Materials.uniform( [ "ambient": color * 0.1,
"diffuse": color * 0.8,
"specular": Colors.white(),
"specular_exponent": 10,
"reflectivity": 0.2 ] )
}
def scene_at(now)
{
var camera = Cameras.perspective( [ "eye": pos(0,0,10),
"look_at": pos(0,0,0) ] )
var cylinder = crop_along_y(cylinder_along_y(), interval(-1,1))
var red_cylinder = decorate(colored_material(Colors.red()), cylinder)
var green_cylinder = decorate(colored_material(Colors.green()), cylinder)
var blue_cylinder = decorate(colored_material(Colors.blue()), cylinder)
var angle = Animations.animate(degrees(0), degrees(360), seconds(5))[now]
var factor = Animations.animate(1, 2, seconds(5))[now]
var x = Animations.animate(-10, 10, seconds(5))[now]
var root = union([
translate(vec(x, 0, -5), red_cylinder),
translate(vec(-2, 0, 0), rotate_around_x(angle, green_cylinder)),
translate(vec(2, 0, 0), scale(factor, factor, factor, blue_cylinder))
])
var lights = [ Lights.omnidirectional( pos(0,5,5), 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. Introduction
A ray tracer can support many shapes, such as spheres, cylinders, cones, planes, triangles, boxes and so on. When building a scene, we want to be able to place these shapes anywhere we want, resize them and rotate them on a whim.
While it would be possible to parameterize all these primitives so that each of them can have a chosen position, size and rotation, this would make their implementation more complex. Instead, we choose another approach: each primitive should only be implemented in its most simple form. For example, a sphere should be centered at \((0,0,0)\) and have radius 1, as these parameters maximally simplify the formulae involved.
So what if we want a bigger sphere? Instead of trying to make the sphere bigger, we make the camera smaller. The nice part about this approach is that we can apply the same trick on all primitives. Similarly, if we want to move the sphere up, we can simply move the camera down instead. Rotation can be handled the same way.
2. Translation
Translation consists of moving a shape to a different position.
Luckily for you, this has already been implemented: you can find the code in primitives/transformer-primitive.cpp
.
The code can act as a guide for you to implement the two other transformations (rotation and scaling.)
3. Rotation
Open Add three functions with signatures
You will need to rely on the classes defined in this extension. Add declarations to the corresponding header file so that these functions are accessible to other compilation units. |
Note
|
You might wonder why we don’t simply use a single |
4. Scaling
To the same file, add a function with signature
You will need to rely on the classes defined in this extension. Add declarations to the appropriate header file so that these functions are accessible to the other compilation units. |
5. Bindings
Add the necessary bindings so to make rotation available in scripts. |
6. Evaluation
TODO