The Layercake Tutorial



The math package

The Layercake project comes with a rudimentary math package. It implements the vector math required for the project and flat vector lists. It does not aim to be a complete vector math library.

The package was written to prevent a dependency on a larger external library. There is nothing special about its design and changing the code to make use of another vector math implementation should be easy. For example, Layercake’s Vec3f and libGDX’s Vector3 classes should be, for the most part, interchangeable.

Mutable vectors

The vector implementations are mutable. This means that the value of a vector can change during its lifetime. Furthermore, all operations reuse vector instances whenever possible.

The reason for this is that Java’s memory model relies on garbage collection. Under certain conditions creating many small short-lived objects can result in a lot of garbage and thus a lot of work for the collector. A mutable design allows to keep the number of such objects low.

In practice, the only thing you have to keep in mind is that whenever an operation returns a vector, it does not create a copy. Instead, a self-reference is returned. For example, the variable c in the following snippet points to the same vector as the variable a:

Vec3f a = new Vec3f(1f, 2f, 3f);
Vec3f b = new Vec3f(5f, 5f, 5f);
Vec3f c = a.add(b);

System.out.println(a); // (6.000, 7.000, 8.000)
System.out.println(b); // (5.000, 5.000, 5.000)
System.out.println(c); // (6.000, 7.000, 8.000)

You might wonder why return any reference at all? To allow for chaining of operations:

float distance = a.sub(b).len();

Flat lists

The math package comes with its own specialized implementations of vector lists. They do not add any notable functionality. Their only purpose is to keep the memory footprint low.

Java of course comes with builtin list implementations. The most commons being the ArrayList which as its name suggests is backed by a simple array. So why not just use that? The problem with an ArrayList<Vec3f> with let’s say 1000 entries is that it does not store the values of the 1000 vectors in a single array. Instead, it maintains an array with references to 1000 separate Vec3f instances. That is a lot of overhead for storing 3000 float values.

By know you probably have guessed what Layercake’s Vec3fList is doing under the hood. Just as an ArrayList it is backed by a single array. But instead of storing references to Vec3f instances, it stores their values. A Vec3fList with 1000 entries is basically a wrapper around a single float array with 3000 items.

Iterating over an Vec3fList requires only a single Vec3f instance. For example, given a list of vertices, you can either pass it in as parameter:

Vec3f vertex = new Vec3f();
for (int i = 0; i < vertices.size(); i++) {
    vertex = vertices.get(i, vertex);
    // do something with the vertex
}

Or make use of an iterator which internally maintains a single Vec3f instance:

for (Vec3f vertex: vertices) {
    // do something with the vertex
}