Coverage Report

Created: 2025-07-11 06:36

/src/ogre/OgreMain/include/OgreVector.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 __Vector_H__
29
#define __Vector_H__
30
31
32
#include "OgrePrerequisites.h"
33
#include "OgreMath.h"
34
#include "OgreQuaternion.h"
35
36
namespace Ogre
37
{
38
39
    /** \addtogroup Core
40
    *  @{
41
    */
42
    /** \addtogroup Math
43
    *  @{
44
    */
45
    /// helper class to implement legacy API. Notably x, y, z access
46
    template <int dims, typename T> struct VectorBase
47
    {
48
        VectorBase() {}
49
        constexpr VectorBase(T _x, T _y)
50
        {
51
            static_assert(dims > 1, "must have at least 2 dimensions");
52
            data[0] = _x; data[1] = _y;
53
        }
54
        constexpr VectorBase(T _x, T _y, T _z)
55
0
        {
56
0
            static_assert(dims > 2, "must have at least 3 dimensions");
57
0
            data[0] = _x; data[1] = _y; data[2] = _z;
58
0
        }
59
        constexpr VectorBase(T _x, T _y, T _z, T _w)
60
        {
61
            static_assert(dims > 3, "must have at least 4 dimensions");
62
            data[0] = _x; data[1] = _y; data[2] = _z; data[3] = _w;
63
        }
64
        T data[dims];
65
        T* ptr() { return data; }
66
0
        const T* ptr() const { return data; }
67
    };
68
    template <> struct _OgreExport VectorBase<2, Real>
69
    {
70
0
        VectorBase() {}
71
0
        constexpr VectorBase(Real _x, Real _y) : x(_x), y(_y) {}
72
        Real x, y;
73
0
        Real* ptr() { return &x; }
74
0
        const Real* ptr() const { return &x; }
75
76
        /** Returns a vector at a point half way between this and the passed
77
            in vector.
78
        */
79
        Vector2 midPoint( const Vector2& vec ) const;
80
81
        /** Calculates the 2 dimensional cross-product of 2 vectors, which results
82
            in a single floating point value which is 2 times the area of the triangle.
83
        */
84
        Real crossProduct( const VectorBase& rkVector ) const
85
0
        {
86
0
            return x * rkVector.y - y * rkVector.x;
87
0
        }
88
89
        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
90
91
            This method will return a vector which is perpendicular to this
92
            vector. There are an infinite number of possibilities but this
93
            method will guarantee to generate one of them. If you need more
94
            control you should use the Quaternion class.
95
        */
96
        Vector2 perpendicular(void) const;
97
98
        /** Generates a new random vector which deviates from this vector by a
99
            given angle in a random direction.
100
101
            This method assumes that the random number generator has already
102
            been seeded appropriately.
103
            @param angle
104
                The angle at which to deviate in radians
105
            @return
106
                A random vector which deviates from this vector by angle. This
107
                vector will not be normalised, normalise it if you wish
108
                afterwards.
109
        */
110
        Vector2 randomDeviant(Radian angle) const;
111
112
        /**  Gets the oriented angle between 2 vectors.
113
114
            Vectors do not have to be unit-length but must represent directions.
115
            The angle is comprised between 0 and 2 PI.
116
        */
117
        Radian angleTo(const Vector2& other) const;
118
119
        // special points
120
        static const Vector2 &ZERO;
121
        static const Vector2 &UNIT_X;
122
        static const Vector2 &UNIT_Y;
123
        static const Vector2 &NEGATIVE_UNIT_X;
124
        static const Vector2 &NEGATIVE_UNIT_Y;
125
        static const Vector2 &UNIT_SCALE;
126
    };
127
128
    template <> struct _OgreExport VectorBase<3, Real>
129
    {
130
8
        VectorBase() {}
131
0
        constexpr VectorBase(Real _x, Real _y, Real _z) : x(_x), y(_y), z(_z) {}
132
        Real x, y, z;
133
0
        Real* ptr() { return &x; }
134
0
        const Real* ptr() const { return &x; }
135
136
        /** Calculates the cross-product of 2 vectors, i.e. the vector that
137
            lies perpendicular to them both.
138
139
            The cross-product is normally used to calculate the normal
140
            vector of a plane, by calculating the cross-product of 2
141
            non-equivalent vectors which lie on the plane (e.g. 2 edges
142
            of a triangle).
143
            @param rkVector
144
                Vector which, together with this one, will be used to
145
                calculate the cross-product.
146
            @return
147
                A vector which is the result of the cross-product. This
148
                vector will <b>NOT</b> be normalised, to maximise efficiency
149
                - call Vector3::normalise on the result if you wish this to
150
                be done. As for which side the resultant vector will be on, the
151
                returned vector will be on the side from which the arc from 'this'
152
                to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z)
153
                = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
154
                This is because OGRE uses a right-handed coordinate system.
155
            @par
156
                For a clearer explanation, look a the left and the bottom edges
157
                of your monitor's screen. Assume that the first vector is the
158
                left edge and the second vector is the bottom edge, both of
159
                them starting from the lower-left corner of the screen. The
160
                resulting vector is going to be perpendicular to both of them
161
                and will go <i>inside</i> the screen, towards the cathode tube
162
                (assuming you're using a CRT monitor, of course).
163
        */
164
        Vector3 crossProduct( const Vector3& rkVector ) const;
165
166
        /** Generates a vector perpendicular to this vector (eg an 'up' vector).
167
168
            This method will return a vector which is perpendicular to this
169
            vector. There are an infinite number of possibilities but this
170
            method will guarantee to generate one of them. If you need more
171
            control you should use the Quaternion class.
172
        */
173
        Vector3 perpendicular(void) const;
174
175
        /** Calculates the absolute dot (scalar) product of this vector with another.
176
177
            This function work similar dotProduct, except it use absolute value
178
            of each component of the vector to computing.
179
            @param
180
                vec Vector with which to calculate the absolute dot product (together
181
                with this one).
182
            @return
183
                A Real representing the absolute dot product value.
184
        */
185
        Real absDotProduct(const VectorBase& vec) const
186
0
        {
187
0
            return Math::Abs(x * vec.x) + Math::Abs(y * vec.y) + Math::Abs(z * vec.z);
188
0
        }
189
190
        /** Returns a vector at a point half way between this and the passed
191
            in vector.
192
        */
193
        Vector3 midPoint( const Vector3& vec ) const;
194
195
        /** Generates a new random vector which deviates from this vector by a
196
            given angle in a random direction.
197
198
            This method assumes that the random number generator has already
199
            been seeded appropriately.
200
            @param
201
                angle The angle at which to deviate
202
            @param
203
                up Any vector perpendicular to this one (which could generated
204
                by cross-product of this vector and any other non-colinear
205
                vector). If you choose not to provide this the function will
206
                derive one on it's own, however if you provide one yourself the
207
                function will be faster (this allows you to reuse up vectors if
208
                you call this method more than once)
209
            @return
210
                A random vector which deviates from this vector by angle. This
211
                vector will not be normalised, normalise it if you wish
212
                afterwards.
213
        */
214
        Vector3 randomDeviant(const Radian& angle, const Vector3& up = ZERO) const;
215
216
        /** Gets the shortest arc quaternion to rotate this vector to the destination
217
            vector.
218
219
            If you call this with a dest vector that is close to the inverse
220
            of this vector, we will rotate 180 degrees around the 'fallbackAxis'
221
            (if specified, or a generated axis if not) since in this case
222
            ANY axis of rotation is valid.
223
        */
224
        Quaternion getRotationTo(const Vector3& dest, const Vector3& fallbackAxis = ZERO) const;
225
226
        /** Returns whether this vector is within a positional tolerance
227
            of another vector, also take scale of the vectors into account.
228
        @param rhs The vector to compare with
229
        @param tolerance The amount (related to the scale of vectors) that distance
230
            of the vector may vary by and still be considered close
231
        */
232
        bool positionCloses(const Vector3& rhs, Real tolerance = 1e-03f) const;
233
234
        /** Returns whether this vector is within a directional tolerance
235
            of another vector.
236
        @param rhs The vector to compare with
237
        @param tolerance The maximum angle by which the vectors may vary and
238
            still be considered equal
239
        @note Both vectors should be normalised.
240
        */
241
        bool directionEquals(const Vector3& rhs, const Radian& tolerance) const;
242
243
        /// Extract the primary (dominant) axis from this direction vector
244
        const Vector3& primaryAxis() const;
245
246
        // special points
247
        static const Vector3 &ZERO;
248
        static const Vector3 &UNIT_X;
249
        static const Vector3 &UNIT_Y;
250
        static const Vector3 &UNIT_Z;
251
        static const Vector3 &NEGATIVE_UNIT_X;
252
        static const Vector3 &NEGATIVE_UNIT_Y;
253
        static const Vector3 &NEGATIVE_UNIT_Z;
254
        static const Vector3 &UNIT_SCALE;
255
    };
256
257
    template <> struct _OgreExport VectorBase<4, Real>
258
    {
259
0
        VectorBase() {}
260
0
        constexpr VectorBase(Real _x, Real _y, Real _z, Real _w) : x(_x), y(_y), z(_z), w(_w) {}
261
        Real x, y, z, w;
262
0
        Real* ptr() { return &x; }
263
0
        const Real* ptr() const { return &x; }
264
265
        // special points
266
        static const Vector4 &ZERO;
267
    };
268
269
    /** Standard N-dimensional vector.
270
271
        A direction in N-D space represented as distances along the
272
        orthogonal axes. Note that positions, directions and
273
        scaling factors can be represented by a vector, depending on how
274
        you interpret the values.
275
    */
276
    template<int dims, typename T>
277
    class _OgreMaybeExport Vector : public VectorBase<dims, T>
278
    {
279
    public:
280
        using VectorBase<dims, T>::ptr;
281
282
        /** Default constructor.
283
            @note It does <b>NOT</b> initialize the vector for efficiency.
284
        */
285
8
        Vector() {}
Ogre::Vector<3, float>::Vector()
Line
Count
Source
285
8
        Vector() {}
Unexecuted instantiation: Ogre::Vector<2, float>::Vector()
Unexecuted instantiation: Ogre::Vector<4, float>::Vector()
286
0
        constexpr Vector(T _x, T _y) : VectorBase<dims, T>(_x, _y) {}
287
0
        constexpr Vector(T _x, T _y, T _z) : VectorBase<dims, T>(_x, _y, _z) {}
Unexecuted instantiation: Ogre::Vector<3, float>::Vector(float, float, float)
Unexecuted instantiation: Ogre::Vector<3, int>::Vector(int, int, int)
288
0
        constexpr Vector(T _x, T _y, T _z, T _w) : VectorBase<dims, T>(_x, _y, _z, _w) {}
289
290
        // use enable_if as function parameter for VC < 2017 compatibility
291
        template <int N = dims>
292
        explicit Vector(const typename std::enable_if<N == 4, Vector<3, T>>::type& rhs, T fW = 1.0f) : VectorBase<dims, T>(rhs[0], rhs[1], rhs[2], fW) {}
293
294
        template<typename U>
295
0
        explicit Vector(const U* _ptr) {
296
0
            for (int i = 0; i < dims; i++)
297
0
                ptr()[i] = T(_ptr[i]);
298
0
        }
Unexecuted instantiation: Ogre::Vector<3, float>::Vector<float>(float const*)
Unexecuted instantiation: Ogre::Vector<3, float>::Vector<int>(int const*)
299
300
        template<typename U>
301
        explicit Vector(const Vector<dims, U>& o) : Vector(o.ptr()) {}
302
303
304
        explicit Vector(T s)
305
0
        {
306
0
            for (int i = 0; i < dims; i++)
307
0
                ptr()[i] = s;
308
0
        }
309
310
        /** Swizzle-like narrowing operations
311
        */
312
        Vector<3, T> xyz() const
313
0
        {
314
0
            static_assert(dims > 3, "just use assignment");
315
0
            return Vector<3, T>(ptr());
316
0
        }
317
        Vector<2, T> xy() const
318
        {
319
            static_assert(dims > 2, "just use assignment");
320
            return Vector<2, T>(ptr());
321
        }
322
323
        T operator[](size_t i) const
324
0
        {
325
0
            assert(i < dims);
326
0
            return ptr()[i];
327
0
        }
Unexecuted instantiation: Ogre::Vector<3, float>::operator[](unsigned long) const
Unexecuted instantiation: Ogre::Vector<3, int>::operator[](unsigned long) const
Unexecuted instantiation: Ogre::Vector<4, float>::operator[](unsigned long) const
328
329
        T& operator[](size_t i)
330
0
        {
331
0
            assert(i < dims);
332
0
            return ptr()[i];
333
0
        }
Unexecuted instantiation: Ogre::Vector<4, float>::operator[](unsigned long)
Unexecuted instantiation: Ogre::Vector<2, float>::operator[](unsigned long)
Unexecuted instantiation: Ogre::Vector<3, float>::operator[](unsigned long)
334
335
        bool operator==(const Vector& v) const
336
0
        {
337
0
            for (int i = 0; i < dims; i++)
338
0
                if (ptr()[i] != v[i])
339
0
                    return false;
340
0
            return true;
341
0
        }
342
343
        /** Returns whether this vector is within a positional tolerance
344
            of another vector.
345
        @param rhs The vector to compare with
346
        @param tolerance The amount that each element of the vector may vary by
347
            and still be considered equal
348
        */
349
        bool positionEquals(const Vector& rhs, Real tolerance = 1e-03f) const
350
        {
351
            for (int i = 0; i < dims; i++)
352
                if (!Math::RealEqual(ptr()[i], rhs[i], tolerance))
353
                    return false;
354
            return true;
355
        }
356
357
0
        bool operator!=(const Vector& v) const { return !(*this == v); }
358
359
        /** Returns true if the vector's scalar components are all greater
360
            that the ones of the vector it is compared against.
361
        */
362
        bool operator<(const Vector& rhs) const
363
0
        {
364
0
            for (int i = 0; i < dims; i++)
365
0
                if (!(ptr()[i] < rhs[i]))
366
0
                    return false;
367
0
            return true;
368
0
        }
369
370
        /** Returns true if the vector's scalar components are all smaller
371
            that the ones of the vector it is compared against.
372
        */
373
        bool operator>(const Vector& rhs) const
374
0
        {
375
0
            for (int i = 0; i < dims; i++)
376
0
                if (!(ptr()[i] > rhs[i]))
377
0
                    return false;
378
0
            return true;
379
0
        }
380
381
        /** Sets this vector's components to the minimum of its own and the
382
            ones of the passed in vector.
383
384
            'Minimum' in this case means the combination of the lowest
385
            value of x, y and z from both vectors. Lowest is taken just
386
            numerically, not magnitude, so -1 < 0.
387
        */
388
        void makeFloor(const Vector& cmp)
389
0
        {
390
0
            for (int i = 0; i < dims; i++)
391
0
                if (cmp[i] < ptr()[i])
392
0
                    ptr()[i] = cmp[i];
393
0
        }
394
395
        /** Sets this vector's components to the maximum of its own and the
396
            ones of the passed in vector.
397
398
            'Maximum' in this case means the combination of the highest
399
            value of x, y and z from both vectors. Highest is taken just
400
            numerically, not magnitude, so 1 > -3.
401
        */
402
        void makeCeil(const Vector& cmp)
403
0
        {
404
0
            for (int i = 0; i < dims; i++)
405
0
                if (cmp[i] > ptr()[i])
406
0
                    ptr()[i] = cmp[i];
407
0
        }
408
409
        /** Calculates the dot (scalar) product of this vector with another.
410
411
            The dot product can be used to calculate the angle between 2
412
            vectors. If both are unit vectors, the dot product is the
413
            cosine of the angle; otherwise the dot product must be
414
            divided by the product of the lengths of both vectors to get
415
            the cosine of the angle. This result can further be used to
416
            calculate the distance of a point from a plane.
417
            @param
418
                vec Vector with which to calculate the dot product (together
419
                with this one).
420
            @return
421
                A float representing the dot product value.
422
        */
423
        T dotProduct(const VectorBase<dims, T>& vec) const
424
0
        {
425
0
            T ret = 0;
426
0
            for (int i = 0; i < dims; i++)
427
0
                ret += ptr()[i] * vec.ptr()[i];
428
0
            return ret;
429
0
        }
Unexecuted instantiation: Ogre::Vector<2, float>::dotProduct(Ogre::VectorBase<2, float> const&) const
Unexecuted instantiation: Ogre::Vector<3, float>::dotProduct(Ogre::VectorBase<3, float> const&) const
430
431
        /** Returns the square of the length(magnitude) of the vector.
432
433
            This  method is for efficiency - calculating the actual
434
            length of a vector requires a square root, which is expensive
435
            in terms of the operations required. This method returns the
436
            square of the length of the vector, i.e. the same as the
437
            length but before the square root is taken. Use this if you
438
            want to find the longest / shortest vector without incurring
439
            the square root.
440
        */
441
0
        T squaredLength() const { return dotProduct(*this); }
Unexecuted instantiation: Ogre::Vector<2, float>::squaredLength() const
Unexecuted instantiation: Ogre::Vector<3, float>::squaredLength() const
442
443
        /** Returns true if this vector is zero length. */
444
        bool isZeroLength() const
445
0
        {
446
0
            return squaredLength() < 1e-06 * 1e-06;
447
0
        }
448
449
        /** Returns the length (magnitude) of the vector.
450
            @warning
451
                This operation requires a square root and is expensive in
452
                terms of CPU operations. If you don't need to know the exact
453
                length (e.g. for just comparing lengths) use squaredLength()
454
                instead.
455
        */
456
0
        Real length() const { return Math::Sqrt(squaredLength()); }
Unexecuted instantiation: Ogre::Vector<2, float>::length() const
Unexecuted instantiation: Ogre::Vector<3, float>::length() const
457
458
        /** Returns the distance to another vector.
459
            @warning
460
                This operation requires a square root and is expensive in
461
                terms of CPU operations. If you don't need to know the exact
462
                distance (e.g. for just comparing distances) use squaredDistance()
463
                instead.
464
        */
465
        Real distance(const Vector& rhs) const
466
0
        {
467
0
            return (*this - rhs).length();
468
0
        }
469
470
        /** Returns the square of the distance to another vector.
471
472
            This method is for efficiency - calculating the actual
473
            distance to another vector requires a square root, which is
474
            expensive in terms of the operations required. This method
475
            returns the square of the distance to another vector, i.e.
476
            the same as the distance but before the square root is taken.
477
            Use this if you want to find the longest / shortest distance
478
            without incurring the square root.
479
        */
480
        T squaredDistance(const Vector& rhs) const
481
0
        {
482
0
            return (*this - rhs).squaredLength();
483
0
        }
484
485
        /** Normalises the vector.
486
487
            This method normalises the vector such that it's
488
            length / magnitude is 1. The result is called a unit vector.
489
            @note
490
                This function will not crash for zero-sized vectors, but there
491
                will be no changes made to their components.
492
            @return The previous length of the vector.
493
        */
494
        Real normalise()
495
0
        {
496
0
            Real fLength = length();
497
498
            // Will also work for zero-sized vectors, but will change nothing
499
            // We're not using epsilons because we don't need to.
500
            // Read http://www.ogre3d.org/forums/viewtopic.php?f=4&t=61259
501
0
            if (fLength > Real(0.0f))
502
0
            {
503
0
                Real fInvLength = 1.0f / fLength;
504
0
                for (int i = 0; i < dims; i++)
505
0
                    ptr()[i] *= fInvLength;
506
0
            }
507
508
0
            return fLength;
509
0
        }
510
511
        /** As normalise, except that this vector is unaffected and the
512
            normalised vector is returned as a copy. */
513
        Vector normalisedCopy() const
514
0
        {
515
0
            Vector ret = *this;
516
0
            ret.normalise();
517
0
            return ret;
518
0
        }
519
520
#ifndef OGRE_FAST_MATH
521
        /// Check whether this vector contains valid values
522
        bool isNaN() const
523
        {
524
            for (int i = 0; i < dims; i++)
525
                if (Math::isNaN(ptr()[i]))
526
                    return true;
527
            return false;
528
        }
529
#endif
530
531
        /** Gets the angle between 2 vectors.
532
533
            Vectors do not have to be unit-length but must represent directions.
534
        */
535
        Radian angleBetween(const Vector& dest) const
536
0
        {
537
0
            Real lenProduct = length() * dest.length();
538
0
539
0
            // Divide by zero check
540
0
            if(lenProduct < 1e-6f)
541
0
                lenProduct = 1e-6f;
542
0
543
0
            Real f = dotProduct(dest) / lenProduct;
544
0
545
0
            f = Math::Clamp(f, (Real)-1.0, (Real)1.0);
546
0
            return Math::ACos(f);
547
0
548
0
        }
549
550
        /** Calculates a reflection vector to the plane with the given normal .
551
        @note assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
552
        */
553
        Vector reflect(const Vector& normal) const { return *this - (2 * dotProduct(normal) * normal); }
554
555
        // Vector: arithmetic updates
556
        Vector& operator*=(Real s)
557
0
        {
558
0
            for (int i = 0; i < dims; i++)
559
0
                ptr()[i] *= s;
560
0
            return *this;
561
0
        }
562
563
        Vector& operator/=(Real s)
564
0
        {
565
0
            assert( s != 0.0 ); // legacy assert
566
0
            Real fInv = 1.0f/s;
567
0
            for (int i = 0; i < dims; i++)
568
0
                ptr()[i] *= fInv;
569
0
            return *this;
570
0
        }
571
572
        Vector& operator+=(Real s)
573
0
        {
574
0
            for (int i = 0; i < dims; i++)
575
0
                ptr()[i] += s;
576
0
            return *this;
577
0
        }
578
579
        Vector& operator-=(Real s)
580
        {
581
            for (int i = 0; i < dims; i++)
582
                ptr()[i] -= s;
583
            return *this;
584
        }
585
586
        Vector& operator+=(const Vector& b)
587
0
        {
588
0
            for (int i = 0; i < dims; i++)
589
0
                ptr()[i] += b[i];
590
0
            return *this;
591
0
        }
592
593
        Vector& operator-=(const Vector& b)
594
0
        {
595
0
            for (int i = 0; i < dims; i++)
596
0
                ptr()[i] -= b[i];
597
0
            return *this;
598
0
        }
599
600
        Vector& operator*=(const Vector& b)
601
0
        {
602
0
            for (int i = 0; i < dims; i++)
603
0
                ptr()[i] *= b[i];
604
0
            return *this;
605
0
        }
606
607
        Vector& operator/=(const Vector& b)
608
        {
609
            for (int i = 0; i < dims; i++)
610
                ptr()[i] /= b[i];
611
            return *this;
612
        }
613
614
        // Scalar * Vector
615
        friend Vector operator*(Real s, Vector v)
616
0
        {
617
0
            v *= s;
618
0
            return v;
619
0
        }
620
621
        friend Vector operator+(Real s, Vector v)
622
        {
623
            v += s;
624
            return v;
625
        }
626
627
        friend Vector operator-(Real s, const Vector& v)
628
        {
629
            Vector ret;
630
            for (int i = 0; i < dims; i++)
631
                ret[i] = s - v[i];
632
            return ret;
633
        }
634
635
        friend Vector operator/(Real s, const Vector& v)
636
        {
637
            Vector ret;
638
            for (int i = 0; i < dims; i++)
639
                ret[i] = s / v[i];
640
            return ret;
641
        }
642
643
        // Vector * Scalar
644
        Vector operator-() const
645
0
        {
646
0
            return -1 * *this;
647
0
        }
648
649
        const Vector& operator+() const
650
        {
651
            return *this;
652
        }
653
654
        Vector operator*(Real s) const
655
0
        {
656
0
            return s * *this;
657
0
        }
658
659
        Vector operator/(Real s) const
660
0
        {
661
0
            assert( s != 0.0 ); // legacy assert
662
0
            Real fInv = 1.0f / s;
663
0
            return fInv * *this;
664
0
        }
665
666
        Vector operator-(Real s) const
667
        {
668
            return -s + *this;
669
        }
670
671
        Vector operator+(Real s) const
672
        {
673
            return s + *this;
674
        }
675
676
        // Vector * Vector
677
        Vector operator+(const Vector& b) const
678
0
        {
679
0
            Vector ret = *this;
680
0
            ret += b;
681
0
            return ret;
682
0
        }
683
684
        Vector operator-(const Vector& b) const
685
0
        {
686
0
            Vector ret = *this;
687
0
            ret -= b;
688
0
            return ret;
689
0
        }
690
691
        Vector operator*(const Vector& b) const
692
0
        {
693
0
            Vector ret = *this;
694
0
            ret *= b;
695
0
            return ret;
696
0
        }
697
698
        Vector operator/(const Vector& b) const
699
        {
700
            Vector ret = *this;
701
            ret /= b;
702
            return ret;
703
        }
704
705
        friend std::ostream& operator<<(std::ostream& o, const Vector& v)
706
0
        {
707
0
            o << "Vector" << dims << "(";
708
0
            for (int i = 0; i < dims; i++) {
709
0
                o << v[i];
710
0
                if(i != dims - 1) o << ", ";
711
0
            }
712
0
            o <<  ")";
713
0
            return o;
714
0
        }
715
    };
716
717
    inline Vector2 VectorBase<2, Real>::midPoint( const Vector2& vec ) const
718
0
    {
719
0
        return Vector2(
720
0
            ( x + vec.x ) * 0.5f,
721
0
            ( y + vec.y ) * 0.5f );
722
0
    }
723
724
    inline Vector2 VectorBase<2, Real>::randomDeviant(Radian angle) const
725
0
    {
726
0
        angle *= Math::RangeRandom(-1, 1);
727
0
        Real cosa = Math::Cos(angle);
728
0
        Real sina = Math::Sin(angle);
729
0
        return Vector2(cosa * x - sina * y,
730
0
                       sina * x + cosa * y);
731
0
    }
732
733
    inline Radian VectorBase<2, Real>::angleTo(const Vector2& other) const
734
0
    {
735
0
        Radian angle = ((const Vector2*)this)->angleBetween(other);
736
0
737
0
        if (crossProduct(other)<0)
738
0
            angle = Radian(Math::TWO_PI) - angle;
739
0
740
0
        return angle;
741
0
    }
742
743
    inline Vector2 VectorBase<2, Real>::perpendicular(void) const
744
0
    {
745
0
        return Vector2(-y, x);
746
0
    }
747
748
    inline Vector3 VectorBase<3, Real>::perpendicular() const
749
0
    {
750
0
        // From Sam Hocevar's article "On picking an orthogonal
751
0
        // vector (and combing coconuts)"
752
0
        Vector3 perp = Math::Abs(x) > Math::Abs(z)
753
0
                     ? Vector3(-y, x, 0.0) : Vector3(0.0, -z, y);
754
0
        return perp.normalisedCopy();
755
0
    }
756
757
    inline Vector3 VectorBase<3, Real>::crossProduct( const Vector3& rkVector ) const
758
0
    {
759
0
        return Vector3(
760
0
            y * rkVector.z - z * rkVector.y,
761
0
            z * rkVector.x - x * rkVector.z,
762
0
            x * rkVector.y - y * rkVector.x);
763
0
    }
764
765
    inline Vector3 VectorBase<3, Real>::midPoint( const Vector3& vec ) const
766
0
    {
767
0
        return Vector3(
768
0
            ( x + vec.x ) * 0.5f,
769
0
            ( y + vec.y ) * 0.5f,
770
0
            ( z + vec.z ) * 0.5f );
771
0
    }
772
773
    inline Vector3 VectorBase<3, Real>::randomDeviant(const Radian& angle, const Vector3& up) const
774
0
    {
775
0
        Vector3 newUp;
776
0
777
0
        if (up == ZERO)
778
0
        {
779
0
            // Generate an up vector
780
0
            newUp = ((const Vector3*)this)->perpendicular();
781
0
        }
782
0
        else
783
0
        {
784
0
            newUp = up;
785
0
        }
786
0
787
0
        // Rotate up vector by random amount around this
788
0
        Quaternion q;
789
0
        q.FromAngleAxis( Radian(Math::UnitRandom() * Math::TWO_PI), (const Vector3&)*this );
790
0
        newUp = q * newUp;
791
0
792
0
        // Finally rotate this by given angle around randomised up
793
0
        q.FromAngleAxis( angle, newUp );
794
0
        return q * (const Vector3&)(*this);
795
0
    }
796
797
    inline Quaternion VectorBase<3, Real>::getRotationTo(const Vector3& dest, const Vector3& fallbackAxis) const
798
0
    {
799
0
        // From Sam Hocevar's article "Quaternion from two vectors:
800
0
        // the final version"
801
0
        Real a = Math::Sqrt(((const Vector3*)this)->squaredLength() * dest.squaredLength());
802
0
        Real b = a + dest.dotProduct(*this);
803
0
804
0
        if (Math::RealEqual(b, 2 * a) || a == 0)
805
0
            return Quaternion::IDENTITY;
806
0
807
0
        Vector3 axis;
808
0
809
0
        if (b < (Real)1e-06 * a)
810
0
        {
811
0
            b = (Real)0.0;
812
0
            axis = fallbackAxis != Vector3::ZERO ? fallbackAxis
813
0
                 : Math::Abs(x) > Math::Abs(z) ? Vector3(-y, x, (Real)0.0)
814
0
                 : Vector3((Real)0.0, -z, y);
815
0
        }
816
0
        else
817
0
        {
818
0
            axis = this->crossProduct(dest);
819
0
        }
820
0
821
0
        Quaternion q(b, axis.x, axis.y, axis.z);
822
0
        q.normalise();
823
0
        return q;
824
0
    }
825
826
    inline bool VectorBase<3, Real>::positionCloses(const Vector3& rhs, Real tolerance) const
827
0
    {
828
0
        return ((const Vector3*)this)->squaredDistance(rhs) <=
829
0
            (((const Vector3*)this)->squaredLength() + rhs.squaredLength()) * tolerance;
830
0
    }
831
832
    inline bool VectorBase<3, Real>::directionEquals(const Vector3& rhs, const Radian& tolerance) const
833
0
    {
834
0
        Real dot = rhs.dotProduct(*this);
835
0
        Radian angle = Math::ACos(dot);
836
0
837
0
        return Math::Abs(angle.valueRadians()) <= tolerance.valueRadians();
838
0
    }
839
840
    inline const Vector3& VectorBase<3, Real>::primaryAxis() const
841
0
    {
842
0
        Real absx = Math::Abs(x);
843
0
        Real absy = Math::Abs(y);
844
0
        Real absz = Math::Abs(z);
845
0
        if (absx > absy)
846
0
            if (absx > absz)
847
0
                return x > 0 ? UNIT_X : NEGATIVE_UNIT_X;
848
0
            else
849
0
                return z > 0 ? UNIT_Z : NEGATIVE_UNIT_Z;
850
0
        else // absx <= absy
851
0
            if (absy > absz)
852
0
                return y > 0 ? UNIT_Y : NEGATIVE_UNIT_Y;
853
0
            else
854
0
                return z > 0 ? UNIT_Z : NEGATIVE_UNIT_Z;
855
0
    }
856
857
    // Math functions
858
    inline Vector3 Math::calculateBasicFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
859
0
    {
860
0
        Vector3 normal = (v2 - v1).crossProduct(v3 - v1);
861
0
        normal.normalise();
862
0
        return normal;
863
0
    }
864
    inline Vector4 Math::calculateFaceNormal(const Vector3& v1, const Vector3& v2, const Vector3& v3)
865
0
    {
866
0
        Vector3 normal = calculateBasicFaceNormal(v1, v2, v3);
867
0
        // Now set up the w (distance of tri from origin
868
0
        return Vector4(normal.x, normal.y, normal.z, -(normal.dotProduct(v1)));
869
0
    }
870
    inline Vector3 Math::calculateBasicFaceNormalWithoutNormalize(
871
        const Vector3& v1, const Vector3& v2, const Vector3& v3)
872
0
    {
873
0
        return (v2 - v1).crossProduct(v3 - v1);
874
0
    }
875
876
    inline Vector4 Math::calculateFaceNormalWithoutNormalize(const Vector3& v1,
877
                                                             const Vector3& v2,
878
                                                             const Vector3& v3)
879
0
    {
880
0
        Vector3 normal = calculateBasicFaceNormalWithoutNormalize(v1, v2, v3);
881
        // Now set up the w (distance of tri from origin)
882
0
        return Vector4(normal.x, normal.y, normal.z, -(normal.dotProduct(v1)));
883
0
    }
884
    /** @} */
885
    /** @} */
886
887
}
888
#endif