Coverage Report

Created: 2026-08-29 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/include/OgreMatrix4.h
Line
Count
Source
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
        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
        {
115
            assert(rows > 2);
116
            m[0][3] = v[0];
117
            m[1][3] = v[1];
118
            m[2][3] = v[2];
119
        }
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
        {
129
            assert(rows > 2);
130
            m[0][0] = v[0];
131
            m[1][1] = v[1];
132
            m[2][2] = v[2];
133
        }
134
    };
135
136
    /** Function for writing to a stream.
137
    */
138
    template <typename CharT, typename TraitsT, int rows, typename T>
139
    std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& o,
140
                                                   const TransformBase<rows, T>& mat)
141
    {
142
        o << "Matrix" << rows << "x4(";
143
        for (size_t i = 0; i < rows; ++i)
144
        {
145
            for (size_t j = 0; j < 4; ++j)
146
            {
147
                o << mat[i][j];
148
                if(j != 3)
149
                    o << ", ";
150
            }
151
152
            if(i != (rows - 1))
153
                o << "; ";
154
        }
155
        o << ")";
156
        return o;
157
    }
158
159
    struct _OgreExport TransformBaseReal : public TransformBase<4, Real>
160
    {
161
        /// Do <b>NOT</b> initialize for efficiency.
162
0
        TransformBaseReal() {}
163
        template<typename U>
164
        explicit TransformBaseReal(const U* ptr) : TransformBase(ptr) {}
165
        /** Builds a translation matrix
166
        */
167
        void makeTrans( const Vector3& v )
168
0
        {
169
0
            makeTrans(v.x, v.y, v.z);
170
0
        }
171
172
        void makeTrans( Real tx, Real ty, Real tz )
173
0
        {
174
0
            m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = tx;
175
0
            m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = ty;
176
0
            m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = tz;
177
0
            m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
178
0
        }
179
180
        /** Assignment from 3x3 matrix.
181
        */
182
        void set3x3Matrix(const Matrix3& mat3)
183
0
        {
184
0
            m[0][0] = mat3[0][0]; m[0][1] = mat3[0][1]; m[0][2] = mat3[0][2];
185
0
            m[1][0] = mat3[1][0]; m[1][1] = mat3[1][1]; m[1][2] = mat3[1][2];
186
0
            m[2][0] = mat3[2][0]; m[2][1] = mat3[2][1]; m[2][2] = mat3[2][2];
187
0
        }
188
189
        /** Extracts the rotation / scaling part of the Matrix as a 3x3 matrix.
190
        */
191
        Matrix3 linear() const
192
0
        {
193
0
            return Matrix3(m[0][0], m[0][1], m[0][2],
194
0
                           m[1][0], m[1][1], m[1][2],
195
0
                           m[2][0], m[2][1], m[2][2]);
196
0
        }
197
198
0
        OGRE_DEPRECATED void extract3x3Matrix(Matrix3& m3x3) const { m3x3 = linear(); }
199
0
        OGRE_DEPRECATED Quaternion extractQuaternion() const { return Quaternion(linear()); }
200
201
        Real determinant() const;
202
203
        Matrix4 transpose() const;
204
205
        /** Building a Affine3 from orientation / scale / position.
206
207
            Transform is performed in the order scale, rotate, translation, i.e. translation is independent
208
            of orientation axes, scale does not affect size of translation, rotation and scaling are always
209
            centered on the origin.
210
        */
211
        void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
212
213
        /** Building an inverse Affine3 from orientation / scale / position.
214
215
            As makeTransform except it build the inverse given the same data as makeTransform, so
216
            performing -translation, -rotate, 1/scale in that order.
217
        */
218
        void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
219
    };
220
221
    /// Transform specialization for projective - encapsulating a 4x4 Matrix
222
    class _OgreExport Matrix4 : public TransformBaseReal
223
    {
224
    public:
225
        /// Do <b>NOT</b> initialize the matrix for efficiency.
226
0
        Matrix4() {}
227
228
        Matrix4(
229
            Real m00, Real m01, Real m02, Real m03,
230
            Real m10, Real m11, Real m12, Real m13,
231
            Real m20, Real m21, Real m22, Real m23,
232
            Real m30, Real m31, Real m32, Real m33 )
233
0
        {
234
0
            m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
235
0
            m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
236
0
            m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
237
0
            m[3][0] = m30; m[3][1] = m31; m[3][2] = m32; m[3][3] = m33;
238
0
        }
239
240
        template<typename U>
241
        explicit Matrix4(const U* ptr) : TransformBaseReal(ptr) {}
242
        explicit Matrix4 (const Real* arr)
243
0
        {
244
0
            memcpy(m,arr,16*sizeof(Real));
245
0
        }
246
247
        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
248
         */
249
250
        explicit Matrix4(const Matrix3& m3x3)
251
0
        {
252
0
          operator=(IDENTITY);
253
0
          operator=(m3x3);
254
0
        }
255
256
        /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Quaternion.
257
         */
258
        
259
        explicit Matrix4(const Quaternion& rot)
260
0
        {
261
0
          Matrix3 m3x3;
262
0
          rot.ToRotationMatrix(m3x3);
263
0
          *this = IDENTITY;
264
0
          *this = m3x3;
265
0
        }
266
        
267
0
        Matrix4& operator=(const Matrix3& mat3) {
268
0
            set3x3Matrix(mat3);
269
0
            return *this;
270
0
        }
271
272
0
        OGRE_DEPRECATED Matrix4 concatenate(const Matrix4& m2) const { return *this * m2; }
273
274
        /** Tests 2 matrices for equality.
275
        */
276
        inline bool operator == ( const Matrix4& m2 ) const
277
0
        {
278
0
            if( 
279
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] ||
280
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] ||
281
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] ||
282
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] )
283
0
                return false;
284
0
            return true;
285
0
        }
286
287
        /** Tests 2 matrices for inequality.
288
        */
289
        inline bool operator != ( const Matrix4& m2 ) const
290
0
        {
291
0
            if( 
292
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] ||
293
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] ||
294
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] ||
295
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] )
296
0
                return true;
297
0
            return false;
298
0
        }
299
300
        static const Matrix4 ZERO;
301
        static const Matrix4 IDENTITY;
302
        /** Useful little matrix which takes 2D clipspace {-1, 1} to {0,1}
303
            and inverts the Y. */
304
        static const Matrix4 CLIPSPACE2DTOIMAGESPACE;
305
306
        inline Matrix4 operator*(Real scalar) const
307
0
        {
308
0
            return Matrix4(
309
0
                scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3],
310
0
                scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3],
311
0
                scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3],
312
0
                scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]);
313
0
        }
314
        
315
        Matrix4 adjoint() const;
316
        Matrix4 inverse() const;
317
    };
318
319
    /// Transform specialization for 3D Affine - encapsulating a 3x4 Matrix
320
    class _OgreExport Affine3 : public TransformBaseReal
321
    {
322
    public:
323
        /// Do <b>NOT</b> initialize the matrix for efficiency.
324
0
        Affine3() {}
325
326
        /// @copydoc TransformBaseReal::makeTransform
327
        Affine3(const Vector3& position, const Quaternion& orientation, const Vector3& scale = Vector3::UNIT_SCALE)
328
0
        {
329
0
            makeTransform(position, scale, orientation);
330
0
        }
331
332
        template<typename U>
333
        explicit Affine3(const U* ptr)
334
        {
335
            for (int i = 0; i < 3; i++)
336
                for (int j = 0; j < 4; j++)
337
                    m[i][j] = Real(ptr[i*4 + j]);
338
            m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1;
339
        }
340
341
        explicit Affine3(const Real* arr)
342
0
        {
343
0
            memcpy(m, arr, 12 * sizeof(Real));
344
0
            m[3][0] = 0, m[3][1] = 0, m[3][2] = 0, m[3][3] = 1;
345
0
        }
346
347
        Affine3(
348
            Real m00, Real m01, Real m02, Real m03,
349
            Real m10, Real m11, Real m12, Real m13,
350
            Real m20, Real m21, Real m22, Real m23)
351
0
        {
352
0
            m[0][0] = m00; m[0][1] = m01; m[0][2] = m02; m[0][3] = m03;
353
0
            m[1][0] = m10; m[1][1] = m11; m[1][2] = m12; m[1][3] = m13;
354
0
            m[2][0] = m20; m[2][1] = m21; m[2][2] = m22; m[2][3] = m23;
355
0
            m[3][0] = 0;   m[3][1] = 0;   m[3][2] = 0;   m[3][3] = 1;
356
0
        }
357
358
        /// extract the Affine part of a Matrix4
359
        explicit Affine3(const Matrix4& mat)
360
0
        {
361
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];
362
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];
363
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];
364
0
            m[3][0] = 0;         m[3][1] = 0;         m[3][2] = 0;         m[3][3] = 1;
365
0
        }
366
367
0
        Affine3& operator=(const Matrix3& mat3) {
368
0
            set3x3Matrix(mat3);
369
0
            return *this;
370
0
        }
371
372
        /** Tests 2 matrices for equality.
373
        */
374
        bool operator==(const Affine3& m2) const
375
0
        {
376
0
            if(
377
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] ||
378
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] ||
379
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] )
380
0
                return false;
381
0
            return true;
382
0
        }
383
384
0
        bool operator!=(const Affine3& m2) const { return !(*this == m2); }
385
386
        Affine3 inverse() const;
387
388
        /** Decompose to orientation / scale / position.
389
        */
390
        void decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const;
391
392
        /// every Affine3 transform is also a _const_ Matrix4
393
0
        operator const Matrix4&() const { return reinterpret_cast<const Matrix4&>(*this); }
394
395
        using TransformBaseReal::getTrans;
396
397
        /** Gets a translation matrix.
398
        */
399
        static Affine3 getTrans( const Vector3& v )
400
0
        {
401
0
            return getTrans(v.x, v.y, v.z);
402
0
        }
403
404
        /** Gets a translation matrix - variation for not using a vector.
405
        */
406
        static Affine3 getTrans( Real t_x, Real t_y, Real t_z )
407
0
        {
408
0
            return Affine3(1, 0, 0, t_x,
409
0
                           0, 1, 0, t_y,
410
0
                           0, 0, 1, t_z);
411
0
        }
412
413
        /** Gets a scale matrix.
414
        */
415
        static Affine3 getScale( const Vector3& v )
416
0
        {
417
0
            return getScale(v.x, v.y, v.z);
418
0
        }
419
420
        /** Gets a scale matrix - variation for not using a vector.
421
        */
422
        static Affine3 getScale( Real s_x, Real s_y, Real s_z )
423
0
        {
424
0
            return Affine3(s_x, 0, 0, 0,
425
0
                           0, s_y, 0, 0,
426
0
                           0, 0, s_z, 0);
427
0
        }
428
429
430
        static const Affine3 ZERO;
431
        static const Affine3 IDENTITY;
432
    };
433
434
    inline Matrix4 TransformBaseReal::transpose() const
435
0
    {
436
0
        return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
437
0
                       m[0][1], m[1][1], m[2][1], m[3][1],
438
0
                       m[0][2], m[1][2], m[2][2], m[3][2],
439
0
                       m[0][3], m[1][3], m[2][3], m[3][3]);
440
0
    }
441
442
    /** Matrix addition.
443
    */
444
    inline Matrix4 operator+(const Matrix4& m, const Matrix4& m2)
445
0
    {
446
0
        Matrix4 r;
447
0
448
0
        r[0][0] = m[0][0] + m2[0][0];
449
0
        r[0][1] = m[0][1] + m2[0][1];
450
0
        r[0][2] = m[0][2] + m2[0][2];
451
0
        r[0][3] = m[0][3] + m2[0][3];
452
0
453
0
        r[1][0] = m[1][0] + m2[1][0];
454
0
        r[1][1] = m[1][1] + m2[1][1];
455
0
        r[1][2] = m[1][2] + m2[1][2];
456
0
        r[1][3] = m[1][3] + m2[1][3];
457
0
458
0
        r[2][0] = m[2][0] + m2[2][0];
459
0
        r[2][1] = m[2][1] + m2[2][1];
460
0
        r[2][2] = m[2][2] + m2[2][2];
461
0
        r[2][3] = m[2][3] + m2[2][3];
462
0
463
0
        r[3][0] = m[3][0] + m2[3][0];
464
0
        r[3][1] = m[3][1] + m2[3][1];
465
0
        r[3][2] = m[3][2] + m2[3][2];
466
0
        r[3][3] = m[3][3] + m2[3][3];
467
0
468
0
        return r;
469
0
    }
470
471
    /** Matrix subtraction.
472
    */
473
    inline Matrix4 operator-(const Matrix4& m, const Matrix4& m2)
474
0
    {
475
0
        Matrix4 r;
476
0
        r[0][0] = m[0][0] - m2[0][0];
477
0
        r[0][1] = m[0][1] - m2[0][1];
478
0
        r[0][2] = m[0][2] - m2[0][2];
479
0
        r[0][3] = m[0][3] - m2[0][3];
480
0
481
0
        r[1][0] = m[1][0] - m2[1][0];
482
0
        r[1][1] = m[1][1] - m2[1][1];
483
0
        r[1][2] = m[1][2] - m2[1][2];
484
0
        r[1][3] = m[1][3] - m2[1][3];
485
0
486
0
        r[2][0] = m[2][0] - m2[2][0];
487
0
        r[2][1] = m[2][1] - m2[2][1];
488
0
        r[2][2] = m[2][2] - m2[2][2];
489
0
        r[2][3] = m[2][3] - m2[2][3];
490
0
491
0
        r[3][0] = m[3][0] - m2[3][0];
492
0
        r[3][1] = m[3][1] - m2[3][1];
493
0
        r[3][2] = m[3][2] - m2[3][2];
494
0
        r[3][3] = m[3][3] - m2[3][3];
495
0
496
0
        return r;
497
0
    }
498
499
    inline Matrix4 operator*(const Matrix4 &m, const Matrix4 &m2)
500
0
    {
501
0
        Matrix4 r;
502
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];
503
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];
504
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];
505
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];
506
0
507
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];
508
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];
509
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];
510
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];
511
0
512
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];
513
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];
514
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];
515
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];
516
0
517
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];
518
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];
519
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];
520
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];
521
0
522
0
        return r;
523
0
    }
524
    inline Affine3 operator*(const Affine3 &m, const Affine3 &m2)
525
0
    {
526
0
        return Affine3(
527
0
            m[0][0] * m2[0][0] + m[0][1] * m2[1][0] + m[0][2] * m2[2][0],
528
0
            m[0][0] * m2[0][1] + m[0][1] * m2[1][1] + m[0][2] * m2[2][1],
529
0
            m[0][0] * m2[0][2] + m[0][1] * m2[1][2] + m[0][2] * m2[2][2],
530
0
            m[0][0] * m2[0][3] + m[0][1] * m2[1][3] + m[0][2] * m2[2][3] + m[0][3],
531
0
532
0
            m[1][0] * m2[0][0] + m[1][1] * m2[1][0] + m[1][2] * m2[2][0],
533
0
            m[1][0] * m2[0][1] + m[1][1] * m2[1][1] + m[1][2] * m2[2][1],
534
0
            m[1][0] * m2[0][2] + m[1][1] * m2[1][2] + m[1][2] * m2[2][2],
535
0
            m[1][0] * m2[0][3] + m[1][1] * m2[1][3] + m[1][2] * m2[2][3] + m[1][3],
536
0
537
0
            m[2][0] * m2[0][0] + m[2][1] * m2[1][0] + m[2][2] * m2[2][0],
538
0
            m[2][0] * m2[0][1] + m[2][1] * m2[1][1] + m[2][2] * m2[2][1],
539
0
            m[2][0] * m2[0][2] + m[2][1] * m2[1][2] + m[2][2] * m2[2][2],
540
0
            m[2][0] * m2[0][3] + m[2][1] * m2[1][3] + m[2][2] * m2[2][3] + m[2][3]);
541
0
    }
542
543
    /** Vector transformation using '*'.
544
545
        Transforms the given 3-D vector by the matrix, projecting the
546
        result back into <i>w</i> = 1.
547
        @note
548
            This means that the initial <i>w</i> is considered to be 1.0,
549
            and then all the tree elements of the resulting 3-D vector are
550
            divided by the resulting <i>w</i>.
551
    */
552
    inline Vector3 operator*(const Matrix4& m, const Vector3& v)
553
0
    {
554
0
        Vector3 r;
555
0
556
0
        Real fInvW = 1.0f / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] );
557
0
558
0
        r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
559
0
        r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
560
0
        r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
561
0
562
0
        return r;
563
0
    }
564
    /// @overload
565
    inline Vector3 operator*(const Affine3& m,const Vector3& v)
566
0
    {
567
0
        return Vector3(
568
0
                m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3],
569
0
                m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
570
0
                m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
571
0
    }
572
573
    inline Vector4 operator*(const Matrix4& m, const Vector4& v)
574
0
    {
575
0
        return Vector4(
576
0
            m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
577
0
            m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
578
0
            m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
579
0
            m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w);
580
0
    }
581
    inline Vector4 operator*(const Affine3& m, const Vector4& v)
582
0
    {
583
0
        return Vector4(
584
0
            m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
585
0
            m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
586
0
            m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
587
0
            v.w);
588
0
    }
589
590
    inline Vector4 operator * (const Vector4& v, const Matrix4& mat)
591
0
    {
592
0
        return Vector4(
593
0
            v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + v.w*mat[3][0],
594
0
            v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + v.w*mat[3][1],
595
0
            v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + v.w*mat[3][2],
596
0
            v.x*mat[0][3] + v.y*mat[1][3] + v.z*mat[2][3] + v.w*mat[3][3]
597
0
            );
598
0
    }
599
    /** @} */
600
    /** @} */
601
602
}
603
#endif