-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy pathTSMatrix3D.h
496 lines (368 loc) · 16.4 KB
/
TSMatrix3D.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
//
// This file is part of the Terathon Math Library, by Eric Lengyel.
// Copyright 1999-2024, Terathon Software LLC
//
// This software is distributed under the MIT License.
// Separate proprietary licenses are available from Terathon Software.
//
#ifndef TSMatrix3D_h
#define TSMatrix3D_h
#include "TSMatrix2D.h"
#include "TSBivector3D.h"
#include "TSRigid2D.h"
#define TERATHON_MATRIX3D 1
#define TERATHON_TRANSFORM2D 1
namespace Terathon
{
class Matrix3D;
class Matrix4D;
class Transform2D;
class Transform3D;
struct ConstMatrix3D;
struct ConstTransform2D;
// ==============================================
// Matrix2D
// ==============================================
struct TypeMatrix3D
{
typedef float component_type;
typedef Matrix2D matrix2D_type;
typedef Matrix3D matrix3D_type;
typedef TypeVector3D column_type_struct;
typedef TypeLine2D row_type_struct;
};
/// @brief Encapsulates a 3 × 3 matrix.
///
/// The \c Matrix3D class is used to store a 3 × 3 matrix. The entries of the matrix
/// are accessed using the () operator with two indexes specifying the row and column of an entry.
///
/// @sa Matrix2D
/// @sa Matrix4D
/// @sa Transform2D
/// @sa Transform3D
class Matrix3D : public Mat3D<TypeMatrix3D>
{
public:
TERATHON_API static const ConstMatrix3D identity;
/// @brief Default constructor that leaves the entries uninitialized.
inline Matrix3D() = default;
/// @brief Constructor that sets entries explicitly.
/// @param n00,n01,n02,n10,n11,n12,n20,n21,n22 The entries of the matrix.
TERATHON_API Matrix3D(float n00, float n01, float n02, float n10, float n11, float n12, float n20, float n21, float n22);
/// @brief Constructor that sets columns explicitly.
/// @param a,b,c The columns of the matrix.
TERATHON_API Matrix3D(const Vector3D& a, const Vector3D& b, const Vector3D& c);
/// @brief Sets all nine entries of a 3 × 3 matrix.
/// @param n00,n01,n02,n10,n11,n12,n20,n21,n22 The new entries of the matrix.
TERATHON_API Matrix3D& Set(float n00, float n01, float n02, float n10, float n11, float n12, float n20, float n21, float n22);
/// @brief Sets all three columns of a 3 × 3 matrix.
/// @param a,b,c The new columns of the matrix.
TERATHON_API Matrix3D& Set(const Vector3D& a, const Vector3D& b, const Vector3D& c);
Matrix3D& operator =(const Matrix3D& m)
{
matrix = m.matrix;
return (*this);
}
void operator =(const Matrix3D& m) volatile
{
matrix = m.matrix;
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
Matrix3D& operator =(const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m)
{
matrix = m;
return (*this);
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
void operator =(const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m) volatile
{
matrix = m;
}
TERATHON_API Matrix3D& operator *=(const Matrix3D& m);
TERATHON_API Matrix3D& operator *=(float s);
TERATHON_API Matrix3D& operator /=(float s);
/// @brief Sets a matrix to the 3 × 3 identity matrix.
TERATHON_API Matrix3D& SetIdentity(void);
/// @brief Orthogonalizes the columns of a 3 × 3 matrix.
/// @param column The index of the column whose direction does not change. This must be 0, 1, or 2.
///
/// The \c Orthogonalize() function uses Gram-Schmidt orthogonalization to orthogonalize the columns
/// of a matrix. The column whose index is specified by the \c column parameter is normalized to unit length.
/// The remaining two columns are orthogonalized and made unit length. Only the two columns not specified by
/// the \c column parameter can change direction.
TERATHON_API Matrix3D& Orthogonalize(int32 column);
TERATHON_API void GetEulerAngles(float *x, float *y, float *z) const;
TERATHON_API Matrix3D& SetEulerAngles(float x, float y, float z);
/// @brief Returns a 3 × 3 matrix that represents a rotation about the <i>x</i> axis.
/// @param angle The angle through which to rotate, in radians.
TERATHON_API static Matrix3D MakeRotationX(float angle);
/// @brief Returns a 3 × 3 matrix that represents a rotation about the <i>y</i> axis.
/// @param angle The angle through which to rotate, in radians.
TERATHON_API static Matrix3D MakeRotationY(float angle);
/// @brief Returns a 3 × 3 matrix that represents a rotation about the <i>z</i> axis.
/// @param angle The angle through which to rotate, in radians.
TERATHON_API static Matrix3D MakeRotationZ(float angle);
/// @brief Returns a 3 × 3 matrix that represents a rotation about an arbitrary axis.
/// @param angle The angle through which to rotate, in radians.
/// @param axis The axis about which to rotate. This bivector must have unit magnitude.
TERATHON_API static Matrix3D MakeRotation(float angle, const Bivector3D& axis);
TERATHON_API static Matrix3D MakeReflection(const Vector3D& a);
TERATHON_API static Matrix3D MakeInvolution(const Vector3D& a);
/// @brief Returns a 3 × 3 matrix that represents a uniform scale.
/// @param scale The scale along all three axes.
TERATHON_API static Matrix3D MakeScale(float scale);
TERATHON_API static Matrix3D MakeScale(float sx, float sy, float sz);
TERATHON_API static Matrix3D MakeScale(float scale, const Vector3D& a);
TERATHON_API static Matrix3D MakeScaleX(float sx);
TERATHON_API static Matrix3D MakeScaleY(float sy);
TERATHON_API static Matrix3D MakeScaleZ(float sz);
TERATHON_API static Matrix3D MakeSkew(float angle, const Vector3D& a, const Vector3D& b);
};
template <typename type_struct, int count, int index_x, int index_y, int index_z>
inline typename type_struct::vector3D_type operator *(const Matrix3D& m, const Subvec3D<type_struct, false, count, index_x, index_y, index_z>& v)
{
return (m.matrix * v);
}
template <typename type_struct, int count, int index_x, int index_y, int index_z>
inline typename type_struct::vector3D_type operator *(const Subvec3D<type_struct, true, count, index_x, index_y, index_z>& v, const Matrix3D& m)
{
return (v * m.matrix);
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
inline Vector3D operator *(const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m, const Vector3D& v)
{
return (m * v.xyz);
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
inline Bivector3D operator *(const Bivector3D& v, const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m)
{
return (v.xyz * m);
}
inline Vector3D operator *(const Matrix3D& m, const Vector3D& v)
{
return (m.matrix * v.xyz);
}
inline Point3D operator *(const Matrix3D& m, const Point3D& p)
{
return (Point3D::origin + m.matrix * p.xyz);
}
inline Bivector3D operator *(const Bivector3D& v, const Matrix3D& m)
{
return (v.xyz * m.matrix);
}
/// @brief Returns the product of the matrices \c m1 and \c m2.
/// @relatedalso Matrix3D
inline Matrix3D operator *(const Matrix3D& m1, const Matrix3D& m2)
{
return (m1.matrix * m2.matrix);
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
inline Matrix3D operator *(const Matrix3D& m1, const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m2)
{
return (m1.matrix * m2);
}
template <typename type_struct, int count, int index_00, int index_01, int index_02, int index_10, int index_11, int index_12, int index_20, int index_21, int index_22>
inline Matrix3D operator *(const Submat3D<type_struct, count, index_00, index_01, index_02, index_10, index_11, index_12, index_20, index_21, index_22>& m1, const Matrix3D& m2)
{
return (m1 * m2.matrix);
}
TERATHON_API Matrix3D operator *(const Matrix3D& m, float s);
TERATHON_API Matrix3D operator /(const Matrix3D& m, float s);
inline Matrix3D operator *(float s, const Matrix3D& m)
{
return (m * s);
}
/// @brief Returns the determinant of the matrix \c m.
/// @relatedalso Matrix3D
TERATHON_API float Determinant(const Matrix3D& m);
/// @brief Returns the inverse of the matrix \c m. If \c m is singular, then the result is undefined.
/// @relatedalso Matrix3D
TERATHON_API Matrix3D Inverse(const Matrix3D& m);
/// @brief Returns the adjugate of the matrix \c m.
/// @relatedalso Matrix3D
TERATHON_API Matrix3D Adjugate(const Matrix3D& m);
// ==============================================
// Transform2D
// ==============================================
/// @brief Encapsulates a 3 × 3 matrix whose third row is always (0, 0, 1).
///
/// The \c Transform2D class is used to store a 3 × 3 matrix whose third row is always (0, 0, 1).
/// Such a matrix represents an affine transformation in 2D space.
///
/// @sa Transform3D
class Transform2D : public Matrix3D
{
public:
TERATHON_API static const ConstTransform2D identity;
/// @brief Default constructor that leaves the entries uninitialized.
inline Transform2D() = default;
/// @brief Constructor that sets entries explicitly.
/// @param n00,n01,n02,n10,n11,n12,n20,n21,n22 The entries of first two rows of the matrix.
TERATHON_API Transform2D(float n00, float n01, float n02, float n10, float n11, float n12);
TERATHON_API Transform2D(const Vector2D& a, const Vector2D& b, const Point2D& p);
TERATHON_API Transform2D(const Vector2D& r0, float n02, const Vector2D& r1, float n12);
TERATHON_API Transform2D(const Matrix2D& m);
TERATHON_API Transform2D(const Matrix2D& m, const Vector2D& v);
TERATHON_API Transform2D& Set(float n00, float n01, float n02, float n10, float n11, float n12);
TERATHON_API Transform2D& Set(const Vector2D& a, const Vector2D& b, const Point2D& p);
TERATHON_API Transform2D& Set(const Matrix2D& m, const Vector2D& v);
Vector2D& operator [](machine j)
{
return (Matrix3D::operator [](j).xy);
}
const Vector2D& operator [](machine j) const
{
return (Matrix3D::operator [](j).xy);
}
const Point2D& GetTranslation(void) const
{
return (Point2D::origin + Matrix3D::operator [](2).xy);
}
Transform2D& SetTranslation(float x, float y)
{
m02 = x;
m12 = y;
return (*this);
}
Transform2D& SetTranslation(const Point2D& p)
{
m02 = p.x;
m12 = p.y;
return (*this);
}
TERATHON_API Transform2D& operator *=(const Transform2D& m);
TERATHON_API Transform2D& operator *=(const Matrix2D& m);
TERATHON_API Transform2D& SetMatrix2D(const Vector2D& a, const Vector2D& b);
TERATHON_API Transform2D& Orthogonalize(int32 column);
TERATHON_API static Transform2D MakeRotation(float angle);
TERATHON_API static Transform2D MakeScale(float sx, float sy);
TERATHON_API static Transform2D MakeTranslation(const Vector2D& dv);
};
template <typename type_struct, int count, int index_x, int index_y>
inline Vector2D operator *(const Transform2D& m, const Subvec2D<type_struct, count, index_x, index_y>& v)
{
return (m.matrix2D * v);
}
template <typename type_struct, int count, int index_x, int index_y>
inline Vector2D operator *(const Subvec2D<type_struct, count, index_x, index_y>& v, const Transform2D& m)
{
return (v * m.matrix2D);
}
template <typename type_struct, int count, int index_x, int index_y, int index_z>
Vector3D operator *(const Transform2D& m, const Subvec3D<type_struct, false, count, index_x, index_y, index_z>& v)
{
return (Vector3D(m(0,0) * v.data[index_x] + m(0,1) * v.data[index_y] + m(0,2) * v.data[index_z],
m(1,0) * v.data[index_x] + m(1,1) * v.data[index_y] + m(1,2) * v.data[index_z],
v.data[index_z]));
}
template <typename type_struct, int count, int index_x, int index_y, int index_z>
Antivector3D operator *(const Subvec3D<type_struct, true, count, index_x, index_y, index_z>& v, const Transform2D& m)
{
return (Antivector3D(m(0,0) * v.data[index_x] + m(1,0) * v.data[index_y],
m(0,1) * v.data[index_x] + m(1,1) * v.data[index_y],
m(0,2) * v.data[index_x] + m(1,2) * v.data[index_y] + v.data[index_z]));
}
inline Vector3D operator *(const Transform2D& m, const Vector3D& v)
{
return (m * v.xyz);
}
inline Antivector3D operator *(const Antivector3D& v, const Transform2D& m)
{
return (v.xyz * m);
}
template <typename type_struct, int count, int index_00, int index_01, int index_10, int index_11>
inline Transform2D operator *(const Transform2D& m1, const Submat2D<type_struct, count, index_00, index_01, index_10, index_11>& m2)
{
Transform2D transform;
transform.matrix2D = m1.matrix2D * m2;
transform[2] = m1[2];
transform.m20 = transform.m21 = 0.0F;
transform.m22 = 1.0F;
return (transform);
}
template <typename type_struct, int count, int index_00, int index_01, int index_10, int index_11>
inline Transform2D operator *(const Submat2D<type_struct, count, index_00, index_01, index_10, index_11>& m1, const Transform2D& m2)
{
Transform2D transform;
transform.matrix2D = m1 * m2.matrix2D;
transform[2] = m1 * m2[2];
transform.m20 = transform.m21 = 0.0F;
transform.m22 = 1.0F;
return (transform);
}
inline Transform2D operator *(const Transform2D& m1, const Matrix2D& m2)
{
return (m1 * m2.matrix);
}
inline Transform2D operator *(const Matrix2D& m1, const Transform2D& m2)
{
return (m1.matrix * m2);
}
TERATHON_API Transform2D operator *(const Transform2D& m1, const Transform2D& m2);
TERATHON_API Matrix3D operator *(const Matrix3D& m1, const Transform2D& m2);
TERATHON_API Matrix3D operator *(const Transform2D& m1, const Matrix3D& m2);
TERATHON_API Vector2D operator *(const Transform2D& m, const Vector2D& v);
TERATHON_API Vector2D operator *(const Vector2D& v, const Transform2D& m);
TERATHON_API Point2D operator *(const Transform2D& m, const Point2D& p);
/// @brief Returns the determinant of the transform \c m.
/// @relatedalso Transform2D
TERATHON_API float Determinant(const Transform2D& m);
/// @brief Returns the inverse of the transform \c m. If \c m is singular, then the result is undefined.
/// @relatedalso Transform2D
TERATHON_API Transform2D Inverse(const Transform2D& m);
/// @brief Returns the inverse of the transform \c m assuming that its determinant is one.
/// @relatedalso Transform2D
TERATHON_API Transform2D InverseUnitDet(const Transform2D& m);
// ==============================================
// POD Structures
// ==============================================
struct ConstMatrix3D
{
float n[3][3];
operator const Matrix3D&(void) const
{
return (reinterpret_cast<const Matrix3D&>(*this));
}
const Matrix3D *operator &(void) const
{
return (reinterpret_cast<const Matrix3D *>(this));
}
const Matrix3D *operator ->(void) const
{
return (reinterpret_cast<const Matrix3D *>(this));
}
float operator ()(int32 i, int32 j) const
{
return (reinterpret_cast<const Matrix3D&>(*this)(i, j));
}
const Vector3D& operator [](machine j) const
{
return (reinterpret_cast<const Matrix3D&>(*this)[j]);
}
};
struct ConstTransform2D
{
float n[3][3];
operator const Transform2D&(void) const
{
return (reinterpret_cast<const Transform2D&>(*this));
}
const Transform2D *operator &(void) const
{
return (reinterpret_cast<const Transform2D *>(this));
}
const Transform2D *operator ->(void) const
{
return (reinterpret_cast<const Transform2D *>(this));
}
float operator ()(int32 i, int32 j) const
{
return (reinterpret_cast<const Transform2D&>(*this)(i, j));
}
const Vector2D& operator [](machine j) const
{
return (reinterpret_cast<const Transform2D&>(*this)[j]);
}
};
}
#endif