Vector3.h 16 KB

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