Current section

Files

Jump to
matrix_gleam src matrix@mat4f.erl
Raw

src/matrix@mat4f.erl

-module(matrix@mat4f).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/matrix/mat4f.gleam").
-export([new/16, from_cols/4, from_diagonal/1, transpose/1, diagonal/1, determinant/1, mul_vec4/2, mul_transpose_vec4/2, scale/2, add/2, subtract/2, from_mat3/1, from_mat3_translation/2, from_translation/1, from_axis_angle/2, from_rotation_x/1, from_rotation_y/1, from_rotation_z/1, from_scale/1, inverse/1, look_to_rh/3, look_to_lh/3, look_at_lh/3, look_at_rh/3, transform_point3/2, transform_vector3/2, from_scale_rotation_translation/3, from_rotation_translation/2, from_quaternion/1, to_scale_rotation_translation/1]).
-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(" 4x4 matrices of floats\n").
-file("src/matrix/mat4f.gleam", 31).
?DOC(
" Constructs a `Mat4f` from its components.\n"
" ```text\n"
" | ax bx cx dx |\n"
" | ay by cy dy |\n"
" | az bz cz dz |\n"
" | aw bw cw dw |\n"
" ```\n"
).
-spec new(
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float(),
float()
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
new(Ax, Ay, Az, Aw, Bx, By, Bz, Bw, Cx, Cy, Cz, Cw, Dx, Dy, Dz, Dw) ->
{vec4,
{vec4, Ax, Ay, Az, Aw},
{vec4, Bx, By, Bz, Bw},
{vec4, Cx, Cy, Cz, Cw},
{vec4, Dx, Dy, Dz, Dw}}.
-file("src/matrix/mat4f.gleam", 64).
?DOC(
" Constructs a `Mat4f` from its four columns.\n"
" ```text\n"
" | a.x b.x c.x d.x |\n"
" | a.y b.y c.y d.y |\n"
" | a.z b.z c.z d.z |\n"
" | a.w b.w c.w d.w |\n"
" ```\n"
).
-spec from_cols(
vec@vec4:vec4(float()),
vec@vec4:vec4(float()),
vec@vec4:vec4(float()),
vec@vec4:vec4(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_cols(A, B, C, D) ->
{vec4, A, B, C, D}.
-file("src/matrix/mat4f.gleam", 69).
?DOC(" Creates a 4x4 matrix with its diagonal set to `diagonal` and all other entries are 0.\n").
-spec from_diagonal(vec@vec4:vec4(float())) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_diagonal(Diagonal) ->
from_cols(
{vec4, erlang:element(2, Diagonal), +0.0, +0.0, +0.0},
{vec4, +0.0, erlang:element(3, Diagonal), +0.0, +0.0},
{vec4, +0.0, +0.0, erlang:element(4, Diagonal), +0.0},
{vec4, +0.0, +0.0, +0.0, erlang:element(5, Diagonal)}
).
-file("src/matrix/mat4f.gleam", 79).
?DOC(" Transposes the `Mat4f` along the diagonal.\n").
-spec transpose(vec@vec4:vec4(vec@vec4:vec4(float()))) -> vec@vec4:vec4(vec@vec4:vec4(float())).
transpose(Mat) ->
from_cols(
{vec4,
erlang:element(2, erlang:element(2, Mat)),
erlang:element(2, erlang:element(3, Mat)),
erlang:element(2, erlang:element(4, Mat)),
erlang:element(2, erlang:element(5, Mat))},
{vec4,
erlang:element(3, erlang:element(2, Mat)),
erlang:element(3, erlang:element(3, Mat)),
erlang:element(3, erlang:element(4, Mat)),
erlang:element(3, erlang:element(5, Mat))},
{vec4,
erlang:element(4, erlang:element(2, Mat)),
erlang:element(4, erlang:element(3, Mat)),
erlang:element(4, erlang:element(4, Mat)),
erlang:element(4, erlang:element(5, Mat))},
{vec4,
erlang:element(5, erlang:element(2, Mat)),
erlang:element(5, erlang:element(3, Mat)),
erlang:element(5, erlang:element(4, Mat)),
erlang:element(5, erlang:element(5, Mat))}
).
-file("src/matrix/mat4f.gleam", 89).
?DOC(" Extracts the diagonal of the `Mat4f`.\n").
-spec diagonal(vec@vec4:vec4(vec@vec4:vec4(float()))) -> vec@vec4:vec4(float()).
diagonal(Mat) ->
{vec4,
erlang:element(2, erlang:element(2, Mat)),
erlang:element(3, erlang:element(3, Mat)),
erlang:element(4, erlang:element(4, Mat)),
erlang:element(5, erlang:element(5, Mat))}.
-file("src/matrix/mat4f.gleam", 94).
?DOC(" Returns the determinant of the `Mat4f`.\n").
-spec determinant(vec@vec4:vec4(vec@vec4:vec4(float()))) -> float().
determinant(Mat) ->
{vec4, M00, M01, M02, M03} = erlang:element(2, Mat),
{vec4, M10, M11, M12, M13} = erlang:element(3, Mat),
{vec4, M20, M21, M22, M23} = erlang:element(4, Mat),
{vec4, M30, M31, M32, M33} = erlang:element(5, Mat),
A2323 = (M22 * M33) - (M23 * M32),
A1323 = (M21 * M33) - (M23 * M31),
A1223 = (M21 * M32) - (M22 * M31),
A0323 = (M20 * M33) - (M23 * M30),
A0223 = (M20 * M32) - (M22 * M30),
A0123 = (M20 * M31) - (M21 * M30),
(((M00 * (((M11 * A2323) - (M12 * A1323)) + (M13 * A1223))) - (M01 * (((M10
* A2323)
- (M12 * A0323))
+ (M13 * A0223))))
+ (M02 * (((M10 * A1323) - (M11 * A0323)) + (M13 * A0123))))
- (M03 * (((M10 * A1223) - (M11 * A0223)) + (M12 * A0123))).
-file("src/matrix/mat4f.gleam", 118).
?DOC(" Transforms a 4D vector by this `Mat4f`.\n").
-spec mul_vec4(vec@vec4:vec4(vec@vec4:vec4(float())), vec@vec4:vec4(float())) -> vec@vec4:vec4(float()).
mul_vec4(Mat, Rhs) ->
_pipe = vec@vec4:map2(Mat, Rhs, fun vec@vec4f:scale/2),
_pipe@1 = vec@vec4:to_list(_pipe),
vec@vec4f:sum(_pipe@1).
-file("src/matrix/mat4f.gleam", 127).
?DOC(
" Transforms a 4D vector by the transpose of the `Mat4f`.\n"
"\n"
" Equivalent to matrix multiplication where the vector is on the left.\n"
).
-spec mul_transpose_vec4(
vec@vec4:vec4(vec@vec4:vec4(float())),
vec@vec4:vec4(float())
) -> vec@vec4:vec4(float()).
mul_transpose_vec4(Mat, Rhs) ->
vec@vec4:map(Mat, fun(_capture) -> vec@vec4f:dot(_capture, Rhs) end).
-file("src/matrix/mat4f.gleam", 132).
?DOC(" Scales the `Mat4f` by a `Float`.\n").
-spec scale(vec@vec4:vec4(vec@vec4:vec4(float())), float()) -> vec@vec4:vec4(vec@vec4:vec4(float())).
scale(Mat, Scale) ->
vec@vec4:map(Mat, fun(_capture) -> vec@vec4f:scale(_capture, Scale) end).
-file("src/matrix/mat4f.gleam", 137).
?DOC(" Adds two `Mat4f`s together\n").
-spec add(
vec@vec4:vec4(vec@vec4:vec4(float())),
vec@vec4:vec4(vec@vec4:vec4(float()))
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
add(A, B) ->
vec@vec4:map2(A, B, fun vec@vec4f:add/2).
-file("src/matrix/mat4f.gleam", 142).
?DOC(" Subtracts `Mat4f` `b` from `a`\n").
-spec subtract(
vec@vec4:vec4(vec@vec4:vec4(float())),
vec@vec4:vec4(vec@vec4:vec4(float()))
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
subtract(A, B) ->
vec@vec4:map2(A, B, fun vec@vec4f:subtract/2).
-file("src/matrix/mat4f.gleam", 219).
?DOC(
" Creates an affine transformation matrix from the given 3x3 linear transformation\n"
" matrix.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_mat3(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_mat3(M) ->
from_cols(
matrix@internal@projection:extend3(erlang:element(2, M), +0.0),
matrix@internal@projection:extend3(erlang:element(3, M), +0.0),
matrix@internal@projection:extend3(erlang:element(4, M), +0.0),
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 227).
?DOC(
" Creates an affine transformation matrics from a 3x3 matrix (expressing scale, shear and\n"
" rotation) and a translation vector.\n"
"\n"
" Equivalent to `multiply(from_translation(translation), from_mat3(mat3))`\n"
).
-spec from_mat3_translation(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_mat3_translation(Mat3, Translation) ->
from_cols(
matrix@internal@projection:extend3(erlang:element(2, Mat3), +0.0),
matrix@internal@projection:extend3(erlang:element(3, Mat3), +0.0),
matrix@internal@projection:extend3(erlang:element(4, Mat3), +0.0),
matrix@internal@projection:extend3(Translation, 1.0)
).
-file("src/matrix/mat4f.gleam", 239).
?DOC(
" Creates an affine transformation matrix from the given 3D `translation`.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_translation(vec@vec3:vec3(float())) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_translation(Translation) ->
from_cols(
{vec4, 1.0, +0.0, +0.0, +0.0},
{vec4, +0.0, 1.0, +0.0, +0.0},
{vec4, +0.0, +0.0, 1.0, +0.0},
matrix@internal@projection:extend3(Translation, 1.0)
).
-file("src/matrix/mat4f.gleam", 247).
?DOC(
" Creates an affine transformation matrix containing a 3D rotation around a normalized\n"
" rotation `axis` of `angle` (in radians).\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_axis_angle(vec@vec3:vec3(float()), float()) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_axis_angle(Axis, Angle) ->
Axis@1 = vec@vec3f:normalize(Axis),
Sin = gleam_community@maths:sin(Angle),
Cos = gleam_community@maths:cos(Angle),
Axis_sin = vec@vec3f:scale(Axis@1, Sin),
Axis_sq = vec@vec3f:multiply(Axis@1, Axis@1),
Omc = 1.0 - Cos,
Xyomc = (erlang:element(2, Axis@1) * erlang:element(3, Axis@1)) * Omc,
Xzomc = (erlang:element(2, Axis@1) * erlang:element(4, Axis@1)) * Omc,
Yzomc = (erlang:element(3, Axis@1) * erlang:element(4, Axis@1)) * Omc,
from_cols(
{vec4,
(erlang:element(2, Axis_sq) * Omc) + Cos,
Xyomc + erlang:element(4, Axis_sin),
Xzomc - erlang:element(3, Axis_sin),
+0.0},
{vec4,
Xyomc - erlang:element(4, Axis_sin),
(erlang:element(3, Axis_sq) * Omc) + Cos,
Yzomc + erlang:element(2, Axis_sin),
+0.0},
{vec4,
Xzomc + erlang:element(3, Axis_sin),
Yzomc - erlang:element(2, Axis_sin),
(erlang:element(4, Axis_sq) * Omc) + Cos,
+0.0},
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 269).
?DOC(
" Creates an affine transformation matrix containing a 3D rotation around the x axis of\n"
" `angle` (in radians).\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_rotation_x(float()) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_rotation_x(Angle) ->
Sin = gleam_community@maths:sin(Angle),
Cos = gleam_community@maths:cos(Angle),
from_cols(
{vec4, 1.0, +0.0, +0.0, +0.0},
{vec4, +0.0, Cos, Sin, +0.0},
{vec4, +0.0, +0.0 - Sin, Cos, +0.0},
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 284).
?DOC(
" Creates an affine transformation matrix containing a 3D rotation around the y axis of\n"
" `angle` (in radians).\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_rotation_y(float()) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_rotation_y(Angle) ->
Sin = gleam_community@maths:sin(Angle),
Cos = gleam_community@maths:cos(Angle),
from_cols(
{vec4, Cos, +0.0, +0.0 - Sin, +0.0},
{vec4, +0.0, 1.0, +0.0, +0.0},
{vec4, Sin, +0.0, Cos, +0.0},
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 299).
?DOC(
" Creates an affine transformation matrix containing a 3D rotation around the z axis of\n"
" `angle` (in radians).\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_rotation_z(float()) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_rotation_z(Angle) ->
Sin = gleam_community@maths:sin(Angle),
Cos = gleam_community@maths:cos(Angle),
from_cols(
{vec4, Cos, Sin, +0.0, +0.0},
{vec4, +0.0 - Sin, Cos, +0.0, +0.0},
{vec4, +0.0, +0.0, 1.0, +0.0},
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 313).
?DOC(
" Creates an affine transformation matrix containing the given 3D non-uniform `scale`.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_scale(vec@vec3:vec3(float())) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_scale(Scale) ->
from_diagonal(matrix@internal@projection:extend3(Scale, 1.0)).
-file("src/matrix/mat4f.gleam", 318).
?DOC(" Inverts the `Mat4f`, returning an error if the matrix is not invertible.\n").
-spec inverse(vec@vec4:vec4(vec@vec4:vec4(float()))) -> {ok,
vec@vec4:vec4(vec@vec4:vec4(float()))} |
{error, nil}.
inverse(Mat) ->
{vec4,
{vec4, M00, M01, M02, M03},
{vec4, M10, M11, M12, M13},
{vec4, M20, M21, M22, M23},
{vec4, M30, M31, M32, M33}} = Mat,
Coef00 = (M22 * M33) - (M32 * M23),
Coef02 = (M12 * M33) - (M32 * M13),
Coef03 = (M12 * M23) - (M22 * M13),
Coef04 = (M21 * M33) - (M31 * M23),
Coef06 = (M11 * M33) - (M31 * M13),
Coef07 = (M11 * M23) - (M21 * M13),
Coef08 = (M21 * M32) - (M31 * M22),
Coef10 = (M11 * M32) - (M31 * M12),
Coef11 = (M11 * M22) - (M21 * M12),
Coef12 = (M20 * M33) - (M30 * M23),
Coef14 = (M10 * M33) - (M30 * M13),
Coef15 = (M10 * M23) - (M20 * M13),
Coef16 = (M20 * M32) - (M30 * M22),
Coef18 = (M10 * M32) - (M30 * M12),
Coef19 = (M10 * M22) - (M20 * M12),
Coef20 = (M20 * M31) - (M30 * M21),
Coef22 = (M10 * M31) - (M30 * M11),
Coef23 = (M10 * M21) - (M20 * M11),
Fac0 = {vec4, Coef00, Coef00, Coef02, Coef03},
Fac1 = {vec4, Coef04, Coef04, Coef06, Coef07},
Fac2 = {vec4, Coef08, Coef08, Coef10, Coef11},
Fac3 = {vec4, Coef12, Coef12, Coef14, Coef15},
Fac4 = {vec4, Coef16, Coef16, Coef18, Coef19},
Fac5 = {vec4, Coef20, Coef20, Coef22, Coef23},
Vec0 = {vec4, M10, M00, M00, M00},
Vec1 = {vec4, M11, M01, M01, M01},
Vec2 = {vec4, M12, M02, M02, M02},
Vec3 = {vec4, M13, M03, M03, M03},
Inv0 = begin
_pipe = Vec1,
_pipe@1 = vec@vec4f:multiply(_pipe, Fac0),
_pipe@3 = vec@vec4f:subtract(
_pipe@1,
begin
_pipe@2 = Vec2,
vec@vec4f:multiply(_pipe@2, Fac1)
end
),
vec@vec4f:add(
_pipe@3,
begin
_pipe@4 = Vec3,
vec@vec4f:multiply(_pipe@4, Fac2)
end
)
end,
Inv1 = begin
_pipe@5 = Vec0,
_pipe@6 = vec@vec4f:multiply(_pipe@5, Fac0),
_pipe@8 = vec@vec4f:subtract(
_pipe@6,
begin
_pipe@7 = Vec2,
vec@vec4f:multiply(_pipe@7, Fac3)
end
),
vec@vec4f:add(
_pipe@8,
begin
_pipe@9 = Vec3,
vec@vec4f:multiply(_pipe@9, Fac4)
end
)
end,
Inv2 = begin
_pipe@10 = Vec0,
_pipe@11 = vec@vec4f:multiply(_pipe@10, Fac1),
_pipe@13 = vec@vec4f:subtract(
_pipe@11,
begin
_pipe@12 = Vec1,
vec@vec4f:multiply(_pipe@12, Fac3)
end
),
vec@vec4f:add(
_pipe@13,
begin
_pipe@14 = Vec3,
vec@vec4f:multiply(_pipe@14, Fac5)
end
)
end,
Inv3 = begin
_pipe@15 = Vec0,
_pipe@16 = vec@vec4f:multiply(_pipe@15, Fac2),
_pipe@18 = vec@vec4f:subtract(
_pipe@16,
begin
_pipe@17 = Vec1,
vec@vec4f:multiply(_pipe@17, Fac4)
end
),
vec@vec4f:add(
_pipe@18,
begin
_pipe@19 = Vec2,
vec@vec4f:multiply(_pipe@19, Fac5)
end
)
end,
Sign_a = {vec4, 1.0, -1.0, 1.0, -1.0},
Sign_b = {vec4, -1.0, 1.0, -1.0, 1.0},
Inverse = from_cols(
begin
_pipe@20 = Inv0,
vec@vec4f:multiply(_pipe@20, Sign_a)
end,
begin
_pipe@21 = Inv1,
vec@vec4f:multiply(_pipe@21, Sign_b)
end,
begin
_pipe@22 = Inv2,
vec@vec4f:multiply(_pipe@22, Sign_a)
end,
begin
_pipe@23 = Inv3,
vec@vec4f:multiply(_pipe@23, Sign_b)
end
),
Col0 = {vec4,
erlang:element(2, erlang:element(2, Inverse)),
erlang:element(2, erlang:element(3, Inverse)),
erlang:element(2, erlang:element(4, Inverse)),
erlang:element(2, erlang:element(5, Inverse))},
Dot0 = begin
_pipe@24 = erlang:element(2, Mat),
vec@vec4f:multiply(_pipe@24, Col0)
end,
Dot1 = ((erlang:element(2, Dot0) + erlang:element(3, Dot0)) + erlang:element(
4,
Dot0
))
+ erlang:element(5, Dot0),
gleam@result:map(
gleam@float:divide(1.0, Dot1),
fun(_capture) -> scale(Inverse, _capture) end
).
-file("src/matrix/mat4f.gleam", 409).
?DOC(
" Creates a right-handed view matrix using a camera position, a facing direction, and an up\n"
" direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.\n"
).
-spec look_to_rh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
look_to_rh(Eye, Dir, Up) ->
F = Dir,
S = begin
_pipe = vec@vec3f:cross(F, Up),
vec@vec3f:normalize(_pipe)
end,
U = vec@vec3f:cross(S, F),
Neg_f = vec@vec3f:negate(F),
Neg_dot_s = gleam@float:negate(vec@vec3f:dot(Eye, S)),
Neg_dot_u = gleam@float:negate(vec@vec3f:dot(Eye, U)),
Dot_f = vec@vec3f:dot(Eye, F),
from_cols(
{vec4,
erlang:element(2, S),
erlang:element(2, U),
erlang:element(2, Neg_f),
+0.0},
{vec4,
erlang:element(3, S),
erlang:element(3, U),
erlang:element(3, Neg_f),
+0.0},
{vec4,
erlang:element(4, S),
erlang:element(4, U),
erlang:element(4, Neg_f),
+0.0},
{vec4, Neg_dot_s, Neg_dot_u, Dot_f, 1.0}
).
-file("src/matrix/mat4f.gleam", 401).
?DOC(
" Creates a left-handed view matrix using a camera position, a facing direction and an up\n"
" direction\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.\n"
).
-spec look_to_lh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
look_to_lh(Eye, Dir, Up) ->
look_to_rh(Eye, vec@vec3f:negate(Dir), Up).
-file("src/matrix/mat4f.gleam", 430).
?DOC(
" Creates a left-handed view matrix using a camera position, a focal points and an up\n"
" direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.\n"
).
-spec look_at_lh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
look_at_lh(Eye, Center, Up) ->
look_to_lh(
Eye,
begin
_pipe = Center,
_pipe@1 = vec@vec3f:subtract(_pipe, Eye),
vec@vec3f:normalize(_pipe@1)
end,
Up
).
-file("src/matrix/mat4f.gleam", 438).
?DOC(
" Creates a right-handed view matrix using a camera position, a focal point, and an up\n"
" direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.\n"
).
-spec look_at_rh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
look_at_rh(Eye, Center, Up) ->
look_to_rh(
Eye,
begin
_pipe = Center,
_pipe@1 = vec@vec3f:subtract(_pipe, Eye),
vec@vec3f:normalize(_pipe@1)
end,
Up
).
-file("src/matrix/mat4f.gleam", 448).
?DOC(
" Transforms the given 3D vector as a point.\n"
"\n"
" This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is\n"
" `1.0`.\n"
"\n"
" This function assumes that `mat` contains a valid affine transform.\n"
).
-spec transform_point3(
vec@vec4:vec4(vec@vec4:vec4(float())),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(float()).
transform_point3(Mat, Rhs) ->
_pipe = vec@vec4f:scale(erlang:element(2, Mat), erlang:element(2, Rhs)),
_pipe@1 = vec@vec4f:add(
_pipe,
vec@vec4f:scale(erlang:element(3, Mat), erlang:element(3, Rhs))
),
_pipe@2 = vec@vec4f:add(
_pipe@1,
vec@vec4f:scale(erlang:element(4, Mat), erlang:element(4, Rhs))
),
_pipe@3 = vec@vec4f:add(_pipe@2, erlang:element(5, Mat)),
matrix@internal@projection:to_xyz(_pipe@3).
-file("src/matrix/mat4f.gleam", 462).
?DOC(
" Transforms the given 3D vector as a direction.\n"
"\n"
" This is the equivalent of multiplying the 3D vector as a 4D vector where `w` is\n"
" `0.0`.\n"
"\n"
" This method assumes that `mat` contains a valid affine transform.\n"
).
-spec transform_vector3(
vec@vec4:vec4(vec@vec4:vec4(float())),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(float()).
transform_vector3(Mat, Rhs) ->
_pipe = vec@vec4f:scale(erlang:element(2, Mat), erlang:element(2, Rhs)),
_pipe@1 = vec@vec4f:add(
_pipe,
vec@vec4f:scale(erlang:element(3, Mat), erlang:element(3, Rhs))
),
_pipe@2 = vec@vec4f:add(
_pipe@1,
vec@vec4f:scale(erlang:element(4, Mat), erlang:element(4, Rhs))
),
matrix@internal@projection:to_xyz(_pipe@2).
-file("src/matrix/mat4f.gleam", 471).
-spec quat_to_axes(vec@vec4:vec4(float())) -> vec@vec3:vec3(vec@vec4:vec4(float())).
quat_to_axes(Rotation) ->
{vec4, X, Y, Z, W} = vec@vec4f:normalize(Rotation),
X2 = X + X,
Y2 = Y + Y,
Z2 = Z + Z,
Xx = X * X2,
Xy = X * Y2,
Xz = X * Z2,
Yy = Y * Y2,
Yz = Y * Z2,
Zz = Z * Z2,
Wx = W * X2,
Wy = Y * Y2,
Wz = W * Z2,
X_axis = {vec4, 1.0 - (Yy + Zz), Xy + Wz, Xz - Wy, +0.0},
Y_axis = {vec4, Xy - Wz, 1.0 - (Xx + Zz), Yz + Wx, +0.0},
Z_axis = {vec4, Xz + Wy, Yz - Wx, 1.0 - (Xx + Yy), +0.0},
{vec3, X_axis, Y_axis, Z_axis}.
-file("src/matrix/mat4f.gleam", 150).
?DOC(
" Creates an affine transformation matrix from the given 3D `scale`, `rotation` and\n"
" `translation`.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_scale_rotation_translation(
vec@vec3:vec3(float()),
vec@vec4:vec4(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_scale_rotation_translation(Scale, Rotation, Translation) ->
Axes = begin
_pipe = Rotation,
_pipe@1 = quat_to_axes(_pipe),
vec@vec3:map2(_pipe@1, Scale, fun vec@vec4f:scale/2)
end,
from_cols(
erlang:element(2, Axes),
erlang:element(3, Axes),
erlang:element(4, Axes),
matrix@internal@projection:extend3(Translation, 1.0)
).
-file("src/matrix/mat4f.gleam", 166).
?DOC(
" Creates an affine transformation matrix from the given 3D `translation`.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_rotation_translation(vec@vec4:vec4(float()), vec@vec3:vec3(float())) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_rotation_translation(Rotation, Translation) ->
from_scale_rotation_translation(
{vec3, 1.0, 1.0, 1.0},
Rotation,
Translation
).
-file("src/matrix/mat4f.gleam", 210).
?DOC(
" Creates an affine transformation matrix from the given `rotation` quaternion.\n"
"\n"
" The resulting matrix can be used to transform 3D points and vectors.\n"
).
-spec from_quaternion(vec@vec4:vec4(float())) -> vec@vec4:vec4(vec@vec4:vec4(float())).
from_quaternion(Q) ->
Rotation = quat_to_axes(Q),
from_cols(
erlang:element(2, Rotation),
erlang:element(3, Rotation),
erlang:element(4, Rotation),
{vec4, +0.0, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat4f.gleam", 493).
-spec quat_from_rotation_axes(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec4:vec4(float()).
quat_from_rotation_axes(X_axis, Y_axis, Z_axis) ->
{vec3, M00, M01, M02} = X_axis,
{vec3, M10, M11, M12} = Y_axis,
{vec3, M20, M21, M22} = Z_axis,
case M22 =< +0.0 of
true ->
Dif10 = M11 - M00,
Omm22 = 1.0 - M22,
case Dif10 =< +0.0 of
true ->
Four_xsq = Omm22 - Dif10,
Inv4x = begin
Four_x@1 = case gleam@float:square_root(Four_xsq) of
{ok, Four_x} -> Four_x;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"matrix/mat4f"/utf8>>,
function => <<"quat_from_rotation_axes"/utf8>>,
line => 512,
value => _assert_fail,
start => 15383,
'end' => 15434,
pattern_start => 15394,
pattern_end => 15404})
end,
case Four_x@1 of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> 0.5 / Gleam@denominator
end
end,
{vec4,
Four_xsq * Inv4x,
(M01 + M10) * Inv4x,
(M02 + M20) * Inv4x,
(M12 - M21) * Inv4x};
false ->
Four_ysq = Omm22 + Dif10,
Inv4y = begin
Four_y@1 = case gleam@float:square_root(Four_ysq) of
{ok, Four_y} -> Four_y;
_assert_fail@1 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"matrix/mat4f"/utf8>>,
function => <<"quat_from_rotation_axes"/utf8>>,
line => 526,
value => _assert_fail@1,
start => 15772,
'end' => 15823,
pattern_start => 15783,
pattern_end => 15793})
end,
case Four_y@1 of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> 0.5 / Gleam@denominator@1
end
end,
{vec4,
(M01 + M10) * Inv4y,
Four_ysq * Inv4y,
(M12 + M21) * Inv4y,
(M20 - M02) * Inv4y}
end;
false ->
Sum10 = M11 + M00,
Opm22 = 1.0 + M22,
case Sum10 =< +0.0 of
true ->
Four_zsq = Opm22 - Sum10,
Inv4z = begin
Four_z@1 = case gleam@float:square_root(Four_zsq) of
{ok, Four_z} -> Four_z;
_assert_fail@2 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"matrix/mat4f"/utf8>>,
function => <<"quat_from_rotation_axes"/utf8>>,
line => 547,
value => _assert_fail@2,
start => 16306,
'end' => 16357,
pattern_start => 16317,
pattern_end => 16327})
end,
case Four_z@1 of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@2 -> 0.5 / Gleam@denominator@2
end
end,
{vec4,
(M02 + M20) * Inv4z,
(M12 + M21) * Inv4z,
Four_zsq * Inv4z,
(M01 - M10) * Inv4z};
false ->
Four_wsq = Opm22 + Sum10,
Inv4w = begin
Four_w@1 = case gleam@float:square_root(Four_wsq) of
{ok, Four_w} -> Four_w;
_assert_fail@3 ->
erlang:error(#{gleam_error => let_assert,
message => <<"Pattern match failed, no pattern matched the value."/utf8>>,
file => <<?FILEPATH/utf8>>,
module => <<"matrix/mat4f"/utf8>>,
function => <<"quat_from_rotation_axes"/utf8>>,
line => 561,
value => _assert_fail@3,
start => 16695,
'end' => 16746,
pattern_start => 16706,
pattern_end => 16716})
end,
case Four_w@1 of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@3 -> 0.5 / Gleam@denominator@3
end
end,
{vec4,
(M12 - M21) * Inv4w,
(M20 - M02) * Inv4w,
(M01 - M10) * Inv4w,
Four_wsq * Inv4w}
end
end.
-file("src/matrix/mat4f.gleam", 175).
?DOC(
" Extracts `scale`, `rotation` and `translation` from `mat`. The input matrix is\n"
" expected to be a 3D affine transformation matrix otherwise the output will be invalid.\n"
"\n"
" Will return `Error(Nil)` if the determinant of `mat` is zero or if the resulting scale vector\n"
" contains any zero elements.\n"
).
-spec to_scale_rotation_translation(vec@vec4:vec4(vec@vec4:vec4(float()))) -> {ok,
{vec@vec3:vec3(float()), vec@vec4:vec4(float()), vec@vec3:vec3(float())}} |
{error, nil}.
to_scale_rotation_translation(Mat) ->
Det = determinant(Mat),
gleam@result:'try'(
gleam@float:divide(Det, gleam@float:absolute_value(Det)),
fun(Signum) ->
Scale = {vec3,
vec@vec4f:length(erlang:element(2, Mat)) * Signum,
vec@vec4f:length(erlang:element(3, Mat)),
vec@vec4f:length(erlang:element(4, Mat))},
gleam@bool:guard(
not vec@vec3f:loosely_equals(
Scale,
{vec3, +0.0, +0.0, +0.0},
0.0000001
),
{error, nil},
fun() ->
gleam@result:map(
begin
_pipe = Scale,
_pipe@1 = vec@vec3:map(
_pipe,
fun(_capture) ->
gleam@float:divide(1.0, _capture)
end
),
vec@vec3:result(_pipe@1)
end,
fun(Inv_scale) ->
Rotation = quat_from_rotation_axes(
begin
_pipe@2 = erlang:element(2, Mat),
_pipe@3 = vec@vec4f:scale(
_pipe@2,
erlang:element(2, Inv_scale)
),
matrix@internal@projection:to_xyz(_pipe@3)
end,
begin
_pipe@4 = erlang:element(3, Mat),
_pipe@5 = vec@vec4f:scale(
_pipe@4,
erlang:element(3, Inv_scale)
),
matrix@internal@projection:to_xyz(_pipe@5)
end,
begin
_pipe@6 = erlang:element(4, Mat),
_pipe@7 = vec@vec4f:scale(
_pipe@6,
erlang:element(4, Inv_scale)
),
matrix@internal@projection:to_xyz(_pipe@7)
end
),
{Scale,
Rotation,
matrix@internal@projection:to_xyz(
erlang:element(5, Mat)
)}
end
)
end
)
end
).