~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to COLLADABaseUtils/include/Math/COLLADABUMathVector3.h

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (c) 2008-2009 NetAllied Systems GmbH
 
3
 
 
4
    This file is part of COLLADABaseUtils.
 
5
 
 
6
    Licensed under the MIT Open Source License, 
 
7
    for details please see LICENSE file or the website
 
8
    http://www.opensource.org/licenses/mit-license.php
 
9
*/
 
10
 
 
11
#ifndef __COLLADABU_MATH_VECTOR3_H__
 
12
#define __COLLADABU_MATH_VECTOR3_H__
 
13
 
 
14
#include "COLLADABUPlatform.h"
 
15
#include "COLLADABUMathPrerequisites.h"
 
16
#include "COLLADABUMathQuaternion.h"
 
17
 
 
18
#include <math.h>
 
19
 
 
20
namespace COLLADABU
 
21
{
 
22
    namespace Math
 
23
    {
 
24
        /** Standard 3-dimensional vector.
 
25
            @remarks
 
26
                A direction in 3D space represented as distances along the 3
 
27
                orthogonal axes (x, y, z). Note that positions, directions and
 
28
                scaling factors can be represented by a vector, depending on how
 
29
                you interpret the values.
 
30
        */
 
31
 
 
32
        class Vector3
 
33
        {
 
34
 
 
35
        public:
 
36
            union {
 
37
 
 
38
                struct
 
39
                {
 
40
                    Real x, y, z;
 
41
                };
 
42
 
 
43
                Real val[ 3 ];
 
44
            };
 
45
 
 
46
        public:
 
47
            inline Vector3() : x(0), y(0), z(0)
 
48
            {}
 
49
 
 
50
            inline Vector3( Real fX, Real fY, Real fZ )
 
51
                    : x( fX ), y( fY ), z( fZ )
 
52
            {}
 
53
 
 
54
            inline Vector3( Real afCoordinate[ 3 ] )
 
55
                    : x( afCoordinate[ 0 ] ),
 
56
                    y( afCoordinate[ 1 ] ),
 
57
                    z( afCoordinate[ 2 ] )
 
58
            {}
 
59
 
 
60
            inline Vector3( int afCoordinate[ 3 ] )
 
61
            {
 
62
                x = ( Real ) afCoordinate[ 0 ];
 
63
                y = ( Real ) afCoordinate[ 1 ];
 
64
                z = ( Real ) afCoordinate[ 2 ];
 
65
            }
 
66
 
 
67
            inline Vector3( const Real* const r )
 
68
                    : x( r[ 0 ] ), y( r[ 1 ] ), z( r[ 2 ] )
 
69
            {}
 
70
 
 
71
            inline Vector3( const Vector3& rkVector )
 
72
                    : x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
 
73
            {}
 
74
 
 
75
                        inline void set( Real fX, Real fY, Real fZ )
 
76
                        {
 
77
                                x = fX;
 
78
                                y = fY;
 
79
                                z = fZ;
 
80
                        }
 
81
 
 
82
            inline Real operator [] ( size_t i ) const
 
83
            {
 
84
                                COLLADABU_ASSERT( i < 3 );
 
85
 
 
86
                return *( &x + i );
 
87
            }
 
88
 
 
89
            inline Real& operator [] ( size_t i )
 
90
            {
 
91
                COLLADABU_ASSERT( i < 3 );
 
92
 
 
93
                return *( &x + i );
 
94
            }
 
95
 
 
96
            /** Assigns the value of the other vector.
 
97
                @param
 
98
                    rkVector The other vector
 
99
            */
 
100
            inline Vector3& operator = ( const Vector3& rkVector )
 
101
            {
 
102
                x = rkVector.x;
 
103
                y = rkVector.y;
 
104
                z = rkVector.z;
 
105
 
 
106
                return *this;
 
107
            }
 
108
 
 
109
            inline bool operator == ( const Vector3& rkVector ) const
 
110
            {
 
111
                return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
 
112
            }
 
113
 
 
114
            inline bool operator != ( const Vector3& rkVector ) const
 
115
            {
 
116
                return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
 
117
            }
 
118
 
 
119
            // arithmetic operations
 
120
            inline Vector3 operator + ( const Vector3& rkVector ) const
 
121
            {
 
122
                Vector3 kSum;
 
123
 
 
124
                kSum.x = x + rkVector.x;
 
125
                kSum.y = y + rkVector.y;
 
126
                kSum.z = z + rkVector.z;
 
127
 
 
128
                return kSum;
 
129
            }
 
130
 
 
131
            inline Vector3 operator - ( const Vector3& rkVector ) const
 
132
            {
 
133
                Vector3 kDiff;
 
134
 
 
135
                kDiff.x = x - rkVector.x;
 
136
                kDiff.y = y - rkVector.y;
 
137
                kDiff.z = z - rkVector.z;
 
138
 
 
139
                return kDiff;
 
140
            }
 
141
 
 
142
            inline Vector3 operator * ( Real fScalar ) const
 
143
            {
 
144
                Vector3 kProd;
 
145
 
 
146
                kProd.x = fScalar * x;
 
147
                kProd.y = fScalar * y;
 
148
                kProd.z = fScalar * z;
 
149
 
 
150
                return kProd;
 
151
            }
 
152
 
 
153
            inline Vector3 operator * ( const Vector3& rhs ) const
 
154
            {
 
155
                Vector3 kProd;
 
156
 
 
157
                kProd.x = rhs.x * x;
 
158
                kProd.y = rhs.y * y;
 
159
                kProd.z = rhs.z * z;
 
160
 
 
161
                return kProd;
 
162
            }
 
163
 
 
164
            inline Vector3 operator / ( Real fScalar ) const
 
165
            {
 
166
                COLLADABU_ASSERT( fScalar != 0.0 );
 
167
 
 
168
                Vector3 kDiv;
 
169
 
 
170
                Real fInv = 1.0 / fScalar;
 
171
                kDiv.x = x * fInv;
 
172
                kDiv.y = y * fInv;
 
173
                kDiv.z = z * fInv;
 
174
 
 
175
                return kDiv;
 
176
            }
 
177
 
 
178
            inline Vector3 operator / ( const Vector3& rhs ) const
 
179
            {
 
180
                Vector3 kDiv;
 
181
 
 
182
                kDiv.x = x / rhs.x;
 
183
                kDiv.y = y / rhs.y;
 
184
                kDiv.z = z / rhs.z;
 
185
 
 
186
                return kDiv;
 
187
            }
 
188
 
 
189
 
 
190
            inline Vector3 operator - () const
 
191
            {
 
192
                Vector3 kNeg;
 
193
 
 
194
                kNeg.x = -x;
 
195
                kNeg.y = -y;
 
196
                kNeg.z = -z;
 
197
 
 
198
                return kNeg;
 
199
            }
 
200
 
 
201
            inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
 
202
            {
 
203
                Vector3 kProd;
 
204
 
 
205
                kProd.x = fScalar * rkVector.x;
 
206
                kProd.y = fScalar * rkVector.y;
 
207
                kProd.z = fScalar * rkVector.z;
 
208
 
 
209
                return kProd;
 
210
            }
 
211
 
 
212
            // arithmetic updates
 
213
            inline Vector3& operator += ( const Vector3& rkVector )
 
214
            {
 
215
                x += rkVector.x;
 
216
                y += rkVector.y;
 
217
                z += rkVector.z;
 
218
 
 
219
                return *this;
 
220
            }
 
221
 
 
222
            inline Vector3& operator -= ( const Vector3& rkVector )
 
223
            {
 
224
                x -= rkVector.x;
 
225
                y -= rkVector.y;
 
226
                z -= rkVector.z;
 
227
 
 
228
                return *this;
 
229
            }
 
230
 
 
231
            inline Vector3& operator *= ( Real fScalar )
 
232
            {
 
233
                x *= fScalar;
 
234
                y *= fScalar;
 
235
                z *= fScalar;
 
236
                return *this;
 
237
            }
 
238
 
 
239
            inline Vector3& operator *= ( const Vector3& rkVector )
 
240
            {
 
241
                x *= rkVector.x;
 
242
                y *= rkVector.y;
 
243
                z *= rkVector.z;
 
244
 
 
245
                return *this;
 
246
            }
 
247
 
 
248
            inline Vector3& operator /= ( Real fScalar )
 
249
            {
 
250
                COLLADABU_ASSERT( fScalar != 0.0 );
 
251
 
 
252
                Real fInv = 1.0 / fScalar;
 
253
 
 
254
                x *= fInv;
 
255
                y *= fInv;
 
256
                z *= fInv;
 
257
 
 
258
                return *this;
 
259
            }
 
260
 
 
261
            inline Vector3& operator /= ( const Vector3& rkVector )
 
262
            {
 
263
                x /= rkVector.x;
 
264
                y /= rkVector.y;
 
265
                z /= rkVector.z;
 
266
 
 
267
                return *this;
 
268
            }
 
269
 
 
270
 
 
271
            /** Returns the length (magnitude) of the vector.
 
272
                @warning
 
273
                    This operation requires a square root and is expensive in
 
274
                    terms of CPU operations. If you don't need to know the exact
 
275
                    length (e.g. for just comparing lengths) use squaredLength()
 
276
                    instead.
 
277
            */
 
278
            inline Real length () const
 
279
            {
 
280
                return sqrt( x * x + y * y + z * z );
 
281
            }
 
282
 
 
283
            /** Returns the square of the length(magnitude) of the vector.
 
284
                @remarks
 
285
                    This  method is for efficiency - calculating the actual
 
286
                    length of a vector requires a square root, which is expensive
 
287
                    in terms of the operations required. This method returns the
 
288
                    square of the length of the vector, i.e. the same as the
 
289
                    length but before the square root is taken. Use this if you
 
290
                    want to find the longest / shortest vector without incurring
 
291
                    the square root.
 
292
            */
 
293
            inline Real squaredLength () const
 
294
            {
 
295
                return x * x + y * y + z * z;
 
296
            }
 
297
 
 
298
            /** Calculates the dot (scalar) product of this vector with another.
 
299
                @remarks
 
300
                    The dot product can be used to calculate the angle between 2
 
301
                    vectors. If both are unit vectors, the dot product is the
 
302
                    cosine of the angle; otherwise the dot product must be
 
303
                    divided by the product of the lengths of both vectors to get
 
304
                    the cosine of the angle. This result can further be used to
 
305
                    calculate the distance of a point from a plane.
 
306
                @param
 
307
                    vec Vector with which to calculate the dot product (together
 
308
                    with this one).
 
309
                @returns
 
310
                    A float representing the dot product value.
 
311
            */
 
312
            inline Real dotProduct( const Vector3& vec ) const
 
313
            {
 
314
                return x * vec.x + y * vec.y + z * vec.z;
 
315
            }
 
316
 
 
317
            /** Normalises the vector.
 
318
                @remarks
 
319
                    This method normalises the vector such that it's
 
320
                    length / magnitude is 1. The result is called a unit vector.
 
321
                @note
 
322
                    This function will not crash for zero-sized vectors, but there
 
323
                    will be no changes made to their components.
 
324
                @returns The previous length of the vector.
 
325
            */
 
326
            inline Real normalise()
 
327
            {
 
328
                Real fLength = sqrt( x * x + y * y + z * z );
 
329
 
 
330
                // Will also work for zero-sized vectors, but will change nothing
 
331
 
 
332
                if ( fLength > 1e-08 )
 
333
                {
 
334
                    Real fInvLength = 1.0 / fLength;
 
335
                    x *= fInvLength;
 
336
                    y *= fInvLength;
 
337
                    z *= fInvLength;
 
338
                }
 
339
 
 
340
                return fLength;
 
341
            }
 
342
 
 
343
            /** Calculates the cross-product of 2 vectors, i.e. the vector that
 
344
                lies perpendicular to them both.
 
345
                @remarks
 
346
                    The cross-product is normally used to calculate the normal
 
347
                    vector of a plane, by calculating the cross-product of 2
 
348
                    non-equivalent vectors which lie on the plane (e.g. 2 edges
 
349
                    of a triangle).
 
350
                @param
 
351
                    rkVector Vector which, together with this one, will be used to
 
352
                    calculate the cross-product.
 
353
                @returns
 
354
                    A vector which is the result of the cross-product. This
 
355
                    vector will <b>NOT</b> be normalised, to maximise efficiency
 
356
                    - call Vector3::normalise on the result if you wish this to
 
357
                    be done. As for which side the resultant vector will be on, the
 
358
                    returned vector will be on the side from which the arc from 'this'
 
359
                    to rkVector is anticlockwise, e.g. UNIT_Y.crossProduct(UNIT_Z) 
 
360
                    = UNIT_X, whilst UNIT_Z.crossProduct(UNIT_Y) = -UNIT_X.
 
361
                @par
 
362
                    For a clearer explanation, look a the left and the bottom edges
 
363
                    of your monitor's screen. Assume that the first vector is the
 
364
                    left edge and the second vector is the bottom edge, both of
 
365
                    them starting from the lower-left corner of the screen. The
 
366
                    resulting vector is going to be perpendicular to both of them
 
367
                    and will go <i>inside</i> the screen, towards the cathode tube
 
368
                    (assuming you're using a CRT monitor, of course).
 
369
            */
 
370
            inline Vector3 crossProduct( const Vector3& rkVector ) const
 
371
            {
 
372
                Vector3 kCross;
 
373
 
 
374
                kCross.x = y * rkVector.z - z * rkVector.y;
 
375
                kCross.y = z * rkVector.x - x * rkVector.z;
 
376
                kCross.z = x * rkVector.y - y * rkVector.x;
 
377
 
 
378
                return kCross;
 
379
            }
 
380
 
 
381
            /** Returns a vector at a point half way between this and the passed
 
382
                in vector.
 
383
            */
 
384
            inline Vector3 midPoint( const Vector3& vec ) const
 
385
            {
 
386
                return Vector3(
 
387
                           ( x + vec.x ) * 0.5,
 
388
                           ( y + vec.y ) * 0.5,
 
389
                           ( z + vec.z ) * 0.5 );
 
390
            }
 
391
 
 
392
            /** Returns true if the vector's scalar components are all greater
 
393
                that the ones of the vector it is compared against.
 
394
            */
 
395
            inline bool operator < ( const Vector3& rhs ) const
 
396
            {
 
397
                if ( x < rhs.x && y < rhs.y && z < rhs.z )
 
398
                    return true;
 
399
 
 
400
                return false;
 
401
            }
 
402
 
 
403
            /** Returns true if the vector's scalar components are all smaller
 
404
                that the ones of the vector it is compared against.
 
405
            */
 
406
            inline bool operator > ( const Vector3& rhs ) const
 
407
            {
 
408
                if ( x > rhs.x && y > rhs.y && z > rhs.z )
 
409
                    return true;
 
410
 
 
411
                return false;
 
412
            }
 
413
 
 
414
            /** Sets this vector's components to the minimum of its own and the
 
415
                ones of the passed in vector.
 
416
                @remarks
 
417
                    'Minimum' in this case means the combination of the lowest
 
418
                    value of x, y and z from both vectors. Lowest is taken just
 
419
                    numerically, not magnitude, so -1 < 0.
 
420
            */
 
421
            inline void makeFloor( const Vector3& cmp )
 
422
            {
 
423
                if ( cmp.x < x )
 
424
                    x = cmp.x;
 
425
 
 
426
                if ( cmp.y < y )
 
427
                    y = cmp.y;
 
428
 
 
429
                if ( cmp.z < z )
 
430
                    z = cmp.z;
 
431
            }
 
432
 
 
433
            /** Sets this vector's components to the maximum of its own and the
 
434
                ones of the passed in vector.
 
435
                @remarks
 
436
                    'Maximum' in this case means the combination of the highest
 
437
                    value of x, y and z from both vectors. Highest is taken just
 
438
                    numerically, not magnitude, so 1 > -3.
 
439
            */
 
440
            inline void makeCeil( const Vector3& cmp )
 
441
            {
 
442
                if ( cmp.x > x )
 
443
                    x = cmp.x;
 
444
 
 
445
                if ( cmp.y > y )
 
446
                    y = cmp.y;
 
447
 
 
448
                if ( cmp.z > z )
 
449
                    z = cmp.z;
 
450
            }
 
451
 
 
452
            /** Generates a vector perpendicular to this vector (eg an 'up' vector).
 
453
                @remarks
 
454
                    This method will return a vector which is perpendicular to this
 
455
                    vector. There are an infinite number of possibilities but this 
 
456
                    method will guarantee to generate one of them. If you need more 
 
457
                    control you should use the Quaternion class.
 
458
            */
 
459
            inline Vector3 perpendicular( void ) const
 
460
            {
 
461
                static const Real fSquareZero = 1e-06 * 1e-06;
 
462
 
 
463
                Vector3 perp = this->crossProduct( Vector3::UNIT_X );
 
464
 
 
465
                // Check length
 
466
 
 
467
                if ( perp.squaredLength() < fSquareZero )
 
468
                {
 
469
                    /* This vector is the Y axis multiplied by a scalar, so we have
 
470
                       to use another axis.
 
471
                    */
 
472
                    perp = this->crossProduct( Vector3::UNIT_Y );
 
473
                }
 
474
 
 
475
                return perp;
 
476
            }
 
477
 
 
478
 
 
479
 
 
480
            /** Returns true if this vector is zero length. */
 
481
            inline bool isZeroLength( void ) const
 
482
            {
 
483
                Real sqlen = ( x * x ) + ( y * y ) + ( z * z );
 
484
                return ( sqlen < ( 1e-06 * 1e-06 ) );
 
485
 
 
486
            }
 
487
 
 
488
            /** As normalise, except that this vector is unaffected and the
 
489
                normalised vector is returned as a copy. */
 
490
            inline Vector3 normalisedCopy( void ) const
 
491
            {
 
492
                Vector3 ret = *this;
 
493
                ret.normalise();
 
494
                return ret;
 
495
            }
 
496
 
 
497
            /** Calculates a reflection vector to the plane with the given normal .
 
498
            @remarks NB assumes 'this' is pointing AWAY FROM the plane, invert if it is not.
 
499
            */
 
500
            inline Vector3 reflect( const Vector3& normal ) const
 
501
            {
 
502
                return Vector3( *this - ( 2 * this->dotProduct( normal ) * normal ) );
 
503
            }
 
504
 
 
505
 
 
506
            /** Returns whether this vector is within a directional tolerance
 
507
             of another vector.
 
508
            @param rhs The vector to compare with
 
509
            @param tolerance_radian The maximum angle by which the vectors may vary and
 
510
             still be considered equal
 
511
            */
 
512
            inline bool directionEquals( const Vector3& rhs,
 
513
                                         const Real& tolerance_radian ) const
 
514
            {
 
515
                Real dot = dotProduct( rhs );
 
516
                Real angle_radian = acos( dot );
 
517
 
 
518
                return fabs( angle_radian ) <= tolerance_radian;
 
519
 
 
520
            }
 
521
 
 
522
            // special points
 
523
            static const Vector3 ZERO;
 
524
            static const Vector3 UNIT_X;
 
525
            static const Vector3 UNIT_Y;
 
526
            static const Vector3 UNIT_Z;
 
527
            static const Vector3 NEGATIVE_UNIT_X;
 
528
            static const Vector3 NEGATIVE_UNIT_Y;
 
529
            static const Vector3 NEGATIVE_UNIT_Z;
 
530
            static const Vector3 UNIT_SCALE;
 
531
 
 
532
        };
 
533
                
 
534
    }           
 
535
}
 
536
 
 
537
#endif //__COLLADABU_MATH_VECTOR3_H__