AABB.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. // file: core/math/aabb.h
  2. // commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
  3. // file: core/math/aabb.cpp
  4. // commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
  5. // file: core/variant_call.cpp
  6. // commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
  7. using System;
  8. #if REAL_T_IS_DOUBLE
  9. using real_t = System.Double;
  10. #else
  11. using real_t = System.Single;
  12. #endif
  13. namespace Godot
  14. {
  15. public struct AABB : IEquatable<AABB>
  16. {
  17. private Vector3 _position;
  18. private Vector3 _size;
  19. public Vector3 Position
  20. {
  21. get { return _position; }
  22. set { _position = value; }
  23. }
  24. public Vector3 Size
  25. {
  26. get { return _size; }
  27. set { _size = value; }
  28. }
  29. public Vector3 End
  30. {
  31. get { return _position + _size; }
  32. set { _size = value - _position; }
  33. }
  34. public bool Encloses(AABB with)
  35. {
  36. Vector3 src_min = _position;
  37. Vector3 src_max = _position + _size;
  38. Vector3 dst_min = with._position;
  39. Vector3 dst_max = with._position + with._size;
  40. return src_min.x <= dst_min.x &&
  41. src_max.x > dst_max.x &&
  42. src_min.y <= dst_min.y &&
  43. src_max.y > dst_max.y &&
  44. src_min.z <= dst_min.z &&
  45. src_max.z > dst_max.z;
  46. }
  47. public AABB Expand(Vector3 point)
  48. {
  49. Vector3 begin = _position;
  50. Vector3 end = _position + _size;
  51. if (point.x < begin.x)
  52. begin.x = point.x;
  53. if (point.y < begin.y)
  54. begin.y = point.y;
  55. if (point.z < begin.z)
  56. begin.z = point.z;
  57. if (point.x > end.x)
  58. end.x = point.x;
  59. if (point.y > end.y)
  60. end.y = point.y;
  61. if (point.z > end.z)
  62. end.z = point.z;
  63. return new AABB(begin, end - begin);
  64. }
  65. public real_t GetArea()
  66. {
  67. return _size.x * _size.y * _size.z;
  68. }
  69. public Vector3 GetEndpoint(int idx)
  70. {
  71. switch (idx)
  72. {
  73. case 0:
  74. return new Vector3(_position.x, _position.y, _position.z);
  75. case 1:
  76. return new Vector3(_position.x, _position.y, _position.z + _size.z);
  77. case 2:
  78. return new Vector3(_position.x, _position.y + _size.y, _position.z);
  79. case 3:
  80. return new Vector3(_position.x, _position.y + _size.y, _position.z + _size.z);
  81. case 4:
  82. return new Vector3(_position.x + _size.x, _position.y, _position.z);
  83. case 5:
  84. return new Vector3(_position.x + _size.x, _position.y, _position.z + _size.z);
  85. case 6:
  86. return new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z);
  87. case 7:
  88. return new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z + _size.z);
  89. default:
  90. throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
  91. }
  92. }
  93. public Vector3 GetLongestAxis()
  94. {
  95. var axis = new Vector3(1f, 0f, 0f);
  96. real_t max_size = _size.x;
  97. if (_size.y > max_size)
  98. {
  99. axis = new Vector3(0f, 1f, 0f);
  100. max_size = _size.y;
  101. }
  102. if (_size.z > max_size)
  103. {
  104. axis = new Vector3(0f, 0f, 1f);
  105. }
  106. return axis;
  107. }
  108. public Vector3.Axis GetLongestAxisIndex()
  109. {
  110. var axis = Vector3.Axis.X;
  111. real_t max_size = _size.x;
  112. if (_size.y > max_size)
  113. {
  114. axis = Vector3.Axis.Y;
  115. max_size = _size.y;
  116. }
  117. if (_size.z > max_size)
  118. {
  119. axis = Vector3.Axis.Z;
  120. }
  121. return axis;
  122. }
  123. public real_t GetLongestAxisSize()
  124. {
  125. real_t max_size = _size.x;
  126. if (_size.y > max_size)
  127. max_size = _size.y;
  128. if (_size.z > max_size)
  129. max_size = _size.z;
  130. return max_size;
  131. }
  132. public Vector3 GetShortestAxis()
  133. {
  134. var axis = new Vector3(1f, 0f, 0f);
  135. real_t max_size = _size.x;
  136. if (_size.y < max_size)
  137. {
  138. axis = new Vector3(0f, 1f, 0f);
  139. max_size = _size.y;
  140. }
  141. if (_size.z < max_size)
  142. {
  143. axis = new Vector3(0f, 0f, 1f);
  144. }
  145. return axis;
  146. }
  147. public Vector3.Axis GetShortestAxisIndex()
  148. {
  149. var axis = Vector3.Axis.X;
  150. real_t max_size = _size.x;
  151. if (_size.y < max_size)
  152. {
  153. axis = Vector3.Axis.Y;
  154. max_size = _size.y;
  155. }
  156. if (_size.z < max_size)
  157. {
  158. axis = Vector3.Axis.Z;
  159. }
  160. return axis;
  161. }
  162. public real_t GetShortestAxisSize()
  163. {
  164. real_t max_size = _size.x;
  165. if (_size.y < max_size)
  166. max_size = _size.y;
  167. if (_size.z < max_size)
  168. max_size = _size.z;
  169. return max_size;
  170. }
  171. public Vector3 GetSupport(Vector3 dir)
  172. {
  173. Vector3 half_extents = _size * 0.5f;
  174. Vector3 ofs = _position + half_extents;
  175. return ofs + new Vector3(
  176. dir.x > 0f ? -half_extents.x : half_extents.x,
  177. dir.y > 0f ? -half_extents.y : half_extents.y,
  178. dir.z > 0f ? -half_extents.z : half_extents.z);
  179. }
  180. public AABB Grow(real_t by)
  181. {
  182. var res = this;
  183. res._position.x -= by;
  184. res._position.y -= by;
  185. res._position.z -= by;
  186. res._size.x += 2.0f * by;
  187. res._size.y += 2.0f * by;
  188. res._size.z += 2.0f * by;
  189. return res;
  190. }
  191. public bool HasNoArea()
  192. {
  193. return _size.x <= 0f || _size.y <= 0f || _size.z <= 0f;
  194. }
  195. public bool HasNoSurface()
  196. {
  197. return _size.x <= 0f && _size.y <= 0f && _size.z <= 0f;
  198. }
  199. public bool HasPoint(Vector3 point)
  200. {
  201. if (point.x < _position.x)
  202. return false;
  203. if (point.y < _position.y)
  204. return false;
  205. if (point.z < _position.z)
  206. return false;
  207. if (point.x > _position.x + _size.x)
  208. return false;
  209. if (point.y > _position.y + _size.y)
  210. return false;
  211. if (point.z > _position.z + _size.z)
  212. return false;
  213. return true;
  214. }
  215. public AABB Intersection(AABB with)
  216. {
  217. Vector3 src_min = _position;
  218. Vector3 src_max = _position + _size;
  219. Vector3 dst_min = with._position;
  220. Vector3 dst_max = with._position + with._size;
  221. Vector3 min, max;
  222. if (src_min.x > dst_max.x || src_max.x < dst_min.x)
  223. {
  224. return new AABB();
  225. }
  226. min.x = src_min.x > dst_min.x ? src_min.x : dst_min.x;
  227. max.x = src_max.x < dst_max.x ? src_max.x : dst_max.x;
  228. if (src_min.y > dst_max.y || src_max.y < dst_min.y)
  229. {
  230. return new AABB();
  231. }
  232. min.y = src_min.y > dst_min.y ? src_min.y : dst_min.y;
  233. max.y = src_max.y < dst_max.y ? src_max.y : dst_max.y;
  234. if (src_min.z > dst_max.z || src_max.z < dst_min.z)
  235. {
  236. return new AABB();
  237. }
  238. min.z = src_min.z > dst_min.z ? src_min.z : dst_min.z;
  239. max.z = src_max.z < dst_max.z ? src_max.z : dst_max.z;
  240. return new AABB(min, max - min);
  241. }
  242. public bool Intersects(AABB with)
  243. {
  244. if (_position.x >= with._position.x + with._size.x)
  245. return false;
  246. if (_position.x + _size.x <= with._position.x)
  247. return false;
  248. if (_position.y >= with._position.y + with._size.y)
  249. return false;
  250. if (_position.y + _size.y <= with._position.y)
  251. return false;
  252. if (_position.z >= with._position.z + with._size.z)
  253. return false;
  254. if (_position.z + _size.z <= with._position.z)
  255. return false;
  256. return true;
  257. }
  258. public bool IntersectsPlane(Plane plane)
  259. {
  260. Vector3[] points =
  261. {
  262. new Vector3(_position.x, _position.y, _position.z),
  263. new Vector3(_position.x, _position.y, _position.z + _size.z),
  264. new Vector3(_position.x, _position.y + _size.y, _position.z),
  265. new Vector3(_position.x, _position.y + _size.y, _position.z + _size.z),
  266. new Vector3(_position.x + _size.x, _position.y, _position.z),
  267. new Vector3(_position.x + _size.x, _position.y, _position.z + _size.z),
  268. new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z),
  269. new Vector3(_position.x + _size.x, _position.y + _size.y, _position.z + _size.z)
  270. };
  271. bool over = false;
  272. bool under = false;
  273. for (int i = 0; i < 8; i++)
  274. {
  275. if (plane.DistanceTo(points[i]) > 0)
  276. over = true;
  277. else
  278. under = true;
  279. }
  280. return under && over;
  281. }
  282. public bool IntersectsSegment(Vector3 from, Vector3 to)
  283. {
  284. real_t min = 0f;
  285. real_t max = 1f;
  286. for (int i = 0; i < 3; i++)
  287. {
  288. real_t segFrom = from[i];
  289. real_t segTo = to[i];
  290. real_t boxBegin = _position[i];
  291. real_t boxEnd = boxBegin + _size[i];
  292. real_t cmin, cmax;
  293. if (segFrom < segTo)
  294. {
  295. if (segFrom > boxEnd || segTo < boxBegin)
  296. return false;
  297. real_t length = segTo - segFrom;
  298. cmin = segFrom < boxBegin ? (boxBegin - segFrom) / length : 0f;
  299. cmax = segTo > boxEnd ? (boxEnd - segFrom) / length : 1f;
  300. }
  301. else
  302. {
  303. if (segTo > boxEnd || segFrom < boxBegin)
  304. return false;
  305. real_t length = segTo - segFrom;
  306. cmin = segFrom > boxEnd ? (boxEnd - segFrom) / length : 0f;
  307. cmax = segTo < boxBegin ? (boxBegin - segFrom) / length : 1f;
  308. }
  309. if (cmin > min)
  310. {
  311. min = cmin;
  312. }
  313. if (cmax < max)
  314. max = cmax;
  315. if (max < min)
  316. return false;
  317. }
  318. return true;
  319. }
  320. public AABB Merge(AABB with)
  321. {
  322. Vector3 beg1 = _position;
  323. Vector3 beg2 = with._position;
  324. var end1 = new Vector3(_size.x, _size.y, _size.z) + beg1;
  325. var end2 = new Vector3(with._size.x, with._size.y, with._size.z) + beg2;
  326. var min = new Vector3(
  327. beg1.x < beg2.x ? beg1.x : beg2.x,
  328. beg1.y < beg2.y ? beg1.y : beg2.y,
  329. beg1.z < beg2.z ? beg1.z : beg2.z
  330. );
  331. var max = new Vector3(
  332. end1.x > end2.x ? end1.x : end2.x,
  333. end1.y > end2.y ? end1.y : end2.y,
  334. end1.z > end2.z ? end1.z : end2.z
  335. );
  336. return new AABB(min, max - min);
  337. }
  338. // Constructors
  339. public AABB(Vector3 position, Vector3 size)
  340. {
  341. _position = position;
  342. _size = size;
  343. }
  344. public static bool operator ==(AABB left, AABB right)
  345. {
  346. return left.Equals(right);
  347. }
  348. public static bool operator !=(AABB left, AABB right)
  349. {
  350. return !left.Equals(right);
  351. }
  352. public override bool Equals(object obj)
  353. {
  354. if (obj is AABB)
  355. {
  356. return Equals((AABB)obj);
  357. }
  358. return false;
  359. }
  360. public bool Equals(AABB other)
  361. {
  362. return _position == other._position && _size == other._size;
  363. }
  364. public override int GetHashCode()
  365. {
  366. return _position.GetHashCode() ^ _size.GetHashCode();
  367. }
  368. public override string ToString()
  369. {
  370. return String.Format("{0} - {1}", new object[]
  371. {
  372. _position.ToString(),
  373. _size.ToString()
  374. });
  375. }
  376. public string ToString(string format)
  377. {
  378. return String.Format("{0} - {1}", new object[]
  379. {
  380. _position.ToString(format),
  381. _size.ToString(format)
  382. });
  383. }
  384. }
  385. }