Overte C++ Documentation
Mat4.h
1 //
2 // Mat4.h
3 // libraries/script-engine/src
4 //
5 // Created by Anthony Thibault on 3/7/16.
6 // Copyright 2016 High Fidelity, Inc.
7 // Copyright 2023 Overte e.V.
8 //
9 // Scriptable 4x4 Matrix class library.
10 //
11 // Distributed under the Apache License, Version 2.0.
12 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
13 // SPDX-License-Identifier: Apache-2.0
14 //
15 
18 
19 #ifndef hifi_Mat4_h
20 #define hifi_Mat4_h
21 
22 #include <QObject>
23 #include <QString>
24 #include <QVector>
25 #include <glm/glm.hpp>
26 #include "RegisteredMetaTypes.h"
27 #include "Scriptable.h"
28 
29 /*@jsdoc
30  * The <code>Mat4</code> API provides facilities for generating and using 4 x 4 matrices. These matrices are typically used to
31  * represent transforms (scale, rotate, and translate) that convert one coordinate system into another, or perspective
32  * transforms that convert 3D points into screen coordinates.
33  *
34  * @namespace Mat4
35  * @variation 0
36  *
37  * @hifi-interface
38  * @hifi-client-entity
39  * @hifi-avatar
40  * @hifi-server-entity
41  * @hifi-assignment-client
42  */
44 class Mat4 : public QObject, protected Scriptable {
45  Q_OBJECT
46 
47 public slots:
48 
49  /*@jsdoc
50  * Multiplies two matrices.
51  * @function Mat4(0).multiply
52  * @param {Mat4} m1 - The first matrix.
53  * @param {Mat4} m2 - The second matrix.
54  * @returns {Mat4} <code>m1</code> multiplied with <code>m2</code>.
55  */
56  glm::mat4 multiply(const glm::mat4& m1, const glm::mat4& m2) const;
57 
58 
59  /*@jsdoc
60  * Creates a matrix that represents a rotation and translation.
61  * @function Mat4(0).createFromRotAndTrans
62  * @param {Quat} rot - The rotation.
63  * @param {Vec3} trans - The translation.
64  * @returns {Mat4} The matrix that represents the rotation and translation.
65  * @example <caption>Create a matrix with rotation and translation.</caption>
66  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
67  * var trans = { x: 10, y: 11, z: 12 };
68  * var matrix = Mat4.createFromRotAndTrans(rot, trans);
69  * Mat4.print("Matrix:", matrix);
70  * // Matrix: dmat4x4((0.353553, 0.612372, -0.707107, 0.000000),
71  * // (-0.573223, 0.739199, 0.353553, 0.000000),
72  * // (0.739199, 0.280330, 0.612372, 0.000000),
73  * // (10.000000, 11.000000, 12.000000, 1.000000))
74  */
75  glm::mat4 createFromRotAndTrans(const glm::quat& rot, const glm::vec3& trans) const;
76 
77  /*@jsdoc
78  * Creates a matrix that represents a scale, rotation, and translation.
79  * @function Mat4(0).createFromScaleRotAndTrans
80  * @param {Vec3} scale - The scale.
81  * @param {Quat} rot - The rotation.
82  * @param {Vec3} trans - The translation.
83  * @returns {Mat4} The matrix that represents the scale, rotation, and translation.
84  * @example <caption>Create a matrix with scale, rotation, and translation.</caption>
85  * var scale = Vec3.multiply(2, Vec3.ONE);
86  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
87  * var trans = { x: 10, y: 11, z: 12 };
88  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
89  * Mat4.print("Matrix:", matrix);
90  * // Matrix: dmat4x4((0.707107, 1.224745, -1.414214, 0.000000),
91  * // (-1.146447, 1.478398, 0.707107, 0.000000),
92  * // (1.478398, 0.560660, 1.224745, 0.000000),
93  * // (10.000000, 11.000000, 12.000000, 1.000000))
94  */
95  glm::mat4 createFromScaleRotAndTrans(const glm::vec3& scale, const glm::quat& rot, const glm::vec3& trans) const;
96 
97  /*@jsdoc
98  * Creates a matrix from columns of values.
99  * @function Mat4(0).createFromColumns
100  * @param {Vec4} col0 - Column 0 values.
101  * @param {Vec4} col1 - Column 1 values.
102  * @param {Vec4} col2 - Column 2 values.
103  * @param {Vec4} col3 - Column 3 valuse.
104  * @returns {Mat4} The matrix with the specified columns values.
105  * @example <caption>Create a matrix from columns.</caption>
106  * var col0 = { x: 0.707107, y: 1.224745, z: -1.414214, w: 0.0 };
107  * var col1 = { x: -1.146447, y: 1.478398, z: 0.707107, w: 0.0 };
108  * var col2 = { x: 1.478398, y: 0.560660, z: 1.224745, w: 0.0 };
109  * var col3 = { x: 10.0, y: 11.0, z: 12.0, w: 1.0 };
110  * var matrix = Mat4.createFromColumns(col0, col1, col2, col3);
111  * Mat4.print("Matrix:", matrix);
112  * //Matrix: dmat4x4((0.707107, 1.224745, -1.414214, 0.000000),
113  * // (-1.146447, 1.478398, 0.707107, 0.000000),
114  * // (1.478398, 0.560660, 1.224745, 0.000000),
115  * // (10.000000, 11.000000, 12.000000, 1.000000))
116  */
117  glm::mat4 createFromColumns(const glm::vec4& col0, const glm::vec4& col1, const glm::vec4& col2, const glm::vec4& col3) const;
118 
119  /*@jsdoc
120  * Creates a matrix from an array of values.
121  * @function Mat4(0).createFromArray
122  * @param {number[]} arr - The array of values, starting with column 0.
123  * @returns {Mat4} The matrix with the specified values.
124  * @example <caption>Create a matrix from an array.</caption>
125  * var arr = [
126  * 0.707107, 1.224745, -1.414214, 0.0,
127  * -1.146447, 1.478398, 0.707107, 0.0,
128  * 1.478398, 0.560660, 1.224745, 0.0,
129  * 10.0, 11.0, 12.0, 1.00
130  * ];
131  * var matrix = Mat4.createFromArray(arr);
132  * Mat4.print("Matrix:", matrix);
133  * //Matrix: dmat4x4((0.707107, 1.224745, -1.414214, 0.000000),
134  * // (-1.146447, 1.478398, 0.707107, 0.000000),
135  * // (1.478398, 0.560660, 1.224745, 0.000000),
136  * // (10.000000, 11.000000, 12.000000, 1.000000))
137  */
138  glm::mat4 createFromArray(const QVector<float>& floats) const;
139 
140 
141  /*@jsdoc
142  * Extracts the translation from a matrix.
143  * @function Mat4(0).extractTranslation
144  * @param {Mat4} m - The matrix.
145  * @returns {Vec3} The translation contained in the matrix.
146  * @example <caption>Extract the translation from a matrix.</caption>
147  * var scale = Vec3.multiply(2, Vec3.ONE);
148  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
149  * var trans = { x: 10, y: 11, z: 12 };
150  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
151  *
152  * trans = Mat4.extractTranslation(matrix);
153  * print("Translation: " + JSON.stringify(trans));
154  * // Translation: {"x":10,"y":11,"z":12}
155  */
156  glm::vec3 extractTranslation(const glm::mat4& m) const;
157 
158  /*@jsdoc
159  * Extracts the rotation from a matrix.
160  * @function Mat4(0).extractRotation
161  * @param {Mat4} m - The matrix.
162  * @returns {Quat} The rotation contained in the matrix.
163  * @example <caption>Extract the rotation from a matrix.</caption>
164  * var scale = Vec3.multiply(2, Vec3.ONE);
165  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
166  * var trans = { x: 10, y: 11, z: 12 };
167  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
168  *
169  * rot = Mat4.extractRotation(matrix);
170  * print("Rotation: " + JSON.stringify(Quat.safeEulerAngles(rot)));
171  * // Rotation: {"x":29.999998092651367,"y":45.00000762939453,"z":60.000003814697266}
172  */
173  glm::quat extractRotation(const glm::mat4& m) const;
174 
175  /*@jsdoc
176  * Extracts the scale from a matrix.
177  * @function Mat4(0).extractScale
178  * @param {Mat4} m - The matrix.
179  * @returns {Vec3} The scale contained in the matrix.
180  * @example <caption>Extract the scale from a matrix.</caption>
181  * var scale = Vec3.multiply(2, Vec3.ONE);
182  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
183  * var trans = { x: 10, y: 11, z: 12 };
184  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
185  *
186  * scale = Mat4.extractScale(matrix);
187  * print("Scale: " + JSON.stringify(scale));
188  * // Scale: {"x":1.9999998807907104,"y":1.9999998807907104,"z":1.9999998807907104}
189  */
190  glm::vec3 extractScale(const glm::mat4& m) const;
191 
192 
193  /*@jsdoc
194  * Transforms a point into a new coordinate system: the point value is scaled, rotated, and translated.
195  * @function Mat4(0).transformPoint
196  * @param {Mat4} m - The transform to the new coordinate system.
197  * @param {Vec3} point - The point to transform.
198  * @returns {Vec3} The point in the new coordinate system.
199  * @example <caption>Transform a point.</caption>
200  * var scale = Vec3.multiply(2, Vec3.ONE);
201  * var rot = Quat.fromPitchYawRollDegrees(0, 45, 0);
202  * var trans = { x: 0, y: 10, z: 0 };
203  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
204  *
205  * var point = { x: 1, y: 1, z: 1 };
206  * var transformedPoint = Mat4.transformPoint(matrix, point);
207  * print("Transformed point: " + JSON.stringify(transformedPoint));
208  * // Transformed point: { "x": 2.8284270763397217, "y": 12, "z": -2.384185791015625e-7 }
209  */
210  glm::vec3 transformPoint(const glm::mat4& m, const glm::vec3& point) const;
211 
212  /*@jsdoc
213  * Transforms a vector into a new coordinate system: the vector is scaled and rotated.
214  * @function Mat4(0).transformVector
215  * @param {Mat4} m - The transform to the new coordinate system.
216  * @param {Vec3} vector - The vector to transform.
217  * @returns {Vec3} The vector in the new coordinate system.
218  * @example <caption>Transform a vector.</caption>
219  * var scale = Vec3.multiply(2, Vec3.ONE);
220  * var rot = Quat.fromPitchYawRollDegrees(0, 45, 0);
221  * var trans = { x: 0, y: 10, z: 0 };
222  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
223  *
224  * var vector = { x: 1, y: 1, z: 1 };
225  * var transformedVector = Mat4.transformVector(matrix, vector);
226  * print("Transformed vector: " + JSON.stringify(transformedVector));
227  * // Transformed vector: { "x": 2.8284270763397217, "y": 2, "z": -2.384185791015625e-7 }
228  */
229  glm::vec3 transformVector(const glm::mat4& m, const glm::vec3& vector) const;
230 
231 
232  /*@jsdoc
233  * Calculates the inverse of a matrix.
234  * @function Mat4(0).inverse
235  * @param {Mat4} m - The matrix.
236  * @returns {Mat4} The inverse of the matrix.
237  * @example <caption>A matrix multiplied with its inverse is the unit matrix.</caption>
238  * var scale = Vec3.multiply(2, Vec3.ONE);
239  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
240  * var trans = { x: 10, y: 11, z: 12 };
241  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
242  * var inverse = Mat4.inverse(matrix);
243  * var multiplied = Mat4.multiply(matrix, inverse);
244  * Mat4.print("Multiplied:", multiplied);
245  * //Multiplied: dmat4x4((1.000000, 0.000000, 0.000000, 0.000000),
246  * // (0.000000, 1.000000, -0.000000, 0.000000),
247  * // (0.000000, 0.000000, 1.000000, 0.000000),
248  * // (0.000000, 0.000000, 0.000001, 1.000000))
249  */
250  glm::mat4 inverse(const glm::mat4& m) const;
251 
252 
253  /*@jsdoc
254  * Gets the "forward" direction that the camera would face if its orientation was set to the rotation contained in a
255  * matrix. The High Fidelity camera has axes x = right, y = up, -z = forward.
256  * <p>Synonym for {@link Mat4(0).getForward|getForward}.</p>
257  * @function Mat4(0).getFront
258  * @param {Mat4} m - The matrix.
259  * @returns {Vec3} The negative z-axis rotated by orientation.
260  */
261  // redundant, calls getForward which better describes the returned vector as a direction
262  glm::vec3 getFront(const glm::mat4& m) const { return getForward(m); }
263 
264  /*@jsdoc
265  * Gets the "forward" direction that the camera would face if its orientation was set to the rotation contained in a
266  * matrix. The High Fidelity camera has axes x = right, y = up, -z = forward.
267  * @function Mat4(0).getForward
268  * @param {Mat4} m - The matrix.
269  * @returns {Vec3} The negative z-axis rotated by the rotation in the matrix.
270  * @example <caption>Demonstrate that the "forward" direction is the negative z-axis.</caption>
271  * var rot = Quat.IDENTITY;
272  * var trans = Vec3.ZERO;
273  * var matrix = Mat4.createFromRotAndTrans(rot, trans);
274  * var forward = Mat4.getForward(matrix);
275  * print("Forward: " + JSON.stringify(forward));
276  * // Forward: {"x":0,"y":0,"z":-1}
277  */
278  glm::vec3 getForward(const glm::mat4& m) const;
279 
280  /*@jsdoc
281  * Gets the "right" direction that the camera would have if its orientation was set to the rotation contained in a matrix.
282  * The High Fidelity camera has axes x = right, y = up, -z = forward.
283  * @function Mat4(0).getRight
284  * @param {Mat4} m - The matrix.
285  * @returns {Vec3} The x-axis rotated by the rotation in the matrix.
286  */
287  glm::vec3 getRight(const glm::mat4& m) const;
288 
289  /*@jsdoc
290  * Gets the "up" direction that the camera would have if its orientation was set to the rotation contained in a matrix. The
291  * High Fidelity camera has axes x = right, y = up, -z = forward.
292  * @function Mat4(0).getUp
293  * @param {Mat4} m - The matrix.
294  * @returns {Vec3} The y-axis rotated by the rotation in the matrix.
295  */
296  glm::vec3 getUp(const glm::mat4& m) const;
297 
298 
299  /*@jsdoc
300  * Prints a matrix to the program log as a label followed by the matrix's values.
301  * @function Mat4(0).print
302  * @param {string} label - The label to print.
303  * @param {Mat4} m - The matrix to print.
304  * @param {boolean} [transpose=false] - <code>true</code> to transpose the matrix before printing (so that it prints the
305  * matrix's rows), <code>false</code> to not transpose the matrix (so that it prints the matrix's columns).
306  * @example <caption>Two ways of printing a label and matrix value.</caption>
307  * var scale = Vec3.multiply(2, Vec3.ONE);
308  * var rot = Quat.fromPitchYawRollDegrees(30, 45, 60);
309  * var trans = { x: 10, y: 11, z: 12 };
310  * var matrix = Mat4.createFromScaleRotAndTrans(scale, rot, trans);
311  *
312  * Mat4.print("Matrix:", matrix);
313  * // Matrix: dmat4x4((0.707107, 1.224745, -1.414214, 0.000000),
314  * // (-1.146447, 1.478398, 0.707107, 0.000000),
315  * // (1.478398, 0.560660, 1.224745, 0.000000),
316  * // (10.000000, 11.000000, 12.000000, 1.000000))
317  *
318  * print("Matrix: " + JSON.stringify(matrix));
319  * // Matrix: {"r0c0":0.7071067094802856,"r1c0":1.2247446775436401,"r2c0":-1.4142136573791504,"r3c0":0,
320  * // "r0c1": -1.1464465856552124, "r1c1": 1.4783978462219238, "r2c1": 0.7071066498756409, "r3c1": 0,
321  * // "r0c2": 1.4783978462219238, "r1c2": 0.5606603026390076, "r2c2": 1.2247447967529297, "r3c2": 0,
322  * // "r0c3": 10, "r1c3": 11, "r2c3": 12, "r3c3": 1}
323  */
324  void print(const QString& label, const glm::mat4& m, bool transpose = false) const;
325 };
326 
327 #endif // hifi_Mat4_h
328 
Provides the Mat4 scripting interface.
Definition: Mat4.h:44
[ScriptInterface] Provides an engine-independent interface for QScriptable
Definition: Scriptable.h:29