nv-sgl 0.6.0__cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. include/tevclient.h +393 -0
  2. nv_sgl-0.6.0.dist-info/LICENSE +29 -0
  3. nv_sgl-0.6.0.dist-info/METADATA +21 -0
  4. nv_sgl-0.6.0.dist-info/RECORD +133 -0
  5. nv_sgl-0.6.0.dist-info/WHEEL +6 -0
  6. nv_sgl-0.6.0.dist-info/top_level.txt +1 -0
  7. sgl/__init__.py +15 -0
  8. sgl/__init__.pyi +6738 -0
  9. sgl/include/sgl/app/app.h +113 -0
  10. sgl/include/sgl/core/bitmap.h +302 -0
  11. sgl/include/sgl/core/crypto.h +89 -0
  12. sgl/include/sgl/core/data_type.h +46 -0
  13. sgl/include/sgl/core/dds_file.h +103 -0
  14. sgl/include/sgl/core/enum.h +201 -0
  15. sgl/include/sgl/core/error.h +161 -0
  16. sgl/include/sgl/core/file_stream.h +77 -0
  17. sgl/include/sgl/core/file_system_watcher.h +141 -0
  18. sgl/include/sgl/core/format.h +36 -0
  19. sgl/include/sgl/core/fwd.h +90 -0
  20. sgl/include/sgl/core/hash.h +45 -0
  21. sgl/include/sgl/core/input.h +522 -0
  22. sgl/include/sgl/core/logger.h +214 -0
  23. sgl/include/sgl/core/macros.h +184 -0
  24. sgl/include/sgl/core/maths.h +45 -0
  25. sgl/include/sgl/core/memory_mapped_file.h +112 -0
  26. sgl/include/sgl/core/memory_mapped_file_stream.h +32 -0
  27. sgl/include/sgl/core/memory_stream.h +74 -0
  28. sgl/include/sgl/core/object.h +683 -0
  29. sgl/include/sgl/core/platform.h +239 -0
  30. sgl/include/sgl/core/plugin.h +331 -0
  31. sgl/include/sgl/core/resolver.h +39 -0
  32. sgl/include/sgl/core/short_vector.h +141 -0
  33. sgl/include/sgl/core/static_vector.h +111 -0
  34. sgl/include/sgl/core/stream.h +54 -0
  35. sgl/include/sgl/core/string.h +276 -0
  36. sgl/include/sgl/core/struct.h +360 -0
  37. sgl/include/sgl/core/thread.h +28 -0
  38. sgl/include/sgl/core/timer.h +52 -0
  39. sgl/include/sgl/core/traits.h +15 -0
  40. sgl/include/sgl/core/type_utils.h +19 -0
  41. sgl/include/sgl/core/window.h +177 -0
  42. sgl/include/sgl/device/agility_sdk.h +24 -0
  43. sgl/include/sgl/device/blit.h +88 -0
  44. sgl/include/sgl/device/buffer_cursor.h +162 -0
  45. sgl/include/sgl/device/command.h +539 -0
  46. sgl/include/sgl/device/cuda_api.h +766 -0
  47. sgl/include/sgl/device/cuda_interop.h +39 -0
  48. sgl/include/sgl/device/cuda_utils.h +107 -0
  49. sgl/include/sgl/device/cursor_utils.h +129 -0
  50. sgl/include/sgl/device/device.h +668 -0
  51. sgl/include/sgl/device/device_resource.h +37 -0
  52. sgl/include/sgl/device/fence.h +91 -0
  53. sgl/include/sgl/device/formats.h +330 -0
  54. sgl/include/sgl/device/framebuffer.h +85 -0
  55. sgl/include/sgl/device/fwd.h +164 -0
  56. sgl/include/sgl/device/helpers.h +20 -0
  57. sgl/include/sgl/device/hot_reload.h +75 -0
  58. sgl/include/sgl/device/input_layout.h +74 -0
  59. sgl/include/sgl/device/kernel.h +69 -0
  60. sgl/include/sgl/device/memory_heap.h +155 -0
  61. sgl/include/sgl/device/native_formats.h +342 -0
  62. sgl/include/sgl/device/native_handle.h +73 -0
  63. sgl/include/sgl/device/native_handle_traits.h +65 -0
  64. sgl/include/sgl/device/pipeline.h +138 -0
  65. sgl/include/sgl/device/print.h +45 -0
  66. sgl/include/sgl/device/python/cursor_utils.h +853 -0
  67. sgl/include/sgl/device/query.h +52 -0
  68. sgl/include/sgl/device/raytracing.h +84 -0
  69. sgl/include/sgl/device/reflection.h +1254 -0
  70. sgl/include/sgl/device/resource.h +705 -0
  71. sgl/include/sgl/device/sampler.h +57 -0
  72. sgl/include/sgl/device/shader.h +516 -0
  73. sgl/include/sgl/device/shader_cursor.h +85 -0
  74. sgl/include/sgl/device/shader_object.h +94 -0
  75. sgl/include/sgl/device/shader_offset.h +67 -0
  76. sgl/include/sgl/device/shared_handle.h +12 -0
  77. sgl/include/sgl/device/slang_utils.h +54 -0
  78. sgl/include/sgl/device/swapchain.h +74 -0
  79. sgl/include/sgl/device/types.h +782 -0
  80. sgl/include/sgl/math/colorspace.h +56 -0
  81. sgl/include/sgl/math/constants.h +7 -0
  82. sgl/include/sgl/math/float16.h +146 -0
  83. sgl/include/sgl/math/matrix.h +6 -0
  84. sgl/include/sgl/math/matrix_math.h +746 -0
  85. sgl/include/sgl/math/matrix_types.h +207 -0
  86. sgl/include/sgl/math/python/primitivetype.h +33 -0
  87. sgl/include/sgl/math/quaternion.h +6 -0
  88. sgl/include/sgl/math/quaternion_math.h +484 -0
  89. sgl/include/sgl/math/quaternion_types.h +83 -0
  90. sgl/include/sgl/math/ray.h +47 -0
  91. sgl/include/sgl/math/scalar_math.h +249 -0
  92. sgl/include/sgl/math/scalar_types.h +107 -0
  93. sgl/include/sgl/math/vector.h +6 -0
  94. sgl/include/sgl/math/vector_math.h +1796 -0
  95. sgl/include/sgl/math/vector_types.h +336 -0
  96. sgl/include/sgl/python/nanobind.h +489 -0
  97. sgl/include/sgl/python/py_doc.h +11600 -0
  98. sgl/include/sgl/python/sgl_ext_pch.h +8 -0
  99. sgl/include/sgl/sgl.h +21 -0
  100. sgl/include/sgl/sgl_pch.h +6 -0
  101. sgl/include/sgl/stl/bit.h +377 -0
  102. sgl/include/sgl/tests/testing.h +54 -0
  103. sgl/include/sgl/ui/fwd.h +34 -0
  104. sgl/include/sgl/ui/imgui_config.h +43 -0
  105. sgl/include/sgl/ui/ui.h +71 -0
  106. sgl/include/sgl/ui/widgets.h +918 -0
  107. sgl/include/sgl/utils/python/slangpy.h +366 -0
  108. sgl/include/sgl/utils/renderdoc.h +50 -0
  109. sgl/include/sgl/utils/slangpy.h +153 -0
  110. sgl/include/sgl/utils/tev.h +93 -0
  111. sgl/include/sgl/utils/texture_loader.h +106 -0
  112. sgl/libgfx.so +0 -0
  113. sgl/libsgl.so +0 -0
  114. sgl/libslang-glslang.so +0 -0
  115. sgl/libslang.so +0 -0
  116. sgl/libtevclient.a +0 -0
  117. sgl/math/__init__.pyi +5083 -0
  118. sgl/platform/__init__.pyi +102 -0
  119. sgl/renderdoc/__init__.pyi +51 -0
  120. sgl/sgl_ext.cpython-313-x86_64-linux-gnu.so +0 -0
  121. sgl/shaders/sgl/device/blit.slang +93 -0
  122. sgl/shaders/sgl/device/nvapi.slang +5 -0
  123. sgl/shaders/sgl/device/nvapi.slangh +7 -0
  124. sgl/shaders/sgl/device/print.slang +445 -0
  125. sgl/shaders/sgl/math/constants.slang +4 -0
  126. sgl/shaders/sgl/math/ray.slang +29 -0
  127. sgl/shaders/sgl/ui/imgui.slang +49 -0
  128. sgl/slangpy/__init__.pyi +268 -0
  129. sgl/tev/__init__.pyi +108 -0
  130. sgl/thread/__init__.pyi +4 -0
  131. sgl/ui/__init__.pyi +1118 -0
  132. share/cmake/tevclient/tevclient-config-release.cmake +19 -0
  133. share/cmake/tevclient/tevclient-config.cmake +103 -0
@@ -0,0 +1,746 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ // Most of this code is derived from the GLM library at https://github.com/g-truc/glm
4
+ // License: https://github.com/g-truc/glm/blob/master/copying.txt
5
+
6
+ #pragma once
7
+
8
+ #include "sgl/math/matrix_types.h"
9
+ #include "sgl/math/vector.h"
10
+ #include "sgl/math/quaternion.h"
11
+ #include "sgl/core/error.h"
12
+ #include "sgl/core/format.h"
13
+
14
+ namespace sgl::math {
15
+
16
+ // ----------------------------------------------------------------------------
17
+ // Binary operators (component-wise)
18
+ // ----------------------------------------------------------------------------
19
+
20
+ /// Binary * operator
21
+ template<typename T, int R, int C>
22
+ [[nodiscard]] matrix<T, R, C> operator*(const matrix<T, R, C>& lhs, const T& rhs)
23
+ {
24
+ matrix<T, R, C> result;
25
+ for (int r = 0; r < R; ++r)
26
+ for (int c = 0; c < C; ++c)
27
+ result[r][c] = lhs[r][c] * rhs;
28
+ return result;
29
+ }
30
+
31
+ // ----------------------------------------------------------------------------
32
+ // Multiplication
33
+ // ----------------------------------------------------------------------------
34
+
35
+ /// Multiply matrix and matrix.
36
+ template<typename T, int M, int N, int P>
37
+ [[nodiscard]] matrix<T, M, P> mul(const matrix<T, M, N>& lhs, const matrix<T, N, P>& rhs)
38
+ {
39
+ matrix<T, M, P> result;
40
+ for (int m = 0; m < M; ++m)
41
+ for (int p = 0; p < P; ++p)
42
+ result[m][p] = dot(lhs.get_row(m), rhs.get_col(p));
43
+ return result;
44
+ }
45
+ /// Multiply matrix and vector. Vector is treated as a column vector.
46
+ template<typename T, int R, int C>
47
+ [[nodiscard]] vector<T, R> mul(const matrix<T, R, C>& lhs, const vector<T, C>& rhs)
48
+ {
49
+ vector<T, R> result;
50
+ for (int r = 0; r < R; ++r)
51
+ result[r] = dot(lhs.get_row(r), rhs);
52
+ return result;
53
+ }
54
+
55
+ /// Multiply vector and matrix. Vector is treated as a row vector.
56
+ template<typename T, int R, int C>
57
+ [[nodiscard]] vector<T, C> mul(const vector<T, R>& lhs, const matrix<T, R, C>& rhs)
58
+ {
59
+ vector<T, C> result;
60
+ for (int c = 0; c < C; ++c)
61
+ result[c] = dot(lhs, rhs.get_col(c));
62
+ return result;
63
+ }
64
+
65
+ /// Transform a point by a 4x4 matrix. The point is treated as a column vector with a 1 in the 4th component.
66
+ template<typename T>
67
+ [[nodiscard]] vector<T, 3> transform_point(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
68
+ {
69
+ return mul(m, vector<T, 4>(v, T(1))).xyz();
70
+ }
71
+
72
+ /// Transform a vector by a 3x3 matrix.
73
+ template<typename T>
74
+ [[nodiscard]] vector<T, 3> transform_vector(const matrix<T, 3, 3>& m, const vector<T, 3>& v)
75
+ {
76
+ return mul(m, v);
77
+ }
78
+
79
+ /// Transform a vector by a 4x4 matrix. The vector is treated as a column vector with a 0 in the 4th component.
80
+ template<typename T>
81
+ [[nodiscard]] vector<T, 3> transform_vector(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
82
+ {
83
+ return mul(m, vector<T, 4>(v, T(0))).xyz();
84
+ }
85
+
86
+ // ----------------------------------------------------------------------------
87
+ // Functions
88
+ // ----------------------------------------------------------------------------
89
+
90
+ /// Transpose a matrix.
91
+ template<typename T, int R, int C>
92
+ matrix<T, C, R> transpose(const matrix<T, R, C>& m)
93
+ {
94
+ matrix<T, C, R> result;
95
+ for (int r = 0; r < R; ++r)
96
+ for (int c = 0; c < C; ++c)
97
+ result[c][r] = m[r][c];
98
+ return result;
99
+ }
100
+
101
+ /// Apply a translation to a 4x4 matrix.
102
+ template<typename T>
103
+ matrix<T, 4, 4> translate(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
104
+ {
105
+ matrix<T, 4, 4> result(m);
106
+ result.set_col(3, m.get_col(0) * v.x + m.get_col(1) * v.y + m.get_col(2) * v.z + m.get_col(3));
107
+ return result;
108
+ }
109
+
110
+ /// Apply a rotation around an axis to a 4x4 matrix.
111
+ template<typename T>
112
+ matrix<T, 4, 4> rotate(const matrix<T, 4, 4>& m, T angle, const vector<T, 3>& axis_)
113
+ {
114
+ T a = angle;
115
+ T c = cos(a);
116
+ T s = sin(a);
117
+
118
+ vector<T, 3> axis(normalize(axis_));
119
+ vector<T, 3> temp((T(1) - c) * axis);
120
+
121
+ matrix<T, 4, 4> rotate;
122
+ rotate[0][0] = c + temp[0] * axis[0];
123
+ rotate[0][1] = temp[1] * axis[0] - s * axis[2];
124
+ rotate[0][2] = temp[2] * axis[0] + s * axis[1];
125
+
126
+ rotate[1][0] = temp[0] * axis[1] + s * axis[2];
127
+ rotate[1][1] = c + temp[1] * axis[1];
128
+ rotate[1][2] = temp[2] * axis[1] - s * axis[0];
129
+
130
+ rotate[2][0] = temp[0] * axis[2] - s * axis[1];
131
+ rotate[2][1] = temp[1] * axis[2] + s * axis[0];
132
+ rotate[2][2] = c + temp[2] * axis[2];
133
+
134
+ matrix<T, 4, 4> result;
135
+ result.set_col(0, m.get_col(0) * rotate[0][0] + m.get_col(1) * rotate[1][0] + m.get_col(2) * rotate[2][0]);
136
+ result.set_col(1, m.get_col(0) * rotate[0][1] + m.get_col(1) * rotate[1][1] + m.get_col(2) * rotate[2][1]);
137
+ result.set_col(2, m.get_col(0) * rotate[0][2] + m.get_col(1) * rotate[1][2] + m.get_col(2) * rotate[2][2]);
138
+ result.set_col(3, m.get_col(3));
139
+
140
+ return result;
141
+ }
142
+
143
+ /// Apply a scale to a 4x4 matrix.
144
+ template<typename T>
145
+ matrix<T, 4, 4> scale(const matrix<T, 4, 4>& m, const vector<T, 3>& v)
146
+ {
147
+ matrix<T, 4, 4> result;
148
+ result.set_col(0, m.get_col(0) * v[0]);
149
+ result.set_col(1, m.get_col(1) * v[1]);
150
+ result.set_col(2, m.get_col(2) * v[2]);
151
+ result.set_col(3, m.get_col(3));
152
+ return result;
153
+ }
154
+
155
+ /// Compute determinant of a 2x2 matrix.
156
+ template<typename T>
157
+ [[nodiscard]] inline T determinant(const matrix<T, 2, 2>& m)
158
+ {
159
+ return m[0][0] * m[1][1] - m[1][0] * m[0][1];
160
+ }
161
+
162
+ /// Compute determinant of a 3x3 matrix.
163
+ template<typename T>
164
+ [[nodiscard]] inline T determinant(const matrix<T, 3, 3>& m)
165
+ {
166
+ T a = m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]);
167
+ T b = m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]);
168
+ T c = m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
169
+ return a - b + c;
170
+ }
171
+
172
+ /// Compute determinant of a 4x4 matrix.
173
+ template<typename T>
174
+ [[nodiscard]] inline T determinant(const matrix<T, 4, 4>& m)
175
+ {
176
+ T sub_factor_00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
177
+ T sub_factor_01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
178
+ T sub_factor_02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
179
+ T sub_factor_03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
180
+ T sub_factor_04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
181
+ T sub_factor_05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
182
+
183
+ vector<T, 4> detCof(
184
+ +(m[1][1] * sub_factor_00 - m[1][2] * sub_factor_01 + m[1][3] * sub_factor_02), //
185
+ -(m[1][0] * sub_factor_00 - m[1][2] * sub_factor_03 + m[1][3] * sub_factor_04), //
186
+ +(m[1][0] * sub_factor_01 - m[1][1] * sub_factor_03 + m[1][3] * sub_factor_05), //
187
+ -(m[1][0] * sub_factor_02 - m[1][1] * sub_factor_04 + m[1][2] * sub_factor_05) //
188
+ );
189
+
190
+ return m[0][0] * detCof[0] + m[0][1] * detCof[1] + m[0][2] * detCof[2] + m[0][3] * detCof[3];
191
+ }
192
+
193
+ /// Compute inverse of a 2x2 matrix.
194
+ template<typename T>
195
+ [[nodiscard]] inline matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m)
196
+ {
197
+ T one_over_det = T(1) / determinant(m);
198
+ return matrix<T, 2, 2>{
199
+ +m[1][1] * one_over_det,
200
+ -m[0][1] * one_over_det, // row 0
201
+ -m[1][0] * one_over_det,
202
+ +m[0][0] * one_over_det // row 1
203
+ };
204
+ }
205
+
206
+ /// Compute inverse of a 3x3 matrix.
207
+ template<typename T>
208
+ [[nodiscard]] inline matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m)
209
+ {
210
+ T one_over_det = T(1) / determinant(m);
211
+
212
+ matrix<T, 3, 3> result;
213
+ result[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) * one_over_det;
214
+ result[0][1] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) * one_over_det;
215
+ result[0][2] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) * one_over_det;
216
+ result[1][0] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * one_over_det;
217
+ result[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) * one_over_det;
218
+ result[1][2] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * one_over_det;
219
+ result[2][0] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) * one_over_det;
220
+ result[2][1] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * one_over_det;
221
+ result[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) * one_over_det;
222
+ return result;
223
+ }
224
+
225
+ /// Compute inverse of a 4x4 matrix.
226
+ template<typename T>
227
+ [[nodiscard]] inline matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m)
228
+ {
229
+ T c00 = m[2][2] * m[3][3] - m[2][3] * m[3][2];
230
+ T c02 = m[2][1] * m[3][3] - m[2][3] * m[3][1];
231
+ T c03 = m[2][1] * m[3][2] - m[2][2] * m[3][1];
232
+
233
+ T c04 = m[1][2] * m[3][3] - m[1][3] * m[3][2];
234
+ T c06 = m[1][1] * m[3][3] - m[1][3] * m[3][1];
235
+ T c07 = m[1][1] * m[3][2] - m[1][2] * m[3][1];
236
+
237
+ T c08 = m[1][2] * m[2][3] - m[1][3] * m[2][2];
238
+ T c10 = m[1][1] * m[2][3] - m[1][3] * m[2][1];
239
+ T c11 = m[1][1] * m[2][2] - m[1][2] * m[2][1];
240
+
241
+ T c12 = m[0][2] * m[3][3] - m[0][3] * m[3][2];
242
+ T c14 = m[0][1] * m[3][3] - m[0][3] * m[3][1];
243
+ T c15 = m[0][1] * m[3][2] - m[0][2] * m[3][1];
244
+
245
+ T c16 = m[0][2] * m[2][3] - m[0][3] * m[2][2];
246
+ T c18 = m[0][1] * m[2][3] - m[0][3] * m[2][1];
247
+ T c19 = m[0][1] * m[2][2] - m[0][2] * m[2][1];
248
+
249
+ T c20 = m[0][2] * m[1][3] - m[0][3] * m[1][2];
250
+ T c22 = m[0][1] * m[1][3] - m[0][3] * m[1][1];
251
+ T c23 = m[0][1] * m[1][2] - m[0][2] * m[1][1];
252
+
253
+ vector<T, 4> fac0(c00, c00, c02, c03);
254
+ vector<T, 4> fac1(c04, c04, c06, c07);
255
+ vector<T, 4> fac2(c08, c08, c10, c11);
256
+ vector<T, 4> fac3(c12, c12, c14, c15);
257
+ vector<T, 4> fac4(c16, c16, c18, c19);
258
+ vector<T, 4> fac5(c20, c20, c22, c23);
259
+
260
+ vector<T, 4> vec0(m[0][1], m[0][0], m[0][0], m[0][0]);
261
+ vector<T, 4> vec1(m[1][1], m[1][0], m[1][0], m[1][0]);
262
+ vector<T, 4> vec2(m[2][1], m[2][0], m[2][0], m[2][0]);
263
+ vector<T, 4> vec3(m[3][1], m[3][0], m[3][0], m[3][0]);
264
+
265
+ vector<T, 4> inv0(vec1 * fac0 - vec2 * fac1 + vec3 * fac2);
266
+ vector<T, 4> inv1(vec0 * fac0 - vec2 * fac3 + vec3 * fac4);
267
+ vector<T, 4> inv2(vec0 * fac1 - vec1 * fac3 + vec3 * fac5);
268
+ vector<T, 4> inv3(vec0 * fac2 - vec1 * fac4 + vec2 * fac5);
269
+
270
+ vector<T, 4> sign_a(+1, -1, +1, -1);
271
+ vector<T, 4> sign_b(-1, +1, -1, +1);
272
+ matrix<T, 4, 4> inverse = matrix_from_columns(inv0 * sign_a, inv1 * sign_b, inv2 * sign_a, inv3 * sign_b);
273
+
274
+ vector<T, 4> row0(inverse[0][0], inverse[0][1], inverse[0][2], inverse[0][3]);
275
+
276
+ vector<T, 4> dot0(m.get_col(0) * row0);
277
+ T dot1 = (dot0.x + dot0.y) + (dot0.z + dot0.w);
278
+
279
+ T one_over_det = T(1) / dot1;
280
+
281
+ return inverse * one_over_det;
282
+ }
283
+
284
+ /// Compute the (X * Y * Z) euler angles of a 4x4 matrix.
285
+ template<typename T>
286
+ void extract_euler_angle_xyz(const matrix<T, 4, 4>& m, float& angle_x, float& angle_y, float& angle_z)
287
+ {
288
+ T t1 = atan2(m[1][2], m[2][2]);
289
+ T c2 = sqrt(m[0][0] * m[0][0] + m[0][1] * m[0][1]);
290
+ T t2 = atan2(-m[0][2], c2);
291
+ T s1 = sin(t1);
292
+ T c1 = cos(t1);
293
+ T t3 = atan2(s1 * m[2][0] - c1 * m[1][0], c1 * m[1][1] - s1 * m[2][1]);
294
+ angle_x = -t1;
295
+ angle_y = -t2;
296
+ angle_z = -t3;
297
+ }
298
+
299
+ /// Decomposes a model matrix into translation, rotation and scale components.
300
+ template<typename T>
301
+ inline bool decompose(
302
+ const matrix<T, 4, 4>& model_matrix,
303
+ vector<T, 3>& scale,
304
+ quat<T>& orientation,
305
+ vector<T, 3>& translation,
306
+ vector<T, 3>& skew,
307
+ vector<T, 4>& perspective
308
+ )
309
+ {
310
+ // See https://caff.de/posts/4X4-matrix-decomposition/decomposition.pdf
311
+
312
+ const T eps = std::numeric_limits<T>::epsilon();
313
+
314
+ matrix<T, 4, 4> local_matrix(model_matrix);
315
+
316
+ // Abort if zero matrix.
317
+ if (abs(local_matrix[3][3]) < eps)
318
+ return false;
319
+
320
+ // Normalize the matrix.
321
+ for (int i = 0; i < 4; ++i)
322
+ for (int j = 0; j < 4; ++j)
323
+ local_matrix[i][j] /= local_matrix[3][3];
324
+
325
+ // perspective_matrix is used to solve for perspective, but it also provides
326
+ // an easy way to test for singularity of the upper 3x3 component.
327
+ matrix<T, 4, 4> perspective_matrix(local_matrix);
328
+ perspective_matrix[3] = vector<T, 4>(0, 0, 0, 1);
329
+ if (abs(determinant(perspective_matrix)) < eps)
330
+ return false;
331
+
332
+ // First, isolate perspective. This is the messiest.
333
+ if (abs(local_matrix[3][0]) >= eps || abs(local_matrix[3][1]) >= eps || abs(local_matrix[3][2]) >= eps) {
334
+ // right_hand_side is the right hand side of the equation.
335
+ vector<T, 4> right_hand_side = local_matrix[3];
336
+
337
+ // Solve the equation by inverting perspective_matrix and multiplying
338
+ // right_hand_side by the inverse.
339
+ // (This is the easiest way, not necessarily the best.)
340
+ matrix<T, 4, 4> inverse_perspective_matrix = inverse(perspective_matrix);
341
+ matrix<T, 4, 4> transposed_inverse_perspective_matrix = transpose(inverse_perspective_matrix);
342
+
343
+ perspective = mul(transposed_inverse_perspective_matrix, right_hand_side);
344
+
345
+ // Clear the perspective partition.
346
+ local_matrix[3] = vector<T, 4>(0, 0, 0, 1);
347
+ } else {
348
+ // No perspective.
349
+ perspective = vector<T, 4>(0, 0, 0, 1);
350
+ }
351
+
352
+ // Next take care of translation (easy).
353
+ translation = local_matrix.get_col(3).xyz();
354
+ local_matrix.set_row(3, vector<T, 4>(0, 0, 0, 1));
355
+
356
+ vector<T, 3> row[3];
357
+
358
+ // Now get scale and shear.
359
+ for (int i = 0; i < 3; ++i)
360
+ for (int j = 0; j < 3; ++j)
361
+ row[i][j] = local_matrix[j][i];
362
+
363
+ // Compute X scale factor and normalize first row.
364
+ scale.x = length(row[0]);
365
+ row[0] = normalize(row[0]);
366
+
367
+ // Compute XY shear factor and make 2nd row orthogonal to 1st.
368
+ skew.z = dot(row[0], row[1]);
369
+ row[1] = row[1] - skew.z * row[0];
370
+
371
+ // Now, compute Y scale and normalize 2nd row.
372
+ scale.y = length(row[1]);
373
+ row[1] = normalize(row[1]);
374
+ skew.z /= scale.y;
375
+
376
+ // Compute XZ and YZ shears, orthogonalize 3rd row.
377
+ skew.y = dot(row[0], row[2]);
378
+ row[2] = row[2] - skew.y * row[0];
379
+ skew.x = dot(row[1], row[2]);
380
+ row[2] = row[2] - skew.x * row[1];
381
+
382
+ // Next, get Z scale and normalize 3rd row.
383
+ scale.z = length(row[2]);
384
+ row[2] = normalize(row[2]);
385
+ skew.y /= scale.z;
386
+ skew.x /= scale.z;
387
+
388
+ // At this point, the matrix (in rows[]) is orthonormal.
389
+ // Check for a coordinate system flip. If the determinant
390
+ // is -1, then negate the matrix and the scaling factors.
391
+ if (dot(row[0], cross(row[1], row[2])) < T(0)) {
392
+ scale *= T(-1);
393
+ for (int i = 0; i < 3; i++)
394
+ row[i] *= T(-1);
395
+ }
396
+
397
+ // Now, get the rotations out, as described in the gem.
398
+ int i, j, k = 0;
399
+ T root, trace = row[0].x + row[1].y + row[2].z;
400
+ if (trace > T(0)) {
401
+ root = sqrt(trace + T(1));
402
+ orientation.w = T(0.5) * root;
403
+ root = T(0.5) / root;
404
+ orientation.x = root * (row[1].z - row[2].y);
405
+ orientation.y = root * (row[2].x - row[0].z);
406
+ orientation.z = root * (row[0].y - row[1].x);
407
+ } // end if > 0
408
+ else {
409
+ static int next[3] = {1, 2, 0};
410
+ i = 0;
411
+ if (row[1].y > row[0].x)
412
+ i = 1;
413
+ if (row[2].z > row[i][i])
414
+ i = 2;
415
+ j = next[i];
416
+ k = next[j];
417
+
418
+ root = sqrt(row[i][i] - row[j][j] - row[k][k] + T(1));
419
+
420
+ orientation[i] = T(0.5) * root;
421
+ root = T(0.5) / root;
422
+ orientation[j] = root * (row[i][j] + row[j][i]);
423
+ orientation[k] = root * (row[i][k] + row[k][i]);
424
+ orientation.w = root * (row[j][k] - row[k][j]);
425
+ } // end if <= 0
426
+
427
+ return true;
428
+ }
429
+
430
+ // ----------------------------------------------------------------------------
431
+ // Construction
432
+ // ----------------------------------------------------------------------------
433
+
434
+ /// Creates a matrix from coefficients in row-major order.
435
+ template<typename T, int R, int C>
436
+ [[nodiscard]] inline matrix<T, R, C> matrix_from_coefficients(const T* coeffs)
437
+ {
438
+ matrix<T, R, C> m;
439
+ std::memcpy(&m, coeffs, sizeof(T) * R * C);
440
+ return m;
441
+ }
442
+
443
+ /// Creates a matrix from column vectors.
444
+ template<typename T, int R>
445
+ [[nodiscard]] inline matrix<T, R, 1> matrix_from_columns(const vector<T, R>& col0)
446
+ {
447
+ matrix<T, R, 1> m;
448
+ m.set_col(0, col0);
449
+ return m;
450
+ }
451
+
452
+ /// Creates a matrix from column vectors.
453
+ template<typename T, int R>
454
+ [[nodiscard]] inline matrix<T, R, 2> matrix_from_columns(const vector<T, R>& col0, const vector<T, R>& col1)
455
+ {
456
+ matrix<T, R, 2> m;
457
+ m.set_col(0, col0);
458
+ m.set_col(1, col1);
459
+ return m;
460
+ }
461
+
462
+ /// Creates a matrix from column vectors.
463
+ template<typename T, int R>
464
+ [[nodiscard]] inline matrix<T, R, 3>
465
+ matrix_from_columns(const vector<T, R>& col0, const vector<T, R>& col1, const vector<T, R>& col2)
466
+ {
467
+ matrix<T, R, 3> m;
468
+ m.set_col(0, col0);
469
+ m.set_col(1, col1);
470
+ m.set_col(2, col2);
471
+ return m;
472
+ }
473
+
474
+ /// Creates a matrix from column vectors.
475
+ template<typename T, int R>
476
+ [[nodiscard]] inline matrix<T, R, 4> matrix_from_columns(
477
+ const vector<T, R>& col0,
478
+ const vector<T, R>& col1,
479
+ const vector<T, R>& col2,
480
+ const vector<T, R>& col3
481
+ )
482
+ {
483
+ matrix<T, R, 4> m;
484
+ m.set_col(0, col0);
485
+ m.set_col(1, col1);
486
+ m.set_col(2, col2);
487
+ m.set_col(3, col3);
488
+ return m;
489
+ }
490
+
491
+ /// Creates a square matrix from a diagonal vector.
492
+ template<typename T, int N>
493
+ [[nodiscard]] inline matrix<T, N, N> matrix_from_diagonal(const vector<T, N>& diag)
494
+ {
495
+ matrix<T, N, N> m = matrix<T, N, N>::zeros();
496
+ for (int i = 0; i < N; i++)
497
+ m[i][i] = diag[i];
498
+ return m;
499
+ }
500
+
501
+ /// Creates a right-handed perspective projection matrix. Depth is mapped to [0, 1].
502
+ template<floating_point T>
503
+ [[nodiscard]] inline matrix<T, 4, 4> perspective(T fovy, T aspect, T z_near, T z_far)
504
+ {
505
+ SGL_ASSERT(abs(aspect - std::numeric_limits<T>::epsilon()) > T(0));
506
+
507
+ T tan_half_fovy = tan(fovy / T(2));
508
+
509
+ matrix<T, 4, 4> m = matrix<T, 4, 4>::zeros();
510
+ m[0][0] = T(1) / (aspect * tan_half_fovy);
511
+ m[1][1] = T(1) / (tan_half_fovy);
512
+ m[2][2] = z_far / (z_near - z_far);
513
+ m[3][2] = -T(1);
514
+ m[2][3] = -(z_far * z_near) / (z_far - z_near);
515
+ return m;
516
+ }
517
+
518
+ /// Creates a right-handed orthographic projection matrix. Depth is mapped to [0, 1].
519
+ template<floating_point T>
520
+ [[nodiscard]] inline matrix<T, 4, 4> ortho(T left, T right, T bottom, T top, T z_near, T z_far)
521
+ {
522
+ matrix<T, 4, 4> m = matrix<T, 4, 4>::identity();
523
+ m[0][0] = T(2) / (right - left);
524
+ m[1][1] = T(2) / (top - bottom);
525
+ m[2][2] = -T(1) / (z_far - z_near);
526
+ m[0][3] = -(right + left) / (right - left);
527
+ m[1][3] = -(top + bottom) / (top - bottom);
528
+ m[2][3] = -z_near / (z_far - z_near);
529
+ return m;
530
+ }
531
+
532
+ /// Creates a translation matrix.
533
+ template<floating_point T>
534
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_translation(const vector<T, 3>& v)
535
+ {
536
+ return translate(matrix<T, 4, 4>::identity(), v);
537
+ }
538
+
539
+ /// Creates a rotation matrix from an angle and an axis.
540
+ template<floating_point T>
541
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation(T angle, const vector<T, 3>& axis)
542
+ {
543
+ return rotate(matrix<T, 4, 4>::identity(), angle, axis);
544
+ }
545
+
546
+ /// Creates a rotation matrix around the X-axis.
547
+ template<floating_point T>
548
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation_x(T angle)
549
+ {
550
+ T c = cos(angle);
551
+ T s = sin(angle);
552
+
553
+ // clang-format off
554
+ return matrix<T, 4, 4>{
555
+ T(1), T(0), T(0), T(0), // row 0
556
+ T(0), c, -s, T(0), // row 1
557
+ T(0), s, c, T(0), // row 2
558
+ T(0), T(0), T(0), T(1) // row 3
559
+ };
560
+ // clang-format on
561
+ }
562
+
563
+ /// Creates a rotation matrix around the Y-axis.
564
+ template<floating_point T>
565
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation_y(T angle)
566
+ {
567
+ T c = cos(angle);
568
+ T s = sin(angle);
569
+
570
+ // clang-format off
571
+ return matrix<T, 4, 4>{
572
+ c, T(0), s, T(0), // row 0
573
+ T(0), T(1), T(0), T(0), // row 1
574
+ -s, T(0), c, T(0), // row 2
575
+ T(0), T(0), T(0), T(1) // row 3
576
+ };
577
+ // clang-format on
578
+ }
579
+
580
+ /// Creates a rotation matrix around the Z-axis.
581
+ template<floating_point T>
582
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation_z(T angle)
583
+ {
584
+ T c = cos(angle);
585
+ T s = sin(angle);
586
+
587
+ // clang-format off
588
+ return matrix<T, 4, 4>{
589
+ c, -s, T(0), T(0), // row 0
590
+ s, c, T(0), T(0), // row 1
591
+ T(0), T(0), T(1), T(0), // row 2
592
+ T(0), T(0), T(0), T(1) // row 3
593
+ };
594
+ // clang-format on
595
+ }
596
+
597
+ /// Creates a rotation matrix (X * Y * Z).
598
+ template<floating_point T>
599
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation_xyz(T angle_x, T angle_y, T angle_z)
600
+ {
601
+ T c1 = cos(-angle_x);
602
+ T c2 = cos(-angle_y);
603
+ T c3 = cos(-angle_z);
604
+ T s1 = sin(-angle_x);
605
+ T s2 = sin(-angle_y);
606
+ T s3 = sin(-angle_z);
607
+
608
+ matrix<T, 4, 4> m;
609
+ m[0][0] = c2 * c3;
610
+ m[0][1] = c2 * s3;
611
+ m[0][2] = -s2;
612
+ m[0][3] = T(0);
613
+
614
+ m[1][0] = -c1 * s3 + s1 * s2 * c3;
615
+ m[1][1] = c1 * c3 + s1 * s2 * s3;
616
+ m[1][2] = s1 * c2;
617
+ m[1][3] = T(0);
618
+
619
+ m[2][0] = s1 * s3 + c1 * s2 * c3;
620
+ m[2][1] = -s1 * c3 + c1 * s2 * s3;
621
+ m[2][2] = c1 * c2;
622
+ m[2][3] = T(0);
623
+
624
+ m[3][0] = T(0);
625
+ m[3][1] = T(0);
626
+ m[3][2] = T(0);
627
+ m[3][3] = T(1);
628
+
629
+ return m;
630
+ }
631
+
632
+ template<floating_point T>
633
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_rotation_xyz(const vector<T, 3>& angles)
634
+ {
635
+ return matrix_from_rotation_xyz(angles.x, angles.y, angles.z);
636
+ }
637
+
638
+ /// Creates a scaling matrix.
639
+ template<floating_point T>
640
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_scaling(const vector<T, 3>& v)
641
+ {
642
+ return scale(matrix<T, 4, 4>::identity(), v);
643
+ }
644
+
645
+ /**
646
+ * Build a look-at matrix.
647
+ * If right handed, forward direction is mapped onto -Z axis.
648
+ * If left handed, forward direction is mapped onto +Z axis.
649
+ * \param eye Eye position
650
+ * \param center Center position
651
+ * \param up Up vector
652
+ * \param handedness Coordinate system handedness.
653
+ */
654
+ template<floating_point T>
655
+ [[nodiscard]] inline matrix<T, 4, 4> matrix_from_look_at(
656
+ const vector<T, 3>& eye,
657
+ const vector<T, 3>& center,
658
+ const vector<T, 3>& up,
659
+ Handedness handedness = Handedness::right_handed
660
+ )
661
+ {
662
+ vector<T, 3> f(handedness == Handedness::right_handed ? normalize(eye - center) : normalize(center - eye));
663
+ vector<T, 3> r(normalize(cross(up, f)));
664
+ vector<T, 3> u(cross(f, r));
665
+
666
+ matrix<T, 4, 4> result = matrix<T, 4, 4>::identity();
667
+ result[0][0] = r.x;
668
+ result[0][1] = r.y;
669
+ result[0][2] = r.z;
670
+ result[1][0] = u.x;
671
+ result[1][1] = u.y;
672
+ result[1][2] = u.z;
673
+ result[2][0] = f.x;
674
+ result[2][1] = f.y;
675
+ result[2][2] = f.z;
676
+ result[0][3] = -dot(r, eye);
677
+ result[1][3] = -dot(u, eye);
678
+ result[2][3] = -dot(f, eye);
679
+
680
+ return result;
681
+ }
682
+
683
+ template<floating_point T>
684
+ [[nodiscard]] inline matrix<T, 3, 3> matrix_from_quat(const quat<T>& q)
685
+ {
686
+ matrix<T, 3, 3> m;
687
+ T qxx(q.x * q.x);
688
+ T qyy(q.y * q.y);
689
+ T qzz(q.z * q.z);
690
+ T qxz(q.x * q.z);
691
+ T qxy(q.x * q.y);
692
+ T qyz(q.y * q.z);
693
+ T qwx(q.w * q.x);
694
+ T qwy(q.w * q.y);
695
+ T qwz(q.w * q.z);
696
+
697
+ m[0][0] = T(1) - T(2) * (qyy + qzz);
698
+ m[0][1] = T(2) * (qxy - qwz);
699
+ m[0][2] = T(2) * (qxz + qwy);
700
+
701
+ m[1][0] = T(2) * (qxy + qwz);
702
+ m[1][1] = T(1) - T(2) * (qxx + qzz);
703
+ m[1][2] = T(2) * (qyz - qwx);
704
+
705
+ m[2][0] = T(2) * (qxz - qwy);
706
+ m[2][1] = T(2) * (qyz + qwx);
707
+ m[2][2] = T(1) - T(2) * (qxx + qyy);
708
+
709
+ return m;
710
+ }
711
+
712
+ template<typename T, int R, int C>
713
+ [[nodiscard]] std::string to_string(const matrix<T, R, C>& m)
714
+ {
715
+ return ::fmt::format("{}", m);
716
+ }
717
+
718
+ template<int R, int C, typename T>
719
+ bool lex_lt(const matrix<T, R, C>& lhs, const matrix<T, R, C>& rhs)
720
+ {
721
+ for (int r = 0; r < R; ++r) {
722
+ for (int c = 0; c < C; ++c) {
723
+ if (lhs[r][c] != rhs[r][c])
724
+ return lhs[r][c] < rhs[r][c];
725
+ }
726
+ }
727
+ return false;
728
+ }
729
+ } // namespace sgl::math
730
+
731
+ template<typename T, int R, int C>
732
+ struct fmt::formatter<sgl::math::matrix<T, R, C>> : formatter<typename sgl::math::matrix<T, R, C>::row_type> {
733
+ using row_type = typename sgl::math::matrix<T, R, C>::row_type;
734
+
735
+ template<typename FormatContext>
736
+ auto format(const sgl::math::matrix<T, R, C>& matrix, FormatContext& ctx) const
737
+ {
738
+ auto out = ctx.out();
739
+ for (int r = 0; r < R; ++r) {
740
+ out = ::fmt::format_to(out, "{}", (r == 0) ? "{" : ", ");
741
+ out = formatter<row_type>::format(matrix.get_row(r), ctx);
742
+ }
743
+ out = fmt::format_to(out, "}}");
744
+ return out;
745
+ }
746
+ };