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