2
Copyright (c) 2008-2009 NetAllied Systems GmbH
4
This file is part of COLLADABaseUtils.
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
11
#ifndef __COLLADABU_MATH_VECTOR3_H__
12
#define __COLLADABU_MATH_VECTOR3_H__
14
#include "COLLADABUPlatform.h"
15
#include "COLLADABUMathPrerequisites.h"
16
#include "COLLADABUMathQuaternion.h"
24
/** Standard 3-dimensional vector.
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.
47
inline Vector3() : x(0), y(0), z(0)
50
inline Vector3( Real fX, Real fY, Real fZ )
51
: x( fX ), y( fY ), z( fZ )
54
inline Vector3( Real afCoordinate[ 3 ] )
55
: x( afCoordinate[ 0 ] ),
56
y( afCoordinate[ 1 ] ),
57
z( afCoordinate[ 2 ] )
60
inline Vector3( int afCoordinate[ 3 ] )
62
x = ( Real ) afCoordinate[ 0 ];
63
y = ( Real ) afCoordinate[ 1 ];
64
z = ( Real ) afCoordinate[ 2 ];
67
inline Vector3( const Real* const r )
68
: x( r[ 0 ] ), y( r[ 1 ] ), z( r[ 2 ] )
71
inline Vector3( const Vector3& rkVector )
72
: x( rkVector.x ), y( rkVector.y ), z( rkVector.z )
75
inline void set( Real fX, Real fY, Real fZ )
82
inline Real operator [] ( size_t i ) const
84
COLLADABU_ASSERT( i < 3 );
89
inline Real& operator [] ( size_t i )
91
COLLADABU_ASSERT( i < 3 );
96
/** Assigns the value of the other vector.
98
rkVector The other vector
100
inline Vector3& operator = ( const Vector3& rkVector )
109
inline bool operator == ( const Vector3& rkVector ) const
111
return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
114
inline bool operator != ( const Vector3& rkVector ) const
116
return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
119
// arithmetic operations
120
inline Vector3 operator + ( const Vector3& rkVector ) const
124
kSum.x = x + rkVector.x;
125
kSum.y = y + rkVector.y;
126
kSum.z = z + rkVector.z;
131
inline Vector3 operator - ( const Vector3& rkVector ) const
135
kDiff.x = x - rkVector.x;
136
kDiff.y = y - rkVector.y;
137
kDiff.z = z - rkVector.z;
142
inline Vector3 operator * ( Real fScalar ) const
146
kProd.x = fScalar * x;
147
kProd.y = fScalar * y;
148
kProd.z = fScalar * z;
153
inline Vector3 operator * ( const Vector3& rhs ) const
164
inline Vector3 operator / ( Real fScalar ) const
166
COLLADABU_ASSERT( fScalar != 0.0 );
170
Real fInv = 1.0 / fScalar;
178
inline Vector3 operator / ( const Vector3& rhs ) const
190
inline Vector3 operator - () const
201
inline friend Vector3 operator * ( Real fScalar, const Vector3& rkVector )
205
kProd.x = fScalar * rkVector.x;
206
kProd.y = fScalar * rkVector.y;
207
kProd.z = fScalar * rkVector.z;
212
// arithmetic updates
213
inline Vector3& operator += ( const Vector3& rkVector )
222
inline Vector3& operator -= ( const Vector3& rkVector )
231
inline Vector3& operator *= ( Real fScalar )
239
inline Vector3& operator *= ( const Vector3& rkVector )
248
inline Vector3& operator /= ( Real fScalar )
250
COLLADABU_ASSERT( fScalar != 0.0 );
252
Real fInv = 1.0 / fScalar;
261
inline Vector3& operator /= ( const Vector3& rkVector )
271
/** Returns the length (magnitude) of the vector.
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()
278
inline Real length () const
280
return sqrt( x * x + y * y + z * z );
283
/** Returns the square of the length(magnitude) of the vector.
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
293
inline Real squaredLength () const
295
return x * x + y * y + z * z;
298
/** Calculates the dot (scalar) product of this vector with another.
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.
307
vec Vector with which to calculate the dot product (together
310
A float representing the dot product value.
312
inline Real dotProduct( const Vector3& vec ) const
314
return x * vec.x + y * vec.y + z * vec.z;
317
/** Normalises the vector.
319
This method normalises the vector such that it's
320
length / magnitude is 1. The result is called a unit vector.
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.
326
inline Real normalise()
328
Real fLength = sqrt( x * x + y * y + z * z );
330
// Will also work for zero-sized vectors, but will change nothing
332
if ( fLength > 1e-08 )
334
Real fInvLength = 1.0 / fLength;
343
/** Calculates the cross-product of 2 vectors, i.e. the vector that
344
lies perpendicular to them both.
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
351
rkVector Vector which, together with this one, will be used to
352
calculate the cross-product.
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.
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).
370
inline Vector3 crossProduct( const Vector3& rkVector ) const
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;
381
/** Returns a vector at a point half way between this and the passed
384
inline Vector3 midPoint( const Vector3& vec ) const
389
( z + vec.z ) * 0.5 );
392
/** Returns true if the vector's scalar components are all greater
393
that the ones of the vector it is compared against.
395
inline bool operator < ( const Vector3& rhs ) const
397
if ( x < rhs.x && y < rhs.y && z < rhs.z )
403
/** Returns true if the vector's scalar components are all smaller
404
that the ones of the vector it is compared against.
406
inline bool operator > ( const Vector3& rhs ) const
408
if ( x > rhs.x && y > rhs.y && z > rhs.z )
414
/** Sets this vector's components to the minimum of its own and the
415
ones of the passed in vector.
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.
421
inline void makeFloor( const Vector3& cmp )
433
/** Sets this vector's components to the maximum of its own and the
434
ones of the passed in vector.
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.
440
inline void makeCeil( const Vector3& cmp )
452
/** Generates a vector perpendicular to this vector (eg an 'up' vector).
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.
459
inline Vector3 perpendicular( void ) const
461
static const Real fSquareZero = 1e-06 * 1e-06;
463
Vector3 perp = this->crossProduct( Vector3::UNIT_X );
467
if ( perp.squaredLength() < fSquareZero )
469
/* This vector is the Y axis multiplied by a scalar, so we have
472
perp = this->crossProduct( Vector3::UNIT_Y );
480
/** Returns true if this vector is zero length. */
481
inline bool isZeroLength( void ) const
483
Real sqlen = ( x * x ) + ( y * y ) + ( z * z );
484
return ( sqlen < ( 1e-06 * 1e-06 ) );
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
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.
500
inline Vector3 reflect( const Vector3& normal ) const
502
return Vector3( *this - ( 2 * this->dotProduct( normal ) * normal ) );
506
/** Returns whether this vector is within a directional tolerance
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
512
inline bool directionEquals( const Vector3& rhs,
513
const Real& tolerance_radian ) const
515
Real dot = dotProduct( rhs );
516
Real angle_radian = acos( dot );
518
return fabs( angle_radian ) <= tolerance_radian;
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;
537
#endif //__COLLADABU_MATH_VECTOR3_H__