Vector3.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. // Copyright (c) 2008-2023 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. // TODO: Вернуть закомментированный вариант. Это временный workaround для https://github.com/urho3d/urho3d/issues/3147
  192. Vector3& operator =(const Vector3& rhs) noexcept
  193. {
  194. x_ = rhs.x_;
  195. y_ = rhs.y_;
  196. z_ = rhs.z_;
  197. return *this;
  198. }
  199. /// Test for equality with another vector without epsilon.
  200. bool operator ==(const Vector3& rhs) const { return x_ == rhs.x_ && y_ == rhs.y_ && z_ == rhs.z_; }
  201. /// Test for inequality with another vector without epsilon.
  202. bool operator !=(const Vector3& rhs) const { return x_ != rhs.x_ || y_ != rhs.y_ || z_ != rhs.z_; }
  203. /// Add a vector.
  204. Vector3 operator +(const Vector3& rhs) const { return Vector3(x_ + rhs.x_, y_ + rhs.y_, z_ + rhs.z_); }
  205. /// Return negation.
  206. Vector3 operator -() const { return Vector3(-x_, -y_, -z_); }
  207. /// Subtract a vector.
  208. Vector3 operator -(const Vector3& rhs) const { return Vector3(x_ - rhs.x_, y_ - rhs.y_, z_ - rhs.z_); }
  209. /// Multiply with a scalar.
  210. Vector3 operator *(float rhs) const { return Vector3(x_ * rhs, y_ * rhs, z_ * rhs); }
  211. /// Multiply with a vector.
  212. Vector3 operator *(const Vector3& rhs) const { return Vector3(x_ * rhs.x_, y_ * rhs.y_, z_ * rhs.z_); }
  213. /// Divide by a scalar.
  214. Vector3 operator /(float rhs) const { return Vector3(x_ / rhs, y_ / rhs, z_ / rhs); }
  215. /// Divide by a vector.
  216. Vector3 operator /(const Vector3& rhs) const { return Vector3(x_ / rhs.x_, y_ / rhs.y_, z_ / rhs.z_); }
  217. /// Add-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. /// Subtract-assign a vector.
  226. Vector3& operator -=(const Vector3& rhs)
  227. {
  228. x_ -= rhs.x_;
  229. y_ -= rhs.y_;
  230. z_ -= rhs.z_;
  231. return *this;
  232. }
  233. /// Multiply-assign a scalar.
  234. Vector3& operator *=(float rhs)
  235. {
  236. x_ *= rhs;
  237. y_ *= rhs;
  238. z_ *= rhs;
  239. return *this;
  240. }
  241. /// Multiply-assign a vector.
  242. Vector3& operator *=(const Vector3& rhs)
  243. {
  244. x_ *= rhs.x_;
  245. y_ *= rhs.y_;
  246. z_ *= rhs.z_;
  247. return *this;
  248. }
  249. /// Divide-assign a scalar.
  250. Vector3& operator /=(float rhs)
  251. {
  252. float invRhs = 1.0f / rhs;
  253. x_ *= invRhs;
  254. y_ *= invRhs;
  255. z_ *= invRhs;
  256. return *this;
  257. }
  258. /// Divide-assign a vector.
  259. Vector3& operator /=(const Vector3& rhs)
  260. {
  261. x_ /= rhs.x_;
  262. y_ /= rhs.y_;
  263. z_ /= rhs.z_;
  264. return *this;
  265. }
  266. /// Normalize to unit length.
  267. void Normalize()
  268. {
  269. float lenSquared = LengthSquared();
  270. if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
  271. {
  272. float invLen = 1.0f / sqrtf(lenSquared);
  273. x_ *= invLen;
  274. y_ *= invLen;
  275. z_ *= invLen;
  276. }
  277. }
  278. /// Return length.
  279. /// @property
  280. float Length() const { return sqrtf(x_ * x_ + y_ * y_ + z_ * z_); }
  281. /// Return squared length.
  282. /// @property
  283. float LengthSquared() const { return x_ * x_ + y_ * y_ + z_ * z_; }
  284. /// Calculate dot product.
  285. float DotProduct(const Vector3& rhs) const { return x_ * rhs.x_ + y_ * rhs.y_ + z_ * rhs.z_; }
  286. /// Calculate absolute dot product.
  287. float AbsDotProduct(const Vector3& rhs) const
  288. {
  289. return Urho3D::Abs(x_ * rhs.x_) + Urho3D::Abs(y_ * rhs.y_) + Urho3D::Abs(z_ * rhs.z_);
  290. }
  291. /// Project direction vector onto axis.
  292. float ProjectOntoAxis(const Vector3& axis) const { return DotProduct(axis.Normalized()); }
  293. /// Project position vector onto plane with given origin and normal.
  294. Vector3 ProjectOntoPlane(const Vector3& origin, const Vector3& normal) const
  295. {
  296. const Vector3 delta = *this - origin;
  297. return *this - normal.Normalized() * delta.ProjectOntoAxis(normal);
  298. }
  299. /// Project position vector onto line segment.
  300. Vector3 ProjectOntoLine(const Vector3& from, const Vector3& to, bool clamped = false) const
  301. {
  302. const Vector3 direction = to - from;
  303. const float lengthSquared = direction.LengthSquared();
  304. float factor = (*this - from).DotProduct(direction) / lengthSquared;
  305. if (clamped)
  306. factor = Clamp(factor, 0.0f, 1.0f);
  307. return from + direction * factor;
  308. }
  309. /// Calculate distance to another position vector.
  310. float DistanceToPoint(const Vector3& point) const { return (*this - point).Length(); }
  311. /// Calculate distance to the plane with given origin and normal.
  312. float DistanceToPlane(const Vector3& origin, const Vector3& normal) const { return (*this - origin).ProjectOntoAxis(normal); }
  313. /// Make vector orthogonal to the axis.
  314. Vector3 Orthogonalize(const Vector3& axis) const { return axis.CrossProduct(*this).CrossProduct(axis).Normalized(); }
  315. /// Calculate cross product.
  316. Vector3 CrossProduct(const Vector3& rhs) const
  317. {
  318. return Vector3(
  319. y_ * rhs.z_ - z_ * rhs.y_,
  320. z_ * rhs.x_ - x_ * rhs.z_,
  321. x_ * rhs.y_ - y_ * rhs.x_
  322. );
  323. }
  324. /// Return absolute vector.
  325. Vector3 Abs() const { return Vector3(Urho3D::Abs(x_), Urho3D::Abs(y_), Urho3D::Abs(z_)); }
  326. /// Linear interpolation with another vector.
  327. Vector3 Lerp(const Vector3& rhs, float t) const { return *this * (1.0f - t) + rhs * t; }
  328. /// Test for equality with another vector with epsilon.
  329. bool Equals(const Vector3& rhs) const
  330. {
  331. return Urho3D::Equals(x_, rhs.x_) && Urho3D::Equals(y_, rhs.y_) && Urho3D::Equals(z_, rhs.z_);
  332. }
  333. /// Returns the angle between this vector and another vector in degrees.
  334. float Angle(const Vector3& rhs) const { return Urho3D::Acos(DotProduct(rhs) / (Length() * rhs.Length())); }
  335. /// Return whether any component is NaN.
  336. bool IsNaN() const { return Urho3D::IsNaN(x_) || Urho3D::IsNaN(y_) || Urho3D::IsNaN(z_); }
  337. /// Return whether any component is Inf.
  338. bool IsInf() const { return Urho3D::IsInf(x_) || Urho3D::IsInf(y_) || Urho3D::IsInf(z_); }
  339. /// Return normalized to unit length.
  340. Vector3 Normalized() const
  341. {
  342. const float lenSquared = LengthSquared();
  343. if (!Urho3D::Equals(lenSquared, 1.0f) && lenSquared > 0.0f)
  344. {
  345. float invLen = 1.0f / sqrtf(lenSquared);
  346. return *this * invLen;
  347. }
  348. else
  349. return *this;
  350. }
  351. /// Return normalized to unit length or zero if length is too small.
  352. Vector3 NormalizedOrDefault(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. return *this / sqrtf(lenSquared);
  358. }
  359. /// Return normalized vector with length in given range.
  360. Vector3 ReNormalized(float minLength, float maxLength, const Vector3& defaultValue = Vector3::ZERO, float eps = M_LARGE_EPSILON) const
  361. {
  362. const float lenSquared = LengthSquared();
  363. if (lenSquared < eps * eps)
  364. return defaultValue;
  365. const float len = sqrtf(lenSquared);
  366. const float newLen = Clamp(len, minLength, maxLength);
  367. return *this * (newLen / len);
  368. }
  369. /// Return float data.
  370. const float* Data() const { return &x_; }
  371. /// Return as string.
  372. String ToString() const;
  373. /// Return hash value for HashSet & HashMap.
  374. hash32 ToHash() const
  375. {
  376. hash32 hash = 37;
  377. hash = 37 * hash + FloatToRawIntBits(x_);
  378. hash = 37 * hash + FloatToRawIntBits(y_);
  379. hash = 37 * hash + FloatToRawIntBits(z_);
  380. return hash;
  381. }
  382. /// X coordinate.
  383. float x_;
  384. /// Y coordinate.
  385. float y_;
  386. /// Z coordinate.
  387. float z_;
  388. /// Zero vector.
  389. static const Vector3 ZERO;
  390. /// (-1,0,0) vector.
  391. static const Vector3 LEFT;
  392. /// (1,0,0) vector.
  393. static const Vector3 RIGHT;
  394. /// (0,1,0) vector.
  395. static const Vector3 UP;
  396. /// (0,-1,0) vector.
  397. static const Vector3 DOWN;
  398. /// (0,0,1) vector.
  399. static const Vector3 FORWARD;
  400. /// (0,0,-1) vector.
  401. static const Vector3 BACK;
  402. /// (1,1,1) vector.
  403. static const Vector3 ONE;
  404. };
  405. /// Multiply Vector3 with a scalar.
  406. inline Vector3 operator *(float lhs, const Vector3& rhs) { return rhs * lhs; }
  407. /// Multiply IntVector3 with a scalar.
  408. inline IntVector3 operator *(int lhs, const IntVector3& rhs) { return rhs * lhs; }
  409. /// Per-component linear interpolation between two 3-vectors.
  410. inline Vector3 VectorLerp(const Vector3& lhs, const Vector3& rhs, const Vector3& t) { return lhs + (rhs - lhs) * t; }
  411. /// Per-component min of two 3-vectors.
  412. 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_)); }
  413. /// Per-component max of two 3-vectors.
  414. 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_)); }
  415. /// Per-component floor of 3-vector.
  416. inline Vector3 VectorFloor(const Vector3& vec) { return Vector3(Floor(vec.x_), Floor(vec.y_), Floor(vec.z_)); }
  417. /// Per-component round of 3-vector.
  418. inline Vector3 VectorRound(const Vector3& vec) { return Vector3(Round(vec.x_), Round(vec.y_), Round(vec.z_)); }
  419. /// Per-component ceil of 3-vector.
  420. inline Vector3 VectorCeil(const Vector3& vec) { return Vector3(Ceil(vec.x_), Ceil(vec.y_), Ceil(vec.z_)); }
  421. /// Per-component absolute value of 3-vector.
  422. inline Vector3 VectorAbs(const Vector3& vec) { return Vector3(Abs(vec.x_), Abs(vec.y_), Abs(vec.z_)); }
  423. /// Per-component floor of 3-vector. Returns IntVector3.
  424. inline IntVector3 VectorFloorToInt(const Vector3& vec) { return IntVector3(FloorToInt(vec.x_), FloorToInt(vec.y_), FloorToInt(vec.z_)); }
  425. /// Per-component round of 3-vector. Returns IntVector3.
  426. inline IntVector3 VectorRoundToInt(const Vector3& vec) { return IntVector3(RoundToInt(vec.x_), RoundToInt(vec.y_), RoundToInt(vec.z_)); }
  427. /// Per-component ceil of 3-vector. Returns IntVector3.
  428. inline IntVector3 VectorCeilToInt(const Vector3& vec) { return IntVector3(CeilToInt(vec.x_), CeilToInt(vec.y_), CeilToInt(vec.z_)); }
  429. /// Per-component min of two 3-vectors.
  430. 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_)); }
  431. /// Per-component max of two 3-vectors.
  432. 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_)); }
  433. /// Per-component absolute value of integer 3-vector.
  434. inline IntVector3 VectorAbs(const IntVector3& vec) { return IntVector3(Abs(vec.x_), Abs(vec.y_), Abs(vec.z_)); }
  435. /// Return a random value from [0, 1) from 3-vector seed.
  436. inline float StableRandom(const Vector3& seed) { return StableRandom(Vector2(StableRandom(Vector2(seed.x_, seed.y_)), seed.z_)); }
  437. }