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