1 //
2 // Copyright (c) 2008-2017 the Urho3D project.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to deal
6 // in the Software without restriction, including without limitation the rights
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 // copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 // THE SOFTWARE.
21 //
22
23 #pragma once
24
25 #include "../Math/Vector2.h"
26 #include "../Math/MathDefs.h"
27
28 namespace Urho3D
29 {
30
31 /// Three-dimensional vector with integer values.
32 class URHO3D_API IntVector3
33 {
34 public:
35 /// Construct a zero vector.
IntVector3()36 IntVector3() :
37 x_(0),
38 y_(0),
39 z_(0)
40 {
41 }
42
43 /// Construct from coordinates.
IntVector3(int x,int y,int z)44 IntVector3(int x, int y, int z) :
45 x_(x),
46 y_(y),
47 z_(z)
48 {
49 }
50
51 /// Construct from an int array.
IntVector3(const int * data)52 IntVector3(const int* data) :
53 x_(data[0]),
54 y_(data[1]),
55 z_(data[2])
56 {
57 }
58
59 /// Copy-construct from another vector.
IntVector3(const IntVector3 & rhs)60 IntVector3(const IntVector3& rhs) :
61 x_(rhs.x_),
62 y_(rhs.y_),
63 z_(rhs.z_)
64 {
65 }
66
67 /// Assign from another vector.
68 IntVector3& operator =(const IntVector3& rhs)
69 {
70 x_ = rhs.x_;
71 y_ = rhs.y_;
72 z_ = rhs.z_;
73 return *this;
74 }
75
76 /// Test for equality with another vector.
77 bool operator ==(const IntVector3& rhs) const { return x_ == rhs.x_ && y_ == rhs.y_ && z_ == rhs.z_; }
78
79 /// Test for inequality with another vector.
80 bool operator !=(const IntVector3& rhs) const { return x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_; }
81
82 /// Add a vector.
83 IntVector3 operator +(const IntVector3& rhs) const { return IntVector3(x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
84
85 /// Return negation.
86 IntVector3 operator -() const { return IntVector3(-x_, -y_, -z_); }
87
88 /// Subtract a vector.
89 IntVector3 operator -(const IntVector3& rhs) const { return IntVector3(x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
90
91 /// Multiply with a scalar.
92 IntVector3 operator *(int rhs) const { return IntVector3(x_ * rhs, y_ * rhs, z_ * rhs); }
93
94 /// Divide by a scalar.
95 IntVector3 operator /(int rhs) const { return IntVector3(x_ / rhs, y_ / rhs, z_ / rhs); }
96
97 /// Add-assign a vector.
98 IntVector3& operator +=(const IntVector3& rhs)
99 {
100 x_ += rhs.x_;
101 y_ += rhs.y_;
102 z_ += rhs.z_;
103 return *this;
104 }
105
106 /// Subtract-assign a vector.
107 IntVector3& operator -=(const IntVector3& rhs)
108 {
109 x_ -= rhs.x_;
110 y_ -= rhs.y_;
111 z_ -= rhs.z_;
112 return *this;
113 }
114
115 /// Multiply-assign a scalar.
116 IntVector3& operator *=(int rhs)
117 {
118 x_ *= rhs;
119 y_ *= rhs;
120 z_ *= rhs;
121 return *this;
122 }
123
124 /// Divide-assign a scalar.
125 IntVector3& operator /=(int rhs)
126 {
127 x_ /= rhs;
128 y_ /= rhs;
129 z_ /= rhs;
130 return *this;
131 }
132
133 /// Return integer data.
Data()134 const int* Data() const { return &x_; }
135
136 /// Return as string.
137 String ToString() const;
138
139 /// Return hash value for HashSet & HashMap.
ToHash()140 unsigned ToHash() const { return (unsigned)x_ * 31 * 31 + (unsigned)y_ * 31 + (unsigned)z_; }
141
142 /// Return length.
Length()143 float Length() const { return sqrtf((float)(x_ * x_ + y_ * y_ + z_ * z_)); }
144
145 /// X coordinate.
146 int x_;
147 /// Y coordinate.
148 int y_;
149 /// Z coordinate.
150 int z_;
151
152 /// Zero vector.
153 static const IntVector3 ZERO;
154 /// (-1,0,0) vector.
155 static const IntVector3 LEFT;
156 /// (1,0,0) vector.
157 static const IntVector3 RIGHT;
158 /// (0,1,0) vector.
159 static const IntVector3 UP;
160 /// (0,-1,0) vector.
161 static const IntVector3 DOWN;
162 /// (0,0,1) vector.
163 static const IntVector3 FORWARD;
164 /// (0,0,-1) vector.
165 static const IntVector3 BACK;
166 /// (1,1,1) vector.
167 static const IntVector3 ONE;
168 };
169
170 /// Three-dimensional vector.
171 class URHO3D_API Vector3
172 {
173 public:
174 /// Construct a zero vector.
Vector3()175 Vector3() :
176 x_(0.0f),
177 y_(0.0f),
178 z_(0.0f)
179 {
180 }
181
182 /// Copy-construct from another vector.
Vector3(const Vector3 & vector)183 Vector3(const Vector3& vector) :
184 x_(vector.x_),
185 y_(vector.y_),
186 z_(vector.z_)
187 {
188 }
189
190 /// Construct from a two-dimensional vector and the Z coordinate.
Vector3(const Vector2 & vector,float z)191 Vector3(const Vector2& vector, float z) :
192 x_(vector.x_),
193 y_(vector.y_),
194 z_(z)
195 {
196 }
197
198 /// Construct from a two-dimensional vector (for Urho2D).
Vector3(const Vector2 & vector)199 Vector3(const Vector2& vector) :
200 x_(vector.x_),
201 y_(vector.y_),
202 z_(0.0f)
203 {
204 }
205
206 /// Construct from an IntVector3.
Vector3(const IntVector3 & vector)207 explicit Vector3(const IntVector3& vector) :
208 x_((float)vector.x_),
209 y_((float)vector.y_),
210 z_((float)vector.z_)
211 {
212 }
213
214 /// Construct from coordinates.
Vector3(float x,float y,float z)215 Vector3(float x, float y, float z) :
216 x_(x),
217 y_(y),
218 z_(z)
219 {
220 }
221
222 /// Construct from two-dimensional coordinates (for Urho2D).
Vector3(float x,float y)223 Vector3(float x, float y) :
224 x_(x),
225 y_(y),
226 z_(0.0f)
227 {
228 }
229
230 /// Construct from a float array.
Vector3(const float * data)231 explicit Vector3(const float* data) :
232 x_(data[0]),
233 y_(data[1]),
234 z_(data[2])
235 {
236 }
237
238 /// Assign from another vector.
239 Vector3& operator =(const Vector3& rhs)
240 {
241 x_ = rhs.x_;
242 y_ = rhs.y_;
243 z_ = rhs.z_;
244 return *this;
245 }
246
247 /// Test for equality with another vector without epsilon.
248 bool operator ==(const Vector3& rhs) const { return x_ == rhs.x_ && y_ == rhs.y_ && z_ == rhs.z_; }
249
250 /// Test for inequality with another vector without epsilon.
251 bool operator !=(const Vector3& rhs) const { return x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_; }
252
253 /// Add a vector.
254 Vector3 operator +(const Vector3& rhs) const { return Vector3(x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
255
256 /// Return negation.
257 Vector3 operator -() const { return Vector3(-x_, -y_, -z_); }
258
259 /// Subtract a vector.
260 Vector3 operator -(const Vector3& rhs) const { return Vector3(x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
261
262 /// Multiply with a scalar.
263 Vector3 operator *(float rhs) const { return Vector3(x_ * rhs, y_ * rhs, z_ * rhs); }
264
265 /// Multiply with a vector.
266 Vector3 operator *(const Vector3& rhs) const { return Vector3(x_ * rhs.x_, y_ * rhs.y_, z_ * rhs.z_); }
267
268 /// Divide by a scalar.
269 Vector3 operator /(float rhs) const { return Vector3(x_ / rhs, y_ / rhs, z_ / rhs); }
270
271 /// Divide by a vector.
272 Vector3 operator /(const Vector3& rhs) const { return Vector3(x_ / rhs.x_, y_ / rhs.y_, z_ / rhs.z_); }
273
274 /// Add-assign a vector.
275 Vector3& operator +=(const Vector3& rhs)
276 {
277 x_ += rhs.x_;
278 y_ += rhs.y_;
279 z_ += rhs.z_;
280 return *this;
281 }
282
283 /// Subtract-assign a vector.
284 Vector3& operator -=(const Vector3& rhs)
285 {
286 x_ -= rhs.x_;
287 y_ -= rhs.y_;
288 z_ -= rhs.z_;
289 return *this;
290 }
291
292 /// Multiply-assign a scalar.
293 Vector3& operator *=(float rhs)
294 {
295 x_ *= rhs;
296 y_ *= rhs;
297 z_ *= rhs;
298 return *this;
299 }
300
301 /// Multiply-assign a vector.
302 Vector3& operator *=(const Vector3& rhs)
303 {
304 x_ *= rhs.x_;
305 y_ *= rhs.y_;
306 z_ *= rhs.z_;
307 return *this;
308 }
309
310 /// Divide-assign a scalar.
311 Vector3& operator /=(float rhs)
312 {
313 float invRhs = 1.0f / rhs;
314 x_ *= invRhs;
315 y_ *= invRhs;
316 z_ *= invRhs;
317 return *this;
318 }
319
320 /// Divide-assign a vector.
321 Vector3& operator /=(const Vector3& rhs)
322 {
323 x_ /= rhs.x_;
324 y_ /= rhs.y_;
325 z_ /= rhs.z_;
326 return *this;
327 }
328
329 /// Normalize to unit length.
Normalize()330 void Normalize()
331 {
332 float lenSquared = LengthSquared();
333 if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
334 {
335 float invLen = 1.0f / sqrtf(lenSquared);
336 x_ *= invLen;
337 y_ *= invLen;
338 z_ *= invLen;
339 }
340 }
341
342 /// Return length.
Length()343 float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_); }
344
345 /// Return squared length.
LengthSquared()346 float LengthSquared() const { return x_ * x_ + y_ * y_ + z_ * z_; }
347
348 /// Calculate dot product.
DotProduct(const Vector3 & rhs)349 float DotProduct(const Vector3& rhs) const { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
350
351 /// Calculate absolute dot product.
AbsDotProduct(const Vector3 & rhs)352 float AbsDotProduct(const Vector3& rhs) const
353 {
354 return Urho3D::Abs(x_ * rhs.x_) + Urho3D::Abs(y_ * rhs.y_) + Urho3D::Abs(z_ * rhs.z_);
355 }
356
357 /// Project vector onto axis.
ProjectOntoAxis(const Vector3 & axis)358 float ProjectOntoAxis(const Vector3& axis) const { return DotProduct(axis.Normalized()); }
359
360 /// Make vector orthogonal to the axis.
Orthogonalize(const Vector3 & axis)361 Vector3 Orthogonalize(const Vector3& axis) const { return axis.CrossProduct(*this).CrossProduct(axis).Normalized(); }
362
363 /// Calculate cross product.
CrossProduct(const Vector3 & rhs)364 Vector3 CrossProduct(const Vector3& rhs) const
365 {
366 return Vector3(
367 y_ * rhs.z_ - z_ * rhs.y_,
368 z_ * rhs.x_ - x_ * rhs.z_,
369 x_ * rhs.y_ - y_ * rhs.x_
370 );
371 }
372
373 /// Return absolute vector.
Abs()374 Vector3 Abs() const { return Vector3(Urho3D::Abs(x_), Urho3D::Abs(y_), Urho3D::Abs(z_)); }
375
376 /// Linear interpolation with another vector.
Lerp(const Vector3 & rhs,float t)377 Vector3 Lerp(const Vector3& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
378
379 /// Test for equality with another vector with epsilon.
Equals(const Vector3 & rhs)380 bool Equals(const Vector3& rhs) const
381 {
382 return Urho3D::Equals(x_, rhs.x_) && Urho3D::Equals(y_, rhs.y_) && Urho3D::Equals(z_, rhs.z_);
383 }
384
385 /// Returns the angle between this vector and another vector in degrees.
Angle(const Vector3 & rhs)386 float Angle(const Vector3& rhs) const { return Urho3D::Acos(DotProduct(rhs) / (Length() * rhs.Length())); }
387
388 /// Return whether is NaN.
IsNaN()389 bool IsNaN() const { return Urho3D::IsNaN(x_) || Urho3D::IsNaN(y_) || Urho3D::IsNaN(z_); }
390
391 /// Return normalized to unit length.
Normalized()392 Vector3 Normalized() const
393 {
394 float lenSquared = LengthSquared();
395 if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
396 {
397 float invLen = 1.0f / sqrtf(lenSquared);
398 return *this * invLen;
399 }
400 else
401 return *this;
402 }
403
404 /// Return float data.
Data()405 const float* Data() const { return &x_; }
406
407 /// Return as string.
408 String ToString() const;
409
410 /// Return hash value for HashSet & HashMap.
ToHash()411 unsigned ToHash() const
412 {
413 unsigned hash = 37;
414 hash = 37 * hash + FloatToRawIntBits(x_);
415 hash = 37 * hash + FloatToRawIntBits(y_);
416 hash = 37 * hash + FloatToRawIntBits(z_);
417
418 return hash;
419 }
420
421 /// X coordinate.
422 float x_;
423 /// Y coordinate.
424 float y_;
425 /// Z coordinate.
426 float z_;
427
428 /// Zero vector.
429 static const Vector3 ZERO;
430 /// (-1,0,0) vector.
431 static const Vector3 LEFT;
432 /// (1,0,0) vector.
433 static const Vector3 RIGHT;
434 /// (0,1,0) vector.
435 static const Vector3 UP;
436 /// (0,-1,0) vector.
437 static const Vector3 DOWN;
438 /// (0,0,1) vector.
439 static const Vector3 FORWARD;
440 /// (0,0,-1) vector.
441 static const Vector3 BACK;
442 /// (1,1,1) vector.
443 static const Vector3 ONE;
444 };
445
446 /// Multiply Vector3 with a scalar.
447 inline Vector3 operator *(float lhs, const Vector3& rhs) { return rhs * lhs; }
448
449 /// Multiply IntVector3 with a scalar.
450 inline IntVector3 operator *(int lhs, const IntVector3& rhs) { return rhs * lhs; }
451
452 /// Per-component linear interpolation between two 3-vectors.
VectorLerp(const Vector3 & lhs,const Vector3 & rhs,const Vector3 & t)453 inline Vector3 VectorLerp(const Vector3& lhs, const Vector3& rhs, const Vector3& t) { return lhs + (rhs - lhs) * t; }
454
455 /// Per-component min of two 3-vectors.
VectorMin(const Vector3 & lhs,const Vector3 & rhs)456 inline Vector3 VectorMin(const Vector3& lhs, const Vector3& rhs) { return Vector3(Min(lhs.x_, rhs.x_), Min(lhs.y_, rhs.y_), Min(lhs.z_, rhs.z_)); }
457
458 /// Per-component max of two 3-vectors.
VectorMax(const Vector3 & lhs,const Vector3 & rhs)459 inline Vector3 VectorMax(const Vector3& lhs, const Vector3& rhs) { return Vector3(Max(lhs.x_, rhs.x_), Max(lhs.y_, rhs.y_), Max(lhs.z_, rhs.z_)); }
460
461 /// Per-component floor of 3-vector.
VectorFloor(const Vector3 & vec)462 inline Vector3 VectorFloor(const Vector3& vec) { return Vector3(Floor(vec.x_), Floor(vec.y_), Floor(vec.z_)); }
463
464 /// Per-component round of 3-vector.
VectorRound(const Vector3 & vec)465 inline Vector3 VectorRound(const Vector3& vec) { return Vector3(Round(vec.x_), Round(vec.y_), Round(vec.z_)); }
466
467 /// Per-component ceil of 3-vector.
VectorCeil(const Vector3 & vec)468 inline Vector3 VectorCeil(const Vector3& vec) { return Vector3(Ceil(vec.x_), Ceil(vec.y_), Ceil(vec.z_)); }
469
470 /// Per-component floor of 3-vector. Returns IntVector3.
VectorFloorToInt(const Vector3 & vec)471 inline IntVector3 VectorFloorToInt(const Vector3& vec) { return IntVector3(FloorToInt(vec.x_), FloorToInt(vec.y_), FloorToInt(vec.z_)); }
472
473 /// Per-component round of 3-vector. Returns IntVector3.
VectorRoundToInt(const Vector3 & vec)474 inline IntVector3 VectorRoundToInt(const Vector3& vec) { return IntVector3(RoundToInt(vec.x_), RoundToInt(vec.y_), RoundToInt(vec.z_)); }
475
476 /// Per-component ceil of 3-vector. Returns IntVector3.
VectorCeilToInt(const Vector3 & vec)477 inline IntVector3 VectorCeilToInt(const Vector3& vec) { return IntVector3(CeilToInt(vec.x_), CeilToInt(vec.y_), CeilToInt(vec.z_)); }
478
479 /// Per-component min of two 3-vectors.
VectorMin(const IntVector3 & lhs,const IntVector3 & rhs)480 inline IntVector3 VectorMin(const IntVector3& lhs, const IntVector3& rhs) { return IntVector3(Min(lhs.x_, rhs.x_), Min(lhs.y_, rhs.y_), Min(lhs.z_, rhs.z_)); }
481
482 /// Per-component max of two 3-vectors.
VectorMax(const IntVector3 & lhs,const IntVector3 & rhs)483 inline IntVector3 VectorMax(const IntVector3& lhs, const IntVector3& rhs) { return IntVector3(Max(lhs.x_, rhs.x_), Max(lhs.y_, rhs.y_), Max(lhs.z_, rhs.z_)); }
484
485 /// Return a random value from [0, 1) from 3-vector seed.
StableRandom(const Vector3 & seed)486 inline float StableRandom(const Vector3& seed) { return StableRandom(Vector2(StableRandom(Vector2(seed.x_, seed.y_)), seed.z_)); }
487
488 }
489