Vector3.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. //
  2. // Copyright (c) 2008-2020 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. #pragma once
  23. #include "../Math/Vector2.h"
  24. #include "../Math/MathDefs.h"
  25. namespace Urho3D
  26. {
  27. /// Three-dimensional vector with integer values.
  28. class URHO3D_API IntVector3
  29. {
  30. public:
  31. /// Construct a zero vector.
  32. IntVector3() noexcept :
  33. x_(0),
  34. y_(0),
  35. z_(0)
  36. {
  37. }
  38. /// Construct from coordinates.
  39. IntVector3(int x, int y, int z) noexcept :
  40. x_(x),
  41. y_(y),
  42. z_(z)
  43. {
  44. }
  45. /// Construct from an int array.
  46. explicit IntVector3(const int* data) noexcept :
  47. x_(data[0]),
  48. y_(data[1]),
  49. z_(data[2])
  50. {
  51. }
  52. /// Copy-construct from another vector.
  53. IntVector3(const IntVector3& rhs) noexcept = default;
  54. /// Assign from another vector.
  55. IntVector3& operator =(const IntVector3& rhs) noexcept = default;
  56. /// Test for equality with another vector.
  57. bool operator ==(const IntVector3& rhs) const { return x_ == rhs.x_ && y_ == rhs.y_ && z_ == rhs.z_; }
  58. /// Test for inequality with another vector.
  59. bool operator !=(const IntVector3& rhs) const { return x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_; }
  60. /// Add a vector.
  61. IntVector3 operator +(const IntVector3& rhs) const { return IntVector3(x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
  62. /// Return negation.
  63. IntVector3 operator -() const { return IntVector3(-x_, -y_, -z_); }
  64. /// Subtract a vector.
  65. IntVector3 operator -(const IntVector3& rhs) const { return IntVector3(x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
  66. /// Multiply with a scalar.
  67. IntVector3 operator *(int rhs) const { return IntVector3(x_ * rhs, y_ * rhs, z_ * rhs); }
  68. /// Multiply with a vector.
  69. IntVector3 operator *(const IntVector3& rhs) const { return IntVector3(x_ * rhs.x_, y_ * rhs.y_, z_ * rhs.z_); }
  70. /// Divide by a scalar.
  71. IntVector3 operator /(int rhs) const { return IntVector3(x_ / rhs, y_ / rhs, z_ / rhs); }
  72. /// Divide by a vector.
  73. IntVector3 operator /(const IntVector3& rhs) const { return IntVector3(x_ / rhs.x_, y_ / rhs.y_, z_ / rhs.z_); }
  74. /// Add-assign a vector.
  75. IntVector3& operator +=(const IntVector3& rhs)
  76. {
  77. x_ += rhs.x_;
  78. y_ += rhs.y_;
  79. z_ += rhs.z_;
  80. return *this;
  81. }
  82. /// Subtract-assign a vector.
  83. IntVector3& operator -=(const IntVector3& rhs)
  84. {
  85. x_ -= rhs.x_;
  86. y_ -= rhs.y_;
  87. z_ -= rhs.z_;
  88. return *this;
  89. }
  90. /// Multiply-assign a scalar.
  91. IntVector3& operator *=(int rhs)
  92. {
  93. x_ *= rhs;
  94. y_ *= rhs;
  95. z_ *= rhs;
  96. return *this;
  97. }
  98. /// Multiply-assign a vector.
  99. IntVector3& operator *=(const IntVector3& rhs)
  100. {
  101. x_ *= rhs.x_;
  102. y_ *= rhs.y_;
  103. z_ *= rhs.z_;
  104. return *this;
  105. }
  106. /// Divide-assign a scalar.
  107. IntVector3& operator /=(int rhs)
  108. {
  109. x_ /= rhs;
  110. y_ /= rhs;
  111. z_ /= rhs;
  112. return *this;
  113. }
  114. /// Divide-assign a vector.
  115. IntVector3& operator /=(const IntVector3& rhs)
  116. {
  117. x_ /= rhs.x_;
  118. y_ /= rhs.y_;
  119. z_ /= rhs.z_;
  120. return *this;
  121. }
  122. /// Return integer data.
  123. const int* Data() const { return &x_; }
  124. /// Return as string.
  125. String ToString() const;
  126. /// Return hash value for HashSet & HashMap.
  127. unsigned ToHash() const { return (unsigned)x_ * 31 * 31 + (unsigned)y_ * 31 + (unsigned)z_; }
  128. /// Return length.
  129. float Length() const { return sqrtf((float)(x_ * x_ + y_ * y_ + z_ * z_)); }
  130. /// X coordinate.
  131. int x_;
  132. /// Y coordinate.
  133. int y_;
  134. /// Z coordinate.
  135. int z_;
  136. /// Zero vector.
  137. static const IntVector3 ZERO;
  138. /// (-1,0,0) vector.
  139. static const IntVector3 LEFT;
  140. /// (1,0,0) vector.
  141. static const IntVector3 RIGHT;
  142. /// (0,1,0) vector.
  143. static const IntVector3 UP;
  144. /// (0,-1,0) vector.
  145. static const IntVector3 DOWN;
  146. /// (0,0,1) vector.
  147. static const IntVector3 FORWARD;
  148. /// (0,0,-1) vector.
  149. static const IntVector3 BACK;
  150. /// (1,1,1) vector.
  151. static const IntVector3 ONE;
  152. };
  153. /// Three-dimensional vector.
  154. class URHO3D_API Vector3
  155. {
  156. public:
  157. /// Construct a zero vector.
  158. Vector3() noexcept :
  159. x_(0.0f),
  160. y_(0.0f),
  161. z_(0.0f)
  162. {
  163. }
  164. /// Copy-construct from another vector.
  165. Vector3(const Vector3& vector) noexcept = default;
  166. /// Construct from a two-dimensional vector and the Z coordinate.
  167. Vector3(const Vector2& vector, float z) noexcept :
  168. x_(vector.x_),
  169. y_(vector.y_),
  170. z_(z)
  171. {
  172. }
  173. /// Construct from a two-dimensional vector (for Urho2D).
  174. explicit Vector3(const Vector2& vector) noexcept :
  175. x_(vector.x_),
  176. y_(vector.y_),
  177. z_(0.0f)
  178. {
  179. }
  180. /// Construct from an IntVector3.
  181. explicit Vector3(const IntVector3& vector) noexcept :
  182. x_((float)vector.x_),
  183. y_((float)vector.y_),
  184. z_((float)vector.z_)
  185. {
  186. }
  187. /// Construct from coordinates.
  188. Vector3(float x, float y, float z) noexcept :
  189. x_(x),
  190. y_(y),
  191. z_(z)
  192. {
  193. }
  194. /// Construct from two-dimensional coordinates (for Urho2D).
  195. Vector3(float x, float y) noexcept :
  196. x_(x),
  197. y_(y),
  198. z_(0.0f)
  199. {
  200. }
  201. /// Construct from a float array.
  202. explicit Vector3(const float* data) noexcept :
  203. x_(data[0]),
  204. y_(data[1]),
  205. z_(data[2])
  206. {
  207. }
  208. /// Assign from another vector.
  209. Vector3& operator =(const Vector3& rhs) noexcept = default;
  210. /// Test for equality with another vector without epsilon.
  211. bool operator ==(const Vector3& rhs) const { return x_ == rhs.x_ && y_ == rhs.y_ && z_ == rhs.z_; }
  212. /// Test for inequality with another vector without epsilon.
  213. bool operator !=(const Vector3& rhs) const { return x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_; }
  214. /// Add a vector.
  215. Vector3 operator +(const Vector3& rhs) const { return Vector3(x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
  216. /// Return negation.
  217. Vector3 operator -() const { return Vector3(-x_, -y_, -z_); }
  218. /// Subtract a vector.
  219. Vector3 operator -(const Vector3& rhs) const { return Vector3(x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
  220. /// Multiply with a scalar.
  221. Vector3 operator *(float rhs) const { return Vector3(x_ * rhs, y_ * rhs, z_ * rhs); }
  222. /// Multiply with a vector.
  223. Vector3 operator *(const Vector3& rhs) const { return Vector3(x_ * rhs.x_, y_ * rhs.y_, z_ * rhs.z_); }
  224. /// Divide by a scalar.
  225. Vector3 operator /(float rhs) const { return Vector3(x_ / rhs, y_ / rhs, z_ / rhs); }
  226. /// Divide by a vector.
  227. Vector3 operator /(const Vector3& rhs) const { return Vector3(x_ / rhs.x_, y_ / rhs.y_, z_ / rhs.z_); }
  228. /// Add-assign a vector.
  229. Vector3& operator +=(const Vector3& rhs)
  230. {
  231. x_ += rhs.x_;
  232. y_ += rhs.y_;
  233. z_ += rhs.z_;
  234. return *this;
  235. }
  236. /// Subtract-assign a vector.
  237. Vector3& operator -=(const Vector3& rhs)
  238. {
  239. x_ -= rhs.x_;
  240. y_ -= rhs.y_;
  241. z_ -= rhs.z_;
  242. return *this;
  243. }
  244. /// Multiply-assign a scalar.
  245. Vector3& operator *=(float rhs)
  246. {
  247. x_ *= rhs;
  248. y_ *= rhs;
  249. z_ *= rhs;
  250. return *this;
  251. }
  252. /// Multiply-assign a vector.
  253. Vector3& operator *=(const Vector3& rhs)
  254. {
  255. x_ *= rhs.x_;
  256. y_ *= rhs.y_;
  257. z_ *= rhs.z_;
  258. return *this;
  259. }
  260. /// Divide-assign a scalar.
  261. Vector3& operator /=(float rhs)
  262. {
  263. float invRhs = 1.0f / rhs;
  264. x_ *= invRhs;
  265. y_ *= invRhs;
  266. z_ *= invRhs;
  267. return *this;
  268. }
  269. /// Divide-assign a vector.
  270. Vector3& operator /=(const Vector3& rhs)
  271. {
  272. x_ /= rhs.x_;
  273. y_ /= rhs.y_;
  274. z_ /= rhs.z_;
  275. return *this;
  276. }
  277. /// Normalize to unit length.
  278. void Normalize()
  279. {
  280. float lenSquared = LengthSquared();
  281. if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
  282. {
  283. float invLen = 1.0f / sqrtf(lenSquared);
  284. x_ *= invLen;
  285. y_ *= invLen;
  286. z_ *= invLen;
  287. }
  288. }
  289. /// Return length.
  290. /// @property
  291. float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_); }
  292. /// Return squared length.
  293. /// @property
  294. float LengthSquared() const { return x_ * x_ + y_ * y_ + z_ * z_; }
  295. /// Calculate dot product.
  296. float DotProduct(const Vector3& rhs) const { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
  297. /// Calculate absolute dot product.
  298. float AbsDotProduct(const Vector3& rhs) const
  299. {
  300. return Urho3D::Abs(x_ * rhs.x_) + Urho3D::Abs(y_ * rhs.y_) + Urho3D::Abs(z_ * rhs.z_);
  301. }
  302. /// Project direction vector onto axis.
  303. float ProjectOntoAxis(const Vector3& axis) const { return DotProduct(axis.Normalized()); }
  304. /// Project position vector onto plane with given origin and normal.
  305. Vector3 ProjectOntoPlane(const Vector3& origin, const Vector3& normal) const
  306. {
  307. const Vector3 delta = *this - origin;
  308. return *this - normal.Normalized() * delta.ProjectOntoAxis(normal);
  309. }
  310. /// Project position vector onto line segment.
  311. Vector3 ProjectOntoLine(const Vector3& from, const Vector3& to, bool clamped = false) const
  312. {
  313. const Vector3 direction = to - from;
  314. const float lengthSquared = direction.LengthSquared();
  315. float factor = (*this - from).DotProduct(direction) / lengthSquared;
  316. if (clamped)
  317. factor = Clamp(factor, 0.0f, 1.0f);
  318. return from + direction * factor;
  319. }
  320. /// Calculate distance to another position vector.
  321. float DistanceToPoint(const Vector3& point) const { return (*this - point).Length(); }
  322. /// Calculate distance to the plane with given origin and normal.
  323. float DistanceToPlane(const Vector3& origin, const Vector3& normal) const { return (*this - origin).ProjectOntoAxis(normal); }
  324. /// Make vector orthogonal to the axis.
  325. Vector3 Orthogonalize(const Vector3& axis) const { return axis.CrossProduct(*this).CrossProduct(axis).Normalized(); }
  326. /// Calculate cross product.
  327. Vector3 CrossProduct(const Vector3& rhs) const
  328. {
  329. return Vector3(
  330. y_ * rhs.z_ - z_ * rhs.y_,
  331. z_ * rhs.x_ - x_ * rhs.z_,
  332. x_ * rhs.y_ - y_ * rhs.x_
  333. );
  334. }
  335. /// Return absolute vector.
  336. Vector3 Abs() const { return Vector3(Urho3D::Abs(x_), Urho3D::Abs(y_), Urho3D::Abs(z_)); }
  337. /// Linear interpolation with another vector.
  338. Vector3 Lerp(const Vector3& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
  339. /// Test for equality with another vector with epsilon.
  340. bool Equals(const Vector3& rhs) const
  341. {
  342. return Urho3D::Equals(x_, rhs.x_) && Urho3D::Equals(y_, rhs.y_) && Urho3D::Equals(z_, rhs.z_);
  343. }
  344. /// Returns the angle between this vector and another vector in degrees.
  345. float Angle(const Vector3& rhs) const { return Urho3D::Acos(DotProduct(rhs) / (Length() * rhs.Length())); }
  346. /// Return whether any component is NaN.
  347. bool IsNaN() const { return Urho3D::IsNaN(x_) || Urho3D::IsNaN(y_) || Urho3D::IsNaN(z_); }
  348. /// Return whether any component is Inf.
  349. bool IsInf() const { return Urho3D::IsInf(x_) || Urho3D::IsInf(y_) || Urho3D::IsInf(z_); }
  350. /// Return normalized to unit length.
  351. Vector3 Normalized() const
  352. {
  353. const float lenSquared = LengthSquared();
  354. if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
  355. {
  356. float invLen = 1.0f / sqrtf(lenSquared);
  357. return *this * invLen;
  358. }
  359. else
  360. return *this;
  361. }
  362. /// Return normalized to unit length or zero if length is too small.
  363. Vector3 NormalizedOrDefault(const Vector3& defaultValue = Vector3::ZERO, float eps = M_LARGE_EPSILON) const
  364. {
  365. const float lenSquared = LengthSquared();
  366. if (lenSquared < eps * eps)
  367. return defaultValue;
  368. return *this / sqrtf(lenSquared);
  369. }
  370. /// Return normalized vector with length in given range.
  371. Vector3 ReNormalized(float minLength, float maxLength, const Vector3& defaultValue = Vector3::ZERO, float eps = M_LARGE_EPSILON) const
  372. {
  373. const float lenSquared = LengthSquared();
  374. if (lenSquared < eps * eps)
  375. return defaultValue;
  376. const float len = sqrtf(lenSquared);
  377. const float newLen = Clamp(len, minLength, maxLength);
  378. return *this * (newLen / len);
  379. }
  380. /// Return float data.
  381. const float* Data() const { return &x_; }
  382. /// Return as string.
  383. String ToString() const;
  384. /// Return hash value for HashSet & HashMap.
  385. unsigned ToHash() const
  386. {
  387. unsigned hash = 37;
  388. hash = 37 * hash + FloatToRawIntBits(x_);
  389. hash = 37 * hash + FloatToRawIntBits(y_);
  390. hash = 37 * hash + FloatToRawIntBits(z_);
  391. return hash;
  392. }
  393. /// X coordinate.
  394. float x_;
  395. /// Y coordinate.
  396. float y_;
  397. /// Z coordinate.
  398. float z_;
  399. /// Zero vector.
  400. static const Vector3 ZERO;
  401. /// (-1,0,0) vector.
  402. static const Vector3 LEFT;
  403. /// (1,0,0) vector.
  404. static const Vector3 RIGHT;
  405. /// (0,1,0) vector.
  406. static const Vector3 UP;
  407. /// (0,-1,0) vector.
  408. static const Vector3 DOWN;
  409. /// (0,0,1) vector.
  410. static const Vector3 FORWARD;
  411. /// (0,0,-1) vector.
  412. static const Vector3 BACK;
  413. /// (1,1,1) vector.
  414. static const Vector3 ONE;
  415. };
  416. /// Multiply Vector3 with a scalar.
  417. inline Vector3 operator *(float lhs, const Vector3& rhs) { return rhs * lhs; }
  418. /// Multiply IntVector3 with a scalar.
  419. inline IntVector3 operator *(int lhs, const IntVector3& rhs) { return rhs * lhs; }
  420. /// Per-component linear interpolation between two 3-vectors.
  421. inline Vector3 VectorLerp(const Vector3& lhs, const Vector3& rhs, const Vector3& t) { return lhs + (rhs - lhs) * t; }
  422. /// Per-component min of two 3-vectors.
  423. 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_)); }
  424. /// Per-component max of two 3-vectors.
  425. 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_)); }
  426. /// Per-component floor of 3-vector.
  427. inline Vector3 VectorFloor(const Vector3& vec) { return Vector3(Floor(vec.x_), Floor(vec.y_), Floor(vec.z_)); }
  428. /// Per-component round of 3-vector.
  429. inline Vector3 VectorRound(const Vector3& vec) { return Vector3(Round(vec.x_), Round(vec.y_), Round(vec.z_)); }
  430. /// Per-component ceil of 3-vector.
  431. inline Vector3 VectorCeil(const Vector3& vec) { return Vector3(Ceil(vec.x_), Ceil(vec.y_), Ceil(vec.z_)); }
  432. /// Per-component absolute value of 3-vector.
  433. inline Vector3 VectorAbs(const Vector3& vec) { return Vector3(Abs(vec.x_), Abs(vec.y_), Abs(vec.z_)); }
  434. /// Per-component floor of 3-vector. Returns IntVector3.
  435. inline IntVector3 VectorFloorToInt(const Vector3& vec) { return IntVector3(FloorToInt(vec.x_), FloorToInt(vec.y_), FloorToInt(vec.z_)); }
  436. /// Per-component round of 3-vector. Returns IntVector3.
  437. inline IntVector3 VectorRoundToInt(const Vector3& vec) { return IntVector3(RoundToInt(vec.x_), RoundToInt(vec.y_), RoundToInt(vec.z_)); }
  438. /// Per-component ceil of 3-vector. Returns IntVector3.
  439. inline IntVector3 VectorCeilToInt(const Vector3& vec) { return IntVector3(CeilToInt(vec.x_), CeilToInt(vec.y_), CeilToInt(vec.z_)); }
  440. /// Per-component min of two 3-vectors.
  441. 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_)); }
  442. /// Per-component max of two 3-vectors.
  443. 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_)); }
  444. /// Per-component absolute value of integer 3-vector.
  445. inline IntVector3 VectorAbs(const IntVector3& vec) { return IntVector3(Abs(vec.x_), Abs(vec.y_), Abs(vec.z_)); }
  446. /// Return a random value from [0, 1) from 3-vector seed.
  447. inline float StableRandom(const Vector3& seed) { return StableRandom(Vector2(StableRandom(Vector2(seed.x_, seed.y_)), seed.z_)); }
  448. }