Current section
Files
Jump to
Current section
Files
src/matrix@mat3f.erl
-module(matrix@mat3f).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/matrix/mat3f.gleam").
-export([new/9, from_cols/3, from_diagonal/1, from_quaternion/1, transpose/1, determinant/1, mul_vec3/2, mul_transpose_vec3/2, negate/1, add/2, subtract/2, multiply/2, scale/2, scale_diagonal/2, inverse/1, divide/2]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(" 3x3 matrices of floats\n").
-file("src/matrix/mat3f.gleam", 33).
?DOC(
" Constructs a `Mat3f` from its components:\n"
" ```text\n"
" | a d g |\n"
" | b e h |\n"
" | c f i |\n"
" ```\n"
).
-spec new(
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float()
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
new(A, B, C, D, E, F, G, H, I) ->
{vec3, {vec3, A, B, C}, {vec3, D, E, F}, {vec3, G, H, I}}.
-file("src/matrix/mat3f.gleam", 53).
?DOC(
" Constructs a `Mat3f` from its three columns.\n"
" ```text\n"
" | ax bx cx |\n"
" | ay by cy |\n"
" | az bz cz |\n"
" ```\n"
).
-spec from_cols(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_cols(A, B, C) ->
{vec3, A, B, C}.
-file("src/matrix/mat3f.gleam", 63).
?DOC(
" Constructs a `Mat3f` with the given diagonal and all other entries set to 0.\n"
" ```text\n"
" | x 0.0 0.0 |\n"
" | 0.0 y 0.0 |\n"
" | 0.0 0.0 z |\n"
" ```\n"
).
-spec from_diagonal(vec@vec3:vec3(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_diagonal(Diag) ->
new(
erlang:element(2, Diag),
+0.0,
+0.0,
+0.0,
erlang:element(3, Diag),
+0.0,
+0.0,
+0.0,
erlang:element(4, Diag)
).
-file("src/matrix/mat3f.gleam", 68).
?DOC(" Constructs a 3D rotation matrix from the given quaternion, represented as a `vec4.Vec4(Float)`.\n").
-spec from_quaternion(vec@vec4:vec4(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_quaternion(Q) ->
Rotation = vec@vec4f:normalize(Q),
X2 = erlang:element(2, Rotation) + erlang:element(2, Rotation),
Y2 = erlang:element(3, Rotation) + erlang:element(3, Rotation),
Z2 = erlang:element(4, Rotation) + erlang:element(4, Rotation),
Xx = erlang:element(2, Rotation) * X2,
Xy = erlang:element(2, Rotation) * Y2,
Xz = erlang:element(2, Rotation) * Z2,
Yy = erlang:element(3, Rotation) * Y2,
Yz = erlang:element(3, Rotation) * Z2,
Zz = erlang:element(4, Rotation) * Z2,
Wx = erlang:element(5, Rotation) * X2,
Wy = erlang:element(5, Rotation) * Y2,
Wz = erlang:element(5, Rotation) * Z2,
from_cols(
{vec3, 1.0 - (Yy + Zz), Xy + Wz, Xz - Wy},
{vec3, Xy - Wz, 1.0 - (Xx + Zz), Yz + Wx},
{vec3, Xz + Wy, Yz - Wx, 1.0 - (Xx + Yy)}
).
-file("src/matrix/mat3f.gleam", 92).
?DOC(" Transposes the `Mat3f` along the diagonal.\n").
-spec transpose(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec3:vec3(vec@vec3:vec3(float())).
transpose(Mat) ->
new(
erlang:element(2, erlang:element(2, Mat)),
erlang:element(2, erlang:element(3, Mat)),
erlang:element(2, erlang:element(4, Mat)),
erlang:element(3, erlang:element(2, Mat)),
erlang:element(3, erlang:element(3, Mat)),
erlang:element(3, erlang:element(4, Mat)),
erlang:element(4, erlang:element(2, Mat)),
erlang:element(4, erlang:element(3, Mat)),
erlang:element(4, erlang:element(4, Mat))
).
-file("src/matrix/mat3f.gleam", 107).
?DOC(" Returns the determinant for the `Mat3f`.\n").
-spec determinant(vec@vec3:vec3(vec@vec3:vec3(float()))) -> float().
determinant(Mat) ->
{vec3, {vec3, A1, B1, C1}, {vec3, A2, B2, C2}, {vec3, A3, B3, C3}} = Mat,
((((((A1 * B2) * C3) - ((A1 * B3) * C2)) - ((A2 * B1) * C3)) + ((A2 * B3) * C1))
+ ((A3 * B1) * C2))
- ((A3 * B2) * C1).
-file("src/matrix/mat3f.gleam", 143).
?DOC(" Transforms a `Vec3f` by this `Mat3f`.\n").
-spec mul_vec3(vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(float())) -> vec@vec3:vec3(float()).
mul_vec3(Mat, Rhs) ->
_pipe = vec@vec3:map2(Mat, Rhs, fun vec@vec3f:scale/2),
_pipe@1 = vec@vec3:to_list(_pipe),
vec@vec3f:sum(_pipe@1).
-file("src/matrix/mat3f.gleam", 150).
?DOC(" Transforms a `Vec3f` by the transpose of this `Mat3f`.\n").
-spec mul_transpose_vec3(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(float()).
mul_transpose_vec3(Mat, Rhs) ->
vec@vec3:map(Mat, fun(_capture) -> vec@vec3f:dot(_capture, Rhs) end).
-file("src/matrix/mat3f.gleam", 155).
?DOC(" Negates all elements of the `Mat3f`\n").
-spec negate(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec3:vec3(vec@vec3:vec3(float())).
negate(Mat) ->
vec@vec3:map(Mat, fun vec@vec3f:negate/1).
-file("src/matrix/mat3f.gleam", 160).
?DOC(" Adds two `Mat3f` together.\n").
-spec add(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(vec@vec3:vec3(float()))
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
add(A, B) ->
vec@vec3:map2(A, B, fun vec@vec3f:add/2).
-file("src/matrix/mat3f.gleam", 165).
?DOC(" Subtracts one `Mat3f` from the other.\n").
-spec subtract(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(vec@vec3:vec3(float()))
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
subtract(A, B) ->
vec@vec3:map2(A, B, fun vec@vec3f:subtract/2).
-file("src/matrix/mat3f.gleam", 170).
?DOC(" Multiplies two `Mat3f` together.\n").
-spec multiply(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(vec@vec3:vec3(float()))
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
multiply(A, B) ->
vec@vec3:map(B, fun(_capture) -> mul_vec3(A, _capture) end).
-file("src/matrix/mat3f.gleam", 181).
?DOC(" Scales the `Mat3f` by a `Float` factor.\n").
-spec scale(vec@vec3:vec3(vec@vec3:vec3(float())), float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
scale(Mat, Scale) ->
vec@vec3:map(Mat, fun(_capture) -> vec@vec3f:scale(_capture, Scale) end).
-file("src/matrix/mat3f.gleam", 188).
?DOC(
" Scales the `Mat3f` by a `Vec3f`.\n"
"\n"
" This is faster than creating a diagonal scaling matrix and then multiplying that.\n"
).
-spec scale_diagonal(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
scale_diagonal(Mat, Scale) ->
vec@vec3:map2(Mat, Scale, fun vec@vec3f:scale/2).
-file("src/matrix/mat3f.gleam", 192).
-spec xz_(vec@vec3:vec3(IRO)) -> vec@vec2:vec2(IRO).
xz_(V) ->
{vec2, erlang:element(2, V), erlang:element(4, V)}.
-file("src/matrix/mat3f.gleam", 196).
-spec xy_(vec@vec3:vec3(IRR)) -> vec@vec2:vec2(IRR).
xy_(V) ->
{vec2, erlang:element(2, V), erlang:element(3, V)}.
-file("src/matrix/mat3f.gleam", 200).
-spec yz_(vec@vec3:vec3(IRU)) -> vec@vec2:vec2(IRU).
yz_(V) ->
{vec2, erlang:element(3, V), erlang:element(4, V)}.
-file("src/matrix/mat3f.gleam", 118).
?DOC(" Inverts the `Mat3f`, returning an error if the determinant is zero.\n").
-spec inverse(vec@vec3:vec3(vec@vec3:vec3(float()))) -> {ok,
vec@vec3:vec3(vec@vec3:vec3(float()))} |
{error, nil}.
inverse(Mat) ->
gleam@result:map(
gleam@float:divide(1.0, determinant(Mat)),
fun(Inv_det) ->
Xx = begin
_pipe = Mat,
_pipe@1 = yz_(_pipe),
_pipe@2 = vec@vec2:map(_pipe@1, fun yz_/1),
matrix@mat2f:determinant(_pipe@2)
end,
Xy = begin
_pipe@3 = Mat,
_pipe@4 = xz_(_pipe@3),
_pipe@5 = vec@vec2:map(_pipe@4, fun yz_/1),
_pipe@6 = vec@vec2:swap(_pipe@5),
matrix@mat2f:determinant(_pipe@6)
end,
Xz = begin
_pipe@7 = Mat,
_pipe@8 = xy_(_pipe@7),
_pipe@9 = vec@vec2:map(_pipe@8, fun yz_/1),
matrix@mat2f:determinant(_pipe@9)
end,
Yx = begin
_pipe@10 = Mat,
_pipe@11 = yz_(_pipe@10),
_pipe@12 = vec@vec2:map(_pipe@11, fun xz_/1),
_pipe@13 = vec@vec2:swap(_pipe@12),
matrix@mat2f:determinant(_pipe@13)
end,
Yy = begin
_pipe@14 = Mat,
_pipe@15 = xz_(_pipe@14),
_pipe@16 = vec@vec2:map(_pipe@15, fun xz_/1),
matrix@mat2f:determinant(_pipe@16)
end,
Yz = begin
_pipe@17 = Mat,
_pipe@18 = xy_(_pipe@17),
_pipe@19 = vec@vec2:map(_pipe@18, fun xz_/1),
_pipe@20 = vec@vec2:swap(_pipe@19),
matrix@mat2f:determinant(_pipe@20)
end,
Zx = begin
_pipe@21 = Mat,
_pipe@22 = yz_(_pipe@21),
_pipe@23 = vec@vec2:map(_pipe@22, fun xy_/1),
matrix@mat2f:determinant(_pipe@23)
end,
Zy = begin
_pipe@24 = Mat,
_pipe@25 = xz_(_pipe@24),
_pipe@26 = vec@vec2:map(_pipe@25, fun xy_/1),
_pipe@27 = vec@vec2:swap(_pipe@26),
matrix@mat2f:determinant(_pipe@27)
end,
Zz = begin
_pipe@28 = Mat,
_pipe@29 = xy_(_pipe@28),
_pipe@30 = vec@vec2:map(_pipe@29, fun xy_/1),
matrix@mat2f:determinant(_pipe@30)
end,
scale(new(Xx, Xy, Xz, Yx, Yy, Yz, Zx, Zy, Zz), Inv_det)
end
).
-file("src/matrix/mat3f.gleam", 175).
?DOC(" Divides one `Mat3f` by another. Equivalent to multiplying the inverse of the second matrix.\n").
-spec divide(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(vec@vec3:vec3(float()))
) -> {ok, vec@vec3:vec3(vec@vec3:vec3(float()))} | {error, nil}.
divide(A, B) ->
gleam@result:map(inverse(B), fun(Inv_b) -> multiply(A, Inv_b) end).