The purpose of Dice Roller is to (unsurprisingly) roll dice! The simulator puts no influence on the outcome of the roll and can be used for any game that requires rolling dice.

There is no physics simulation, only procedurally generated parametric trajectories and rotations that result in specific (but still random) dice faces.

When launching the program from the command line, the resource directory and roll description are given as arguments. The roll description tells the program how many of which dice to roll. The resulting total of the roll is displayed on the console.

Usage: ./dice RESOURCE_DIR ROLL_DESCRIPTION

./dice : the program name

RESOURCE_DIR : the directory that holds the project's resources

ROLL_DESCRIPTION : which/how many dice are rolled

./dice : the program name

RESOURCE_DIR : the directory that holds the project's resources

ROLL_DESCRIPTION : which/how many dice are rolled

ROLL_DESCRIPTION looks like this:

- 2d4+d6 rolls 2 four-sided dice and 1 six-sided dice.
- 3d8+d20 rolls 3 eight-sided dice and 1 twenty-sided dice.
- 3d12+1d4+1d6 rolls 3 twelve-sided dice, 1 four-sided dice, and 1 six-sided dice.
- 5d12+18 rolls 5 twelve-sided dice and adds 18 to the total.

Some rules:

- there must be at least one dice term, and at most 4. The last "extra value" term at the end does not count as a term.
- there can only be one "extra value" term applied to the very end of the roll description.
- the coefficient of any given term can be anything from 1 to 9. If omitted, 1 is assumed.
- the options for dice types are d4, d6, d8, d10, d12, d20, and d100. The d100 is actually two ten-sided dice. One has numbers 0-9, and the other has numbers 00-90 in increments of 10. So, a d100 can result in a 70 and a 4. 74.

If any of the syntax rules are violated, a warning will be displayed on the console and no dice will roll. If the ROLL_DESCRIPTION is omitted, the default description of d100 will roll.

The lighting system in Dice Roller relies on the Cook-Torrance algorithm. The available parameters are:

- Ambient light r, g, b values
- A roughness value between 0 and 1
- A fresnel reflectance at normal incidence (also between 0 and 1)
- The proportion of light that is reflected diffusely. The specular proportion is determined to be 1 - diffuse.

Using this lighting system allowed for more fine grained control of the dice material.

These materials were set up to respond to a single point light that was placed in the scene.

Each dice also has a texture that is clearly divided into black/white sections.

This allowed me to tell my shaders whether or not to clip the bodies of the dice or the numbers. So, each dice is assigned 2 materials, and two renders are made per dice. One for the body, and one for the numbers.

Initially, there was no skybox, but I decided to add one in order to make the scene a bit more interesting. The skybox is simply a large cube that is texture mapped in the inside faces. The texture below was used to create the space scene.

In order to fit the project to the scope of the course, I decided to ignore true physics behavior. This did not make the motion easy though.

Instead, each face of each dice is assigned a normal vector. A random face is chosen from each dice that is being rolled and then parametric equations in 3D space are used to translate and rotate the dice through space in such a way that the randomly selected face's normal vector is pointing upwards.

This leads into the most significant challenge.

In order to get the rolling motion described above to work, I needed a normal vector for each face of each dice. Contrary to my intuition, calculating the normal vectors of the faces of each of these polyhedron is not a mathematically trivial pursuit.

In order to address this, I took advantage of the fact that each .obj file was made of vertices that already had normal vectors and texture coordinates. With this information, I defined a range of texture coordinates that contained the number. Then, I could iterate over all of that dice's vertices. If I found a vertex whose texture coordinate existed in that region, then I used that vertex's normal vector as the normal face of that dice.