1 /*
2 Copyright (C) 2005-2007 Feeling Software Inc.
3 Portions of the code are:
4 Copyright (C) 2005-2007 Sony Computer Entertainment America
5
6 MIT License: http://www.opensource.org/licenses/mit-license.php
7 */
8
9 /**
10 @file FMVector3.h The file containing the class and global functions for 3 dimensional vectors.
11 */
12
13 #ifndef _FM_VECTOR3_H_
14 #define _FM_VECTOR3_H_
15
16 class FMVector4;
17
18 /**
19 A 3 dimensional vector.
20
21 Simple, non-optimized vector class: * is the dot-product, ^ is the
22 cross-product.
23
24 @ingroup FMath
25 */
26 class FCOLLADA_EXPORT
27 ALIGN_STRUCT(16)
28 FMVector3
29 {
30 public:
31 float x; /**< The first coordinate. */
32 float y; /**< The second coordinate. */
33 float z; /**< The third coordinate. */
34 private:
35 float w; // For alignment purposes.
36
37 public:
38 /**
39 * Creates an empty FMVector3.
40 */
41 #ifndef _DEBUG
FMVector3()42 inline FMVector3() {}
43 #else
44 inline FMVector3() { x = 123456789.0f; y = 123456789.0f; z = 123456789.0f; }
45 #endif
46
47 /** Creates the FMVector3 with the coordinates given.
48 @param _x The first coordinate.
49 @param _y The second coordinate.
50 @param _z The third coordinate. */
FMVector3(float _x,float _y,float _z)51 inline FMVector3(float _x, float _y, float _z) { x = _x; y = _y; z = _z; }
52
53 /** Copy constuctor.
54 @param rhs A second 3D vector. */
FMVector3(const FMVector3 & rhs)55 inline FMVector3(const FMVector3& rhs) { x = rhs.x; y = rhs.y; z = rhs.z; }
56
57 /** Constructor.
58 Reduces the 4D vector into 3D by removing the 4th dimension.
59 @param vect4 A 4D vector. */
60 FMVector3(const FMVector4& vect4);
61
62 /** Creates the FMVector3 from a list of floating-point values.
63 It takes the first three floating-point starting from and including \a startIndex
64 (0 indexing) in the array as the 3 coordinates. The first as the first
65 coordinate, the second as the second, and the third as the third.
66 @param source The floating-point value array.
67 @param startIndex The index of the first element. */
68 FMVector3(const float* source, uint32 startIndex = 0);
69 FMVector3(const double* source, uint32 startIndex = 0); /**< See above. */
70
71 /** Retrieves the squared length of the vector.
72 @return The squared length of this vector. */
LengthSquared()73 inline float LengthSquared() const { return x * x + y * y + z * z; }
74
75 /** Retrieves the length of the vector.
76 @return The length of this vector. */
Length()77 inline float Length() const { return sqrtf(x * x + y * y + z * z); }
78
79 /** Normalizes this vector. */
NormalizeIt()80 inline void NormalizeIt() { float l = Length(); if (l > 0.0f) { x /= l; y /= l; z /= l; } else { x = y = 0; z = 1; }}
81
82 /** Get a normalized FMVector3 with the same direction as this vector.
83 @return A FMVector3 with length 1 and same direction as this vector. */
Normalize()84 inline FMVector3 Normalize() const { float l = Length(); return (l > 0.0f) ? FMVector3(x / l, y / l, z / l) : FMVector3::XAxis; }
85
86 /** Project this FMVector3 onto another FMVector3.
87 @param unto The FMVector3 to project onto. */
Project(const FMVector3 & unto)88 inline void Project(const FMVector3& unto) { (*this) = Projected(unto); }
89
90 /** Get the projection of this FMVector3 onto another FMVector3.
91 @param unto The FMVector3 to project onto.
92 @return The projected FMVector3. */
93 inline FMVector3 Projected(const FMVector3& unto) const;
94
95 /** Get this FMVector3 as an array of \c floats.
96 @return The \c float array. */
97 inline operator float*() { return &x; }
98
99 /** Get this FMVector3 as an array of \c floats.
100 @return The \c float array. */
101 inline operator const float*() const { return &x; }
102
103 /** Set the values of this vector
104 @param x The new X value
105 @param y The new Y value
106 @param z The new Z value */
Set(float x,float y,float z)107 inline void Set(float x, float y, float z) { this->x = x; this->y = y, this->z = z; }
108
109 /** Assign this FMVector3 to the given float array.
110 Assigns each coordinate of this FMVector3 to the elements in the \c
111 float array. The first element to the first coordinate, the second to
112 the second, and the third to the third. It returns this FMVector3.
113 @param v The \c float array to assign with.
114 @return This vector. */
115 inline FMVector3& operator =(const float* v) { x = *v; y = *(v + 1); z = *(v + 2); return *this; }
116
117 /** Assigns the FMVector3 passed to outselves.
118 Copies XYZ from the passed vector
119 @param rhs The vector copy off */
120 inline FMVector3& operator =(const FMVector3& rhs) { x=rhs.x; y=rhs.y; z=rhs.z; return *this; }
121
122 /** Update each component of this FMVector to the minimum of two FMVector3s.
123 Updates each of the three components to be the minimum of the current
124 value and that of the corresponding value of the given FMVector3.
125 @param min The FMVector to take values from. */
ComponentMinimum(const FMVector3 & min)126 inline void ComponentMinimum(const FMVector3& min) { if (x < min.x) x = min.x; if (y < min.y) y = min.y; if (z < min.z) z = min.z; }
127
128 /** Retrieves the smallest component of the vector.
129 @return The smallest component of the vector. */
ComponentMinimum()130 inline float ComponentMinimum() const { return min(fabsf(x), min(fabsf(y), fabsf(z))); }
131
132 /** Update each component of this FMVector to the maximum of two FMVector3s.
133 Updates each of the three components to be the maximum of the current
134 value and that of the corresponding value of the given FMVector3.
135 @param max The FMVector to take values from. */
ComponentMaximum(const FMVector3 & max)136 inline void ComponentMaximum(const FMVector3& max) { if (x > max.x) x = max.x; if (y > max.y) y = max.y; if (z > max.z) z = max.z; }
137
138 /** Retrieves the largest component of the vector.
139 @return The largest component of the vector. */
ComponentMaximum()140 inline float ComponentMaximum() const { return max(fabsf(x), max(fabsf(y), fabsf(z))); }
141
142 /** Clamp each component of this FMVector by the corresponding components
143 in the specified min and max FMVector3.
144 Clamp refers to setting a value within a given range. If the value is
145 lower than the minimum of the range, it is set to the minimum; same for
146 the maximum.
147 @param min The FMVector to take the minimum values from.
148 @param max The FMVector to take the maximum values from. */
ComponentClamp(const FMVector3 & min,const FMVector3 & max)149 inline void ComponentClamp(const FMVector3& min, const FMVector3& max) { ComponentMinimum(min); ComponentMaximum(max); }
150
151 /** Retrieves the average of the three vector components.
152 @return The component average. */
ComponentAverage()153 inline float ComponentAverage() const { return (fabsf(x) + fabsf(y) + fabsf(z)) / 3.0f; }
154
155 public:
156 static const FMVector3 XAxis; /**< The FMVector3 representing the x axis */
157 static const FMVector3 YAxis; /**< The FMVector3 representing the y axis */
158 static const FMVector3 ZAxis; /**< The FMVector3 representing the z axis */
159 static const FMVector3 Origin;/**< The FMVector3 representing the origin */
160 static const FMVector3 Zero; /**< The FMVector3 containing all zeroes: (0,0,0). */
161 static const FMVector3 One; /**< The FMVector3 containing all ones: (1,1,1). */
162 };
163
164 /** Vector addition with two FMVector3.
165 @param a The first vector.
166 @param b The second vector.
167 @return The FMVector3 representation of the resulting vector. */
168 inline FMVector3 operator +(const FMVector3& a, const FMVector3& b) { return FMVector3(a.x + b.x, a.y + b.y, a.z + b.z); }
169
170 /** Vector subtraction with two FMVector3.
171 @param a The first vector.
172 @param b The second vector.
173 @return The FMVector3 representation of the resulting vector. */
174 inline FMVector3 operator -(const FMVector3& a, const FMVector3& b) { return FMVector3(a.x - b.x, a.y - b.y, a.z - b.z); }
175
176 /** Positive operator of the given FMVector3.
177 It applies the positive operator to each of the components of the FMVector3.
178 @param a The vector to apply the positive operator to.
179 @return The FMVector3 representation of the resulting vector. */
180 inline FMVector3 operator +(const FMVector3& a) { return FMVector3(+a.x, +a.y, +a.z); }
181
182 /** Negates the given FMVector3.
183 It negates each of the components of the FMVector3.
184 @param a The vector to negate.
185 @return The FMVector3 representation of the resulting vector. */
186 inline FMVector3 operator -(const FMVector3& a) { return FMVector3(-a.x, -a.y, -a.z); }
187
188 /** Dot product of two FMVector3.
189 @param a The first vector.
190 @param b The second vector.
191 @return The result of the dot product. */
192 inline float operator *(const FMVector3& a, const FMVector3& b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
193
194 /** Scalar multiplication with a FMVector3.
195 @param a The vector.
196 @param b The scalar.
197 @return The FMVector3 representing the resulting vector. */
198 inline FMVector3 operator *(const FMVector3& a, float b) { return FMVector3(a.x * b, a.y * b, a.z * b); }
199
200 /** Scalar multiplication with a FMVector3.
201 @param a The scalar.
202 @param b The vector.
203 @return The FMVector3 representing the resulting vector. */
204 inline FMVector3 operator *(float a, const FMVector3& b) { return FMVector3(a * b.x, a * b.y, a * b.z); }
205
206 /** Scalar division with a FMVector3.
207 @param a The vector.
208 @param b The scalar.
209 @return The FMVector3 representing the resulting vector. */
210 inline FMVector3 operator /(const FMVector3& a, float b) { return FMVector3(a.x / b, a.y / b, a.z / b); }
211
212 /** Cross product of two FMVector3.
213 @param a The first vector.
214 @param b The second vector.
215 @return The result of the dot product. */
216 inline FMVector3 operator ^(const FMVector3& a, const FMVector3& b) { return FMVector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); }
217
218 /** Assignment of the addition of two FMVector3.
219 @param b The first vector, which will also be assigned to the result.
220 @param a The second vector.
221 @return The first vector, after it has been assigned new values. */
222 inline FMVector3& operator +=(FMVector3& b, const FMVector3& a) { b.x += a.x; b.y += a.y; b.z += a.z; return b; }
223
224 /** Assignment of the subtraction of two FMVector3.
225 @param b The first vector, which will also be assigned to the result.
226 @param a The second vector.
227 @return The first vector, after it has been assigned new values. */
228 inline FMVector3& operator -=(FMVector3& b, const FMVector3& a) { b.x -= a.x; b.y -= a.y; b.z -= a.z; return b; }
229
230 /** Assignment of the scalar multiplication of a FMVector3.
231 @param b The vector, which will also be assigned to the result.
232 @param a The scalar.
233 @return The vector, after it has been assigned new values. */
234 inline FMVector3& operator *=(FMVector3& b, float a) { b.x *= a; b.y *= a; b.z *= a; return b; }
235
236 /** Assignment of the scalar division of a FMVector3.
237 @param b The vector, which will also be assigned to the result.
238 @param a The scalar.
239 @return The vector, after it has been assigned new values. */
240 inline FMVector3& operator /=(FMVector3& b, float a) { b.x /= a; b.y /= a; b.z /= a; return b; }
241
242 /** Returns whether two 3D vectors or points are equivalent.
243 @param p A first vector.
244 @param q A second vector.
245 @return Whether the vectors are equivalent. */
IsEquivalent(const FMVector3 & p,const FMVector3 & q)246 inline bool IsEquivalent(const FMVector3& p, const FMVector3& q) { return IsEquivalent(p.x, q.x) && IsEquivalent(p.y, q.y) && IsEquivalent(p.z, q.z); }
247 inline bool operator == (const FMVector3& p, const FMVector3& q) { return IsEquivalent(p, q); } /**< See above. */
248
249 // Already documented above.
Projected(const FMVector3 & unto)250 inline FMVector3 FMVector3::Projected(const FMVector3& unto) const { return ((*this) * unto) / unto.LengthSquared() * unto; }
251
252 /** A dynamically-sized array of 3D vectors or points. */
253 typedef fm::vector<FMVector3> FMVector3List;
254
255 #endif // _FM_VECTOR3_H_
256