Skip to content

Tutorial 3 Constraints

Jacob Austin edited this page May 16, 2020 · 2 revisions

Goals

In this tutorial, we will apply constraints to various objects and leverage the power of containers to improve performance. Our goal will be to apply arbitrary constraints to various masses in a lattice, while modifying Lattice parameters.

Setup

See the first tutorial for the full project setup. As before, include the Titan simulation header to access the library methods.

#include <Titan/sim.h>

Setting up the simulation

We will start the simulation with a single lattice bouncing on a flat plane. This is almost the same as the previous tutorials, except that we store the pointer to the lattice object for convenient access. The lattice is nothing more than a derived container subclass which supports all the same methods.

using namespace titan;

Simulation sim; // create the basic simulation object.
Lattice * l1 = sim.createLattice(Vec(0, 0, 20), Vec(5, 5, 5), 5, 5, 5);
sim.createPlane(Vec(0, 0, 1), 0);

Next, we can add constraints to a few masses in the lattice, which we can access through the underlying vector in the lattice. We will apply a plane constraint to the first mass, which will constraint it to lie in a plane with normal (0, 0, 1) and no friction. We will also apply a direction constraint to another mass which will force it to follow a line with tangent (0, 1, 1) and no friction.

l1 -> masses[0] -> addConstraint(CONSTRAINT_PLANE, Vec(0, 0, 1), 0);
l1 -> masses[20] -> addConstraint(DIRECTION, Vec(0, 1, 1), 0);
l1 -> masses[10] -> setDrag(100); // add drag to the mass with drag coefficient C equal to 100.

Then we can start the simulation as usual. During the run, as an example of the container utilities, we will fetch (get) the latest information from the GPU, modify it, and push it back.

    sim.start();

    while (sim.time() < 10.0) {
        sim.pause(sim.time() + 1.0);

        sim.get(l1); // get lattice data from the GPU;
        l1 -> setSpringConstants(10000 * exp(-sim.time() / 3)); // exponential decay of the spring constant
        sim.set(l1); // push the lattice data to the GPU;

        sim.resume();
    }

    sim.stop();
}

When you run this program, you should be able to see the simulation running, with several of the masses exhibiting unusual behavior due to these constraints.

The finished program:

The full program now looks like this:

#include <Titan/sim.h>
using namespace titan;

int main() {
    Simulation sim; // create the basic simulation object.
    sim.setViewport(Vec(20, 20, 10), Vec(0, 0, 10), Vec(0, 0, 1)); // move the viewport so you can see the cubes

    Lattice * l1 = sim.createLattice(Vec(0, 0, 20), Vec(5, 5, 5), 5, 5, 5);
    sim.createPlane(Vec(0, 0, 1), 0);

    l1 -> masses[0] -> addConstraint(CONSTRAINT_PLANE, Vec(0, 0, 1), 0);
    l1 -> masses[20] -> addConstraint(DIRECTION, Vec(0, 1, 1), 0);
    l1 -> masses[0] -> setDrag(100); // add drag to the mass with drag coefficient C equal to 100.

    sim.start();

    while (sim.time() < 10.0) {
        sim.pause(sim.time() + 1.0);

        sim.get(l1); // get lattice data from the GPU;
        l1 -> setSpringConstants(10000 * exp(-sim.time() / 3)); // exponential decay of the spring constant
        sim.set(l1); // push the lattice data to the GPU;

        sim.resume();
    }

    sim.stop();
}

Try compiling and running this!

Result