Skip to content

4D matrix design #557

Description

@bvssvni

Dyon supports 4D matrices to transform 4D vectors.

To define a new 4D matrix, one uses the mat4 block. The mat4 block can omit parentheses of basis vectors and even remaining rows, filling in with row vectors from the identity matrix:

mat4 {(1, 0, 0, 0); (0, 1, 0, 0); (0, 0, 1, 0); (0, 0, 0, 1)}
mat4 {1,0,0,0; 0,1,0,0; 0,0,1,0; 0,0,0,1} // With omitted parentheses
mat4 {1,; 0,1; 0,0,1; 0,0,0,1}  // Trailing zeroes can be omitted like in `vec4` syntax
mat4 {1,; 0,1; 0,0,1} // Fills out row vectors corresponding to identity matrix
mat4 {1,;} // Identity matrix.

Formatted output is designed for readability.

The precision is f32, the same as for vec4.

The format is row-major at syntax level for easier working with basis vectors, while column-major is used internally for easier integration with GPU shaders in game engines.

You can add or multiply matrices:

fn main() {
    a := mat4 {1,;}
    b := a + a
    // Prints `mat4 {2,0,0,0; 0,2,0,0; 0,0,2,0; 0,0,0,2}`.
    println(b)

    // Prints `mat4 {4,0,0,0; 0,4,0,0; 0,0,4,0; 0,0,0,4}`.
    c := b * b
    println(c)
}

You can also use +=, -= and *= with matrices:

fn main() {
    a := mat4 {1,;}
    a += a
    // Prints `mat4 {2,0,0,0; 0,2,0,0; 0,0,2,0; 0,0,0,2}`.
    println(a)

    // Prints `mat4 {4,0,0,0; 0,4,0,0; 0,0,4,0; 0,0,0,4}`.
    a *= a
    println(a)

    // Prints `mat4 {3,0,0,0; 0,3,0,0; 0,0,3,0; 0,0,0,3}`
    a -= mat4 {1,;}
    println(a)
}

You can use +, - and * with scalars and matrices:

fn main() {
    a := mat4 {1,2,3,4;2,3,4,1;3,4,1,2;4,1,2,3}
    println(2 * a)
    println(a * 2)
    println(2 + a)
    println(a + 2)
    println(2 - a)
    println(a - 2)
}

You can transform a vector by multiplying a 4D matrix with a vec4 that has a zero in the 4th component:

fn main() {
    // Scale x-axis up 2 times.
    a := mat4 {2,;}
    println(a * (1, 1, 1))

    // Scale y-axis up 2 times.
    a := mat4 {1,; 0,2}
    println(a * (1, 1, 1))

    // Scale z-axis up 2 times.
    a := mat4 {1,; 0,1; 0,0,2}
    println(a * (1, 1, 1))
    // The same using `scale`.
    println(scale((1, 1, 2)) * (1, 1, 1))
}

You can transform a point by multiplying a 4D matrix with a vec4 that has a one in the 4th component:

fn main() {
    pos := (1, 2, 3)
    // Put `1` in the 4th component to transform a point.
    println(mov((1, 2)) * (xyz pos, 1))
}

With rx, ry, rz, rw, rv you get row vectors and with cx, cy, cz, cw, cv you get column vectors:

fn main() {
    a := mat4 {
        1,2,3,4;
        5,6,7,8;
        9,10,11,12;
        13,14,15,16;
    }

    // Print row vectors.
    println(rx(a)) // Prints `(1, 2, 3, 4)`.
    println(ry(a)) // Prints `(5, 6, 7, 8)`.
    println(rz(a)) // Prints `(9, 10, 11, 12)`.
    println(rw(a)) // Prints `(13, 14, 15, 16)`.

    // Print row vectors using a loop.
    for i 4 {println(rv(a, i))}

    // Print column vectors.
    println(cx(a)) // Prints `(1, 5, 9, 13)`
    println(cy(a)) // Prints `(2, 6, 10, 14)`
    println(cz(a)) // Prints `(3, 7, 11, 15)`
    println(cw(a)) // Prints `(4, 8, 12, 16)`

    // Print column vectors using a loop.
    for i 4 {println(cv(a, i))}
}

This is designed for:

  • Easier 2D and 3D programming
  • Easier physics programming

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions