Ray Tracing 003The Vec3 Class


  • Added a simple vec3 class to help with operations on 3D positions, direction vectors and RGB colors.


In the first chapter I created a simple image by assigning RGB values to a number of individual variables in a loop that iterated across the x- and y-coordinates. This was ok there, but this won't work very well for scenes with multiple objects in a 3D coordinate system.

The following example produces the same image, but it introduces the vec3 class that will make it easier to perform calculations with 3-dimensional vectors later. To keep it simple, it can be used for x, y and z-coordinates as well as RGB values.

Click to view C++ source code

Vec3 with Javascript and Canvas

The beauty of C++ is that it supports operator overloading and allows me to add two 3D vectors with a standard '+' operator just as easily as adding two integer numbers. I won't have to do anything special to add up two 3D vectors or even more complex datatypes.

Unfortunately, Javascript doesn't support the same type of overloading. For each operation, I defined a function add(), mul(), and div() instead.

This is not a huge problem, but it makes the code a bit less easy to read when multiple add, multiply, or divide operations are chained to a longer expression.

There may be more elegant or more complete approaches. Vector3 is a basic datatype that has been implemented in pretty much all Javascript graphics libraries, like Three.JS for example. Since the goal was to avoid external dependencies, I'll add my own version here.

A quick note about the coding style: Normally I would define all class names to begin with an uppercase letter. For example "Vector3" which is also the style used in Three.JS. A lowercase "vec3" is the norm in other areas, for example the OpenGL Shading Language (GLSL). Maybe it's a historical thing, or simply because vec3 or vec4 are data types that can be considered just as fundamental as float or int. The book defined a lowercase "vec3" class as well, and I decided to go with it for the time being. I might change it to an uppercase format in one of the future versions.


Figure RT003: Simple canvas image rendered with Javascript

Click to view Javascript source code

Vec3 with Python

Like C++, Python supports overloading operators. This can be accomplished with a number of magic functions. In my vec3 class I used the following:

  • __pos__: +vec3
  • __neg__: -vec3
  • __iadd__: vec3 + vec3, updates value in instance
  • __isub__: vec3 - vec3, updates value in instance
  • __imul__: vec3 * vec3 or float, updates value in instance
  • __idiv__: vec3 / vec3 or float, updates value in instance
  • __add__: vec3 + vec3, returns new vec3
  • __sub__: vec3 - vec3, returns new vec3
  • __mul__: vec3 * vec3 or float, returns new vec3
  • __truediv__: vec3 / vec3 or float, returns new vec3
  • __str__: returns a string representation of this instance

With the "@property" directive, Python provides a convenient way to access the vec3 components with x, y, z or r, g, and b.

Click to view Python source code