The Math package

In Chapter 3, Cardboard Box, we introduced 3D geometry and matrix math calculations. We will wrap these up into even more useful functions.

Much of this math code that we've put together is from existing open source projects (attributions are given in comments in the source code). After all, we might as well take advantage of the math geniuses who like this stuff and have open sourced excellent true and tested code. The code list is included with the file downloads for this book.

Note

The following list documents our math API. The actual code is included with the file downloads for this book and the GitHub repository.

Generally speaking, the mathematics falls within the subject of linear algebra, but most of it is specific to graphics programming and works within the constraints of fast floating point math on modern CPUs.

We encourage you to browse the source code included with the book, which you will obviously need access to in order to complete the project. Suffice it to say that everything included is pretty standard fare for a 3D game engine and was, in fact, largely sourced from (or checked against) an open source engine called LibGDX. The math library for LibGDX is pretty vast, optimized for mobile CPUs, and could make a great drop-in replacement for our simpler math package. We will also use the Android Matrix class extensively, which, in most cases, runs in native code and avoids the overhead of the Java Virtual Machine (JVM or Dalvik VM in the case of Android).

Here's a summary of our math API.

MathUtils

The MathUtils variables and methods are mostly self-explanatory: PI, sin, cos, and so on, defined to use floats as an alternative to Java's Math class, which contains doubles. In computer graphics, we speak floats. The math takes less power and fewer transistors and the precision loss is acceptable. Your MathUtils class should look like the following code:

// File: renderbox/math/MathUtils.java
public class MathUtils {
    static public final float PI = 3.1415927f;
    static public final float PI2 = PI * 2;
    static public final float degreesToRadians = PI / 180;
    static public final float radiansToDegrees = 180f / PI;
}

Matrix4

The Matrix4 class manages 4 x 4 transformation matrices and is used to translate (position), rotate, and scale points in three-dimensional space. We'll make good use of these soon. Here is an abridged version of the Matrix4 class with function bodies removed:

// File: renderbox/math/Matrix4.java
public class Matrix4{
    public final float[] val = new float[16];
    public Matrix4()
    public Matrix4 toIdentity()

    public static Matrix4 TRS(Vector3 position, Vector3 rotation, Vector3 scale)
    public Matrix4 translate(Vector3 position)
    public Matrix4 rotate(Vector3 rotation)
    public Matrix4 scale(Vector3 scale)
    public Vector3 multiplyPoint3x4(Vector3 v)
    public Matrix4 multiply(Matrix4 matrix)
    public Matrix4 multiply(float[] matrix)

Make a special note of the TRS function. It is used by the Transform class to combine the position, rotation, and scale information into a useful matrix, which represents all three. The order in which this matrix is created is important. First, we generate a translation matrix, and then we rotate and scale it. The resulting matrix can be multiplied by any 3D point (our vertices) to apply these three operations hierarchically.

Quaternion

A quaternion represents a rotational orientation in three-dimensional space in such a way that, when two quaternions are combined, no information is lost.

From a human point of view, it's easier to think of rotational orientation as three Euler (pronounced "oiler") angles since we think of three dimensions of rotation: pitch, yaw, and roll. The reason we use quaternions as opposed to a more straightforward vector representation of rotations is that depending on the order in which you apply the three Euler rotations to an object, the resulting 3D orientation will be different.

Even though quaternions are a four-dimensional construct, we treat each quaternion as a single value, which represents a 3D orientation. Thus, when we apply multiple rotation operations in a row, we don't run into issues where one axis' rotation influences the effect of another. If none of this makes any sense, don't worry. This is one of the trickiest concepts in 3D graphics. Here is the abridged Quaternion class:

// File: renderbox/math/Quaternion.java
public class Quaternion {
    public float x,y,z,w;
    public Quaternion()
    public Quaternion(Quaternion quat)

    public Quaternion setEulerAngles (float pitch, float yaw, float roll) public Quaternion setEulerAnglesRad (float pitch, float yaw, float roll) 
    public Quaternion conjugate ()
    public Quaternion multiply(final Quaternion other)
    public float[] toMatrix4()
    public String toString()

Vector2

A Vector2 is a two-dimensional point or direction vector defined by (X,Y) coordinates. With the Vector2 class, you can transform and manipulate vectors. Here is the abridged Vector2 class:

// File: renderbox/math/Vector2.java
public class Vector2 {
    public float x;
    public float y;
    
    public static final Vector2 zero = new Vector2(0, 0);
    public static final Vector2 up = new Vector2(0, 1);
    public static final Vector2 down = new Vector2(0, -1);
    public static final Vector2 left = new Vector2(-1, 0);
    public static final Vector2 right = new Vector2(1, 0);

    public Vector2()

    public Vector2(float xValue, float yValue)
    public Vector2(Vector2 other)
    public Vector2(float[] vec)

    public final Vector2 add(Vector2 other)
    public final Vector2 add(float otherX, float otherY, float otherZ)
    public final Vector2 subtract(Vector2 other)
    public final Vector2 multiply(float magnitude)
    public final Vector2 multiply(Vector2 other)
    public final Vector2 divide(float magnitude)
    public final Vector2 set(Vector2 other)
    public final Vector2 set(float xValue, float yValue)
    public final Vector2 scale(float xValue, float yValue)
    public final Vector2 scale(Vector2 scale)
    public final float dot(Vector2 other)
    public final float length2()
    public final float distance2(Vector2 other)
    public Vector2 normalize()
    public final Vector2 zero()
    public float[] toFloat3()
    public float[] toFloat4()
    public float[] toFloat4(float w)
    public String toString()

Vector3

A Vector3 is a three-dimensional point or direction vector defined by X, Y, and Z coordinates. With the Vector3 class, you can transform and manipulate vectors. Here is the abridged Vector3 class:

// File: renderbox/math/Vector3.java
public final class Vector3 {
    public float x;
    public float y;
    public float z;

    public static final Vector3 zero = new Vector3(0, 0, 0);
    public static final Vector3 up = new Vector3(0, 1, 0);
    public static final Vector3 down = new Vector3(0, -1, 0);
    public static final Vector3 left = new Vector3(-1, 0, 0);
    public static final Vector3 right = new Vector3(1, 0, 0);
    public static final Vector3 forward = new Vector3(0, 0, 1);
    public static final Vector3 backward = new Vector3(0, 0, -1);

    public Vector3()
    public Vector3(float xValue, float yValue, float zValue)
    public Vector3(Vector3 other)
    public Vector3(float[] vec)

    public final Vector3 add(Vector3 other)
    public final Vector3 add(float otherX, float otherY, float otherZ)
    public final Vector3 subtract(Vector3 other)
    public final Vector3 multiply(float magnitude)
    public final Vector3 multiply(Vector3 other)
    public final Vector3 divide(float magnitude)
    public final Vector3 set(Vector3 other)
    public final Vector3 set(float xValue, float yValue, float zValue)
    public final Vector3 scale(float xValue, float yValue, float zValue)
    public final Vector3 scale(Vector3 scale)
    public final float dot(Vector3 other)
    public final float length()
    public final float length2()
    public final float distance2(Vector3 other)
    public Vector3 normalize()
    public final Vector3 zero()
    public float[] toFloat3()
    public float[] toFloat4()
    public float[] toFloat4(float w)
    public String toString()

Vector2 and Vector3 share a lot of the same functionality, but pay special attention to the functions that exist in 3D, and that do not exist in 2D. Next, we'll see how the math library gets used when we implement the Transform class.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset