Coverage Report

Created: 2025-07-18 07:08

/src/ogre/OgreMain/include/OgreMatrix4.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef __Matrix4__
29
#define __Matrix4__
30
31
// Precompiler options
32
#include "OgrePrerequisites.h"
33
34
#include "OgreMatrix3.h"
35
#include "OgreVector.h"
36
37
namespace Ogre
38
{
39
    /** \addtogroup Core
40
    *  @{
41
    */
42
    /** \addtogroup Math
43
    *  @{
44
    */
45
    class Matrix4;
46
    class Affine3;
47
    Matrix4 operator*(const Matrix4 &m, const Matrix4 &m2);
48
    /** Class encapsulating a standard 4x4 homogeneous matrix.
49
50
        OGRE uses column vectors when applying matrix multiplications,
51
        This means a vector is represented as a single column, 4-row
52
        matrix. This has the effect that the transformations implemented
53
        by the matrices happens right-to-left e.g. if vector V is to be
54
        transformed by M1 then M2 then M3, the calculation would be
55
        M3 * M2 * M1 * V. The order that matrices are concatenated is
56
        vital since matrix multiplication is not commutative, i.e. you
57
        can get a different result if you concatenate in the wrong order.
58
        @par
59
            The use of column vectors and right-to-left ordering is the
60
            standard in most mathematical texts, and is the same as used in
61
            OpenGL. It is, however, the opposite of Direct3D, which has
62
            inexplicably chosen to differ from the accepted standard and uses
63
            row vectors and left-to-right matrix multiplication.
64
        @par
65
            OGRE deals with the differences between D3D and OpenGL etc.
66
            internally when operating through different render systems. OGRE
67
            users only need to conform to standard maths conventions, i.e.
68
            right-to-left matrix multiplication, (OGRE transposes matrices it
69
            passes to D3D to compensate).
70
        @par
71
            The generic form M * V which shows the layout of the matrix
72
            entries is shown below:
73
            <pre>
74
                [ m[0][0]  m[0][1]  m[0][2]  m[0][3] ]   {x}
75
                | m[1][0]  m[1][1]  m[1][2]  m[1][3] | * {y}
76
                | m[2][0]  m[2][1]  m[2][2]  m[2][3] |   {z}
77
                [ m[3][0]  m[3][1]  m[3][2]  m[3][3] ]   {1}
78
            </pre>
79
    */
80
    template<int rows, typename T> class TransformBase
81
    {
82
    protected:
83
        /// The matrix entries, indexed by [row][col].
84
        T m[rows][4];
85
        // do not reduce storage for affine for compatibility with SSE, shader mat4 types
86
    public:
87
        /// Do <b>NOT</b> initialize for efficiency.
88
10
        TransformBase() {}
89
90
        template<typename U>
91
        explicit TransformBase(const U* ptr) {
92
            for (int i = 0; i < rows; i++)
93
                for (int j = 0; j < 4; j++)
94
                    m[i][j] = T(ptr[i*4 + j]);
95
        }
96
97
        template<typename U>
98
        explicit TransformBase(const TransformBase<rows, U>& o) : TransformBase(o[0]) {}
99
100
        T* operator[](size_t iRow)
101
0
        {
102
0
            assert(iRow < rows);
103
0
            return m[iRow];
104
0
        }
105
106
        const T* operator[](size_t iRow) const
107
0
        {
108
0
            assert(iRow < rows);
109
0
            return m[iRow];
110
0
        }
111
112
        /// Sets the translation transformation part of the matrix.
113
        void setTrans( const Vector<3, T>& v )
114
0
        {
115
0
            assert(rows > 2);
116
0
            m[0][3] = v[0];
117
0
            m[1][3] = v[1];
118
0
            m[2][3] = v[2];
119
0
        }
120
        /// Extracts the translation transformation part of the matrix.
121
        Vector<3, T> getTrans() const
122
        {
123
            assert(rows > 2);
124
            return Vector<3, T>(m[0][3], m[1][3], m[2][3]);
125
        }
126
        /// Sets the scale part of the matrix.
127
        void setScale( const Vector<3, T>& v )
128
0
        {
129
0
            assert(rows > 2);
130
0
            m[0][0] = v[0];
131
0
            m[1][1] = v[1];
132
0
            m[2][2] = v[2];
133
0
        }
134
135
        /** Function for writing to a stream.
136
         */
137
        inline friend std::ostream& operator<<(std::ostream& o, const TransformBase& mat)
138
        {
139
            o << "Matrix" << rows << "x4(";
140
            for (size_t i = 0; i < rows; ++i)
141
            {
142
                for (size_t j = 0; j < 4; ++j)
143
                {
144
                    o << mat[i][j];
145
                    if(j != 3)
146
                        o << ", ";
147
                }
148
149
                if(i != (rows - 1))
150
                    o << "; ";
151
            }
152
            o << ")";
153
            return o;
154
        }
155
    };
156
157
    struct _OgreExport TransformBaseReal : public TransformBase<4, Real>
158
    {
159
        /// Do <b>NOT</b> initialize for efficiency.
160
10
        TransformBaseReal() {}
161
        template<typename U>
162
        explicit TransformBaseReal(const U* ptr) : TransformBase(ptr) {}
163
        /** Builds a translation matrix
164
        */
165
        void makeTrans( const Vector3& v )
166
0
        {
167
0
            makeTrans(v.x, v.y, v.z);
168
0
        }
169
170
        void makeTrans( Real tx, Real ty, Real tz )
171
0
        {
172
0
            m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = tx;
173
0
            m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = ty;
174
0
            m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = tz;
175
0
            m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
176
0
        }
177
178
        /** Assignment from 3x3 matrix.
179
        */
180
        void set3x3Matrix(const Matrix3& mat3)
181
0
        {
182
0
            m[0][0] = mat3[0][0]; m[0][1] = mat3[0][1]; m[0][2] = mat3[0][2];
183
0
            m[1][0] = mat3[1][0]; m[1][1] = mat3[1][1]; m[1][2] = mat3[1][2];
184
0
            m[2][0] = mat3[2][0]; m[2][1] = mat3[2][1]; m[2][2] = mat3[2][2];
185
0
        }
186
187
        /** Extracts the rotation / scaling part of the Matrix as a 3x3 matrix.
188
        */
189
        Matrix3 linear() const
190
0
        {
191
0
            return Matrix3(m[0][0], m[0][1], m[0][2],
192
0
                           m[1][0], m[1][1], m[1][2],
193
0
                           m[2][0], m[2][1], m[2][2]);
194
0
        }
195
196
0
        OGRE_DEPRECATED void extract3x3Matrix(Matrix3& m3x3) const { m3x3 = linear(); }
197
0
        OGRE_DEPRECATED Quaternion extractQuaternion() const { return Quaternion(linear()); }
198
199
        Real determinant() const;
200
201
        Matrix4 transpose() const;
202
203
        /** Building a Affine3 from orientation / scale / position.
204
205
            Transform is performed in the order scale, rotate, translation, i.e. translation is independent
206
            of orientation axes, scale does not affect size of translation, rotation and scaling are always
207
            centered on the origin.
208
        */
209
        void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
210
211
        /** Building an inverse Affine3 from orientation / scale / position.
212
213
            As makeTransform except it build the inverse given the same data as makeTransform, so
214
            performing -translation, -rotate, 1/scale in that order.
215
        */
216
        void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
217
    };
218
219
    /// Transform specialization for projective - encapsulating a 4x4 Matrix
220
    class _OgreExport Matrix4 : public TransformBaseReal
221
    {
222
    public:
223
        /// Do <b>NOT</b> initialize the matrix for efficiency.
224
0
        Matrix4() {}
225
226
        Matrix4(
227
            Real m00, Real m01, Real m02, Real m03,
228
            Real m10, Real m11, Real m12, Real m13,
229
            Real m20, Real m21, Real m22, Real m23,
230
            Real m30, Real m31, Real m32, Real m33 )
231
        {
232
            m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
233
            m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
234
            m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
235
            m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
236
        }
237
238
        template<typename U>
239
        explicit Matrix4(const U* ptr) : TransformBaseReal(ptr) {}
240
        explicit Matrix4 (const Real* arr)
241
0
        {
242
0
            memcpy(m,arr,16*sizeof(Real));
243
0
        }
244
245
        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
246
         */
247
248
        explicit Matrix4(const Matrix3& m3x3)
249
0
        {
250
0
          operator=(IDENTITY);
251
0
          operator=(m3x3);
252
0
        }
253
254
        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Quaternion.
255
         */
256
        
257
        explicit Matrix4(const Quaternion& rot)
258
0
        {
259
0
          Matrix3 m3x3;
260
0
          rot.ToRotationMatrix(m3x3);
261
0
          *this = IDENTITY;
262
0
          *this = m3x3;
263
0
        }
264
        
265
0
        Matrix4& operator=(const Matrix3& mat3) {
266
0
            set3x3Matrix(mat3);
267
0
            return *this;
268
0
        }
269
270
0
        OGRE_DEPRECATED Matrix4 concatenate(const Matrix4& m2) const { return *this * m2; }
271
272
        /** Tests 2 matrices for equality.
273
        */
274
        inline bool operator == ( const Matrix4& m2 ) const
275
0
        {
276
0
            if( 
277
0
                m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
278
0
                m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
279
0
                m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
280
0
                m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
281
0
                return false;
282
0
            return true;
283
0
        }
284
285
        /** Tests 2 matrices for inequality.
286
        */
287
        inline bool operator != ( const Matrix4& m2 ) const
288
0
        {
289
0
            if( 
290
0
                m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
291
0
                m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
292
0
                m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
293
0
                m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
294
0
                return true;
295
0
            return false;
296
0
        }
297
298
        static const Matrix4 ZERO;
299
        static const Matrix4 IDENTITY;
300
        /** Useful little matrix which takes 2D clipspace {-1, 1} to {0,1}
301
            and inverts the Y. */
302
        static const Matrix4 CLIPSPACE2DTOIMAGESPACE;
303
304
        inline Matrix4 operator*(Real scalar) const
305
0
        {
306
0
            return Matrix4(
307
0
                scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3],
308
0
                scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3],
309
0
                scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3],
310
0
                scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]);
311
0
        }
312
        
313
        Matrix4 adjoint() const;
314
        Matrix4 inverse() const;
315
    };
316
317
    /// Transform specialization for 3D Affine - encapsulating a 3x4 Matrix
318
    class _OgreExport Affine3 : public TransformBaseReal
319
    {
320
    public:
321
        /// Do <b>NOT</b> initialize the matrix for efficiency.
322
0
        Affine3() {}
323
324
        /// @copydoc TransformBaseReal::makeTransform
325
        Affine3(const Vector3& position, const Quaternion& orientation, const Vector3& scale = Vector3::UNIT_SCALE)
326
0
        {
327
0
            makeTransform(position, scale, orientation);
328
0
        }
329
330
        template<typename U>
331
        explicit Affine3(const U* ptr)
332
        {
333
            for (int i = 0; i < 3; i++)
334
                for (int j = 0; j < 4; j++)
335
                    m[i][j] = Real(ptr[i*4 + j]);
336
            m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1;
337
        }
338
339
        explicit Affine3(const Real* arr)
340
0
        {
341
0
            memcpy(m, arr, 12 * sizeof(Real));
342
0
            m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1;
343
0
        }
344
345
        Affine3(
346
            Real m00, Real m01, Real m02, Real m03,
347
            Real m10, Real m11, Real m12, Real m13,
348
            Real m20, Real m21, Real m22, Real m23)
349
        {
350
            m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
351
            m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
352
            m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
353
            m[3][0] = 0;   m[3][1] = 0;   m[3][2] = 0;   m[3][3] = 1;
354
        }
355
356
        /// extract the Affine part of a Matrix4
357
        explicit Affine3(const Matrix4& mat)
358
0
        {
359
0
            m[0][0] = mat[0][0]; m[0][1] = mat[0][1]; m[0][2] = mat[0][2]; m[0][3] = mat[0][3];
360
0
            m[1][0] = mat[1][0]; m[1][1] = mat[1][1]; m[1][2] = mat[1][2]; m[1][3] = mat[1][3];
361
0
            m[2][0] = mat[2][0]; m[2][1] = mat[2][1]; m[2][2] = mat[2][2]; m[2][3] = mat[2][3];
362
0
            m[3][0] = 0;         m[3][1] = 0;         m[3][2] = 0;         m[3][3] = 1;
363
0
        }
364
365
0
        Affine3& operator=(const Matrix3& mat3) {
366
0
            set3x3Matrix(mat3);
367
0
            return *this;
368
0
        }
369
370
        /** Tests 2 matrices for equality.
371
        */
372
        bool operator==(const Affine3& m2) const
373
0
        {
374
0
            if(
375
0
                m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
376
0
                m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
377
0
                m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] )
378
0
                return false;
379
0
            return true;
380
0
        }
381
382
0
        bool operator!=(const Affine3& m2) const { return !(*this == m2); }
383
384
        Affine3 inverse() const;
385
386
        /** Decompose to orientation / scale / position.
387
        */
388
        void decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const;
389
390
        /// every Affine3 transform is also a _const_ Matrix4
391
0
        operator const Matrix4&() const { return reinterpret_cast<const Matrix4&>(*this); }
392
393
        using TransformBaseReal::getTrans;
394
395
        /** Gets a translation matrix.
396
        */
397
        static Affine3 getTrans( const Vector3& v )
398
0
        {
399
0
            return getTrans(v.x, v.y, v.z);
400
0
        }
401
402
        /** Gets a translation matrix - variation for not using a vector.
403
        */
404
        static Affine3 getTrans( Real t_x, Real t_y, Real t_z )
405
0
        {
406
0
            return Affine3(1, 0, 0, t_x,
407
0
                           0, 1, 0, t_y,
408
0
                           0, 0, 1, t_z);
409
0
        }
410
411
        /** Gets a scale matrix.
412
        */
413
        static Affine3 getScale( const Vector3& v )
414
0
        {
415
0
            return getScale(v.x, v.y, v.z);
416
0
        }
417
418
        /** Gets a scale matrix - variation for not using a vector.
419
        */
420
        static Affine3 getScale( Real s_x, Real s_y, Real s_z )
421
0
        {
422
0
            return Affine3(s_x, 0, 0, 0,
423
0
                           0, s_y, 0, 0,
424
0
                           0, 0, s_z, 0);
425
0
        }
426
427
428
        static const Affine3 ZERO;
429
        static const Affine3 IDENTITY;
430
    };
431
432
    inline Matrix4 TransformBaseReal::transpose() const
433
0
    {
434
0
        return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
435
0
                       m[0][1], m[1][1], m[2][1], m[3][1],
436
0
                       m[0][2], m[1][2], m[2][2], m[3][2],
437
0
                       m[0][3], m[1][3], m[2][3], m[3][3]);
438
0
    }
439
440
    /** Matrix addition.
441
    */
442
    inline Matrix4 operator+(const Matrix4& m, const Matrix4& m2)
443
0
    {
444
0
        Matrix4 r;
445
0
446
0
        r[0][0] = m[0][0] + m2[0][0];
447
0
        r[0][1] = m[0][1] + m2[0][1];
448
0
        r[0][2] = m[0][2] + m2[0][2];
449
0
        r[0][3] = m[0][3] + m2[0][3];
450
0
451
0
        r[1][0] = m[1][0] + m2[1][0];
452
0
        r[1][1] = m[1][1] + m2[1][1];
453
0
        r[1][2] = m[1][2] + m2[1][2];
454
0
        r[1][3] = m[1][3] + m2[1][3];
455
0
456
0
        r[2][0] = m[2][0] + m2[2][0];
457
0
        r[2][1] = m[2][1] + m2[2][1];
458
0
        r[2][2] = m[2][2] + m2[2][2];
459
0
        r[2][3] = m[2][3] + m2[2][3];
460
0
461
0
        r[3][0] = m[3][0] + m2[3][0];
462
0
        r[3][1] = m[3][1] + m2[3][1];
463
0
        r[3][2] = m[3][2] + m2[3][2];
464
0
        r[3][3] = m[3][3] + m2[3][3];
465
0
466
0
        return r;
467
0
    }
468
469
    /** Matrix subtraction.
470
    */
471
    inline Matrix4 operator-(const Matrix4& m, const Matrix4& m2)
472
0
    {
473
0
        Matrix4 r;
474
0
        r[0][0] = m[0][0] - m2[0][0];
475
0
        r[0][1] = m[0][1] - m2[0][1];
476
0
        r[0][2] = m[0][2] - m2[0][2];
477
0
        r[0][3] = m[0][3] - m2[0][3];
478
0
479
0
        r[1][0] = m[1][0] - m2[1][0];
480
0
        r[1][1] = m[1][1] - m2[1][1];
481
0
        r[1][2] = m[1][2] - m2[1][2];
482
0
        r[1][3] = m[1][3] - m2[1][3];
483
0
484
0
        r[2][0] = m[2][0] - m2[2][0];
485
0
        r[2][1] = m[2][1] - m2[2][1];
486
0
        r[2][2] = m[2][2] - m2[2][2];
487
0
        r[2][3] = m[2][3] - m2[2][3];
488
0
489
0
        r[3][0] = m[3][0] - m2[3][0];
490
0
        r[3][1] = m[3][1] - m2[3][1];
491
0
        r[3][2] = m[3][2] - m2[3][2];
492
0
        r[3][3] = m[3][3] - m2[3][3];
493
0
494
0
        return r;
495
0
    }
496
497
    inline Matrix4 operator*(const Matrix4 &m, const Matrix4 &m2)
498
0
    {
499
0
        Matrix4 r;
500
0
        r[0][0] = m[0][0] * m2[0][0] + m[0][1] * m2[1][0] + m[0][2] * m2[2][0] + m[0][3] * m2[3][0];
501
0
        r[0][1] = m[0][0] * m2[0][1] + m[0][1] * m2[1][1] + m[0][2] * m2[2][1] + m[0][3] * m2[3][1];
502
0
        r[0][2] = m[0][0] * m2[0][2] + m[0][1] * m2[1][2] + m[0][2] * m2[2][2] + m[0][3] * m2[3][2];
503
0
        r[0][3] = m[0][0] * m2[0][3] + m[0][1] * m2[1][3] + m[0][2] * m2[2][3] + m[0][3] * m2[3][3];
504
0
505
0
        r[1][0] = m[1][0] * m2[0][0] + m[1][1] * m2[1][0] + m[1][2] * m2[2][0] + m[1][3] * m2[3][0];
506
0
        r[1][1] = m[1][0] * m2[0][1] + m[1][1] * m2[1][1] + m[1][2] * m2[2][1] + m[1][3] * m2[3][1];
507
0
        r[1][2] = m[1][0] * m2[0][2] + m[1][1] * m2[1][2] + m[1][2] * m2[2][2] + m[1][3] * m2[3][2];
508
0
        r[1][3] = m[1][0] * m2[0][3] + m[1][1] * m2[1][3] + m[1][2] * m2[2][3] + m[1][3] * m2[3][3];
509
0
510
0
        r[2][0] = m[2][0] * m2[0][0] + m[2][1] * m2[1][0] + m[2][2] * m2[2][0] + m[2][3] * m2[3][0];
511
0
        r[2][1] = m[2][0] * m2[0][1] + m[2][1] * m2[1][1] + m[2][2] * m2[2][1] + m[2][3] * m2[3][1];
512
0
        r[2][2] = m[2][0] * m2[0][2] + m[2][1] * m2[1][2] + m[2][2] * m2[2][2] + m[2][3] * m2[3][2];
513
0
        r[2][3] = m[2][0] * m2[0][3] + m[2][1] * m2[1][3] + m[2][2] * m2[2][3] + m[2][3] * m2[3][3];
514
0
515
0
        r[3][0] = m[3][0] * m2[0][0] + m[3][1] * m2[1][0] + m[3][2] * m2[2][0] + m[3][3] * m2[3][0];
516
0
        r[3][1] = m[3][0] * m2[0][1] + m[3][1] * m2[1][1] + m[3][2] * m2[2][1] + m[3][3] * m2[3][1];
517
0
        r[3][2] = m[3][0] * m2[0][2] + m[3][1] * m2[1][2] + m[3][2] * m2[2][2] + m[3][3] * m2[3][2];
518
0
        r[3][3] = m[3][0] * m2[0][3] + m[3][1] * m2[1][3] + m[3][2] * m2[2][3] + m[3][3] * m2[3][3];
519
0
520
0
        return r;
521
0
    }
522
    inline Affine3 operator*(const Affine3 &m, const Affine3 &m2)
523
0
    {
524
0
        return Affine3(
525
0
            m[0][0] * m2[0][0] + m[0][1] * m2[1][0] + m[0][2] * m2[2][0],
526
0
            m[0][0] * m2[0][1] + m[0][1] * m2[1][1] + m[0][2] * m2[2][1],
527
0
            m[0][0] * m2[0][2] + m[0][1] * m2[1][2] + m[0][2] * m2[2][2],
528
0
            m[0][0] * m2[0][3] + m[0][1] * m2[1][3] + m[0][2] * m2[2][3] + m[0][3],
529
0
530
0
            m[1][0] * m2[0][0] + m[1][1] * m2[1][0] + m[1][2] * m2[2][0],
531
0
            m[1][0] * m2[0][1] + m[1][1] * m2[1][1] + m[1][2] * m2[2][1],
532
0
            m[1][0] * m2[0][2] + m[1][1] * m2[1][2] + m[1][2] * m2[2][2],
533
0
            m[1][0] * m2[0][3] + m[1][1] * m2[1][3] + m[1][2] * m2[2][3] + m[1][3],
534
0
535
0
            m[2][0] * m2[0][0] + m[2][1] * m2[1][0] + m[2][2] * m2[2][0],
536
0
            m[2][0] * m2[0][1] + m[2][1] * m2[1][1] + m[2][2] * m2[2][1],
537
0
            m[2][0] * m2[0][2] + m[2][1] * m2[1][2] + m[2][2] * m2[2][2],
538
0
            m[2][0] * m2[0][3] + m[2][1] * m2[1][3] + m[2][2] * m2[2][3] + m[2][3]);
539
0
    }
540
541
    /** Vector transformation using '*'.
542
543
        Transforms the given 3-D vector by the matrix, projecting the
544
        result back into <i>w</i> = 1.
545
        @note
546
            This means that the initial <i>w</i> is considered to be 1.0,
547
            and then all the tree elements of the resulting 3-D vector are
548
            divided by the resulting <i>w</i>.
549
    */
550
    inline Vector3 operator*(const Matrix4& m, const Vector3& v)
551
0
    {
552
0
        Vector3 r;
553
0
554
0
        Real fInvW = 1.0f / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] );
555
0
556
0
        r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
557
0
        r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
558
0
        r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
559
0
560
0
        return r;
561
0
    }
562
    /// @overload
563
    inline Vector3 operator*(const Affine3& m,const Vector3& v)
564
0
    {
565
0
        return Vector3(
566
0
                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3],
567
0
                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
568
0
                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
569
0
    }
570
571
    inline Vector4 operator*(const Matrix4& m, const Vector4& v)
572
0
    {
573
0
        return Vector4(
574
0
            m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
575
0
            m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
576
0
            m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
577
0
            m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w);
578
0
    }
579
    inline Vector4 operator*(const Affine3& m, const Vector4& v)
580
0
    {
581
0
        return Vector4(
582
0
            m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
583
0
            m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
584
0
            m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
585
0
            v.w);
586
0
    }
587
588
    inline Vector4 operator * (const Vector4& v, const Matrix4& mat)
589
0
    {
590
0
        return Vector4(
591
0
            v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + v.w*mat[3][0],
592
0
            v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + v.w*mat[3][1],
593
0
            v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + v.w*mat[3][2],
594
0
            v.x*mat[0][3] + v.y*mat[1][3] + v.z*mat[2][3] + v.w*mat[3][3]
595
0
            );
596
0
    }
597
    /** @} */
598
    /** @} */
599
600
}
601
#endif