Box.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using UnityEditor;
  4. using System;
  5. using System.Collections.Generic;
  6. namespace O3DWB
  7. {
  8. public struct Box
  9. {
  10. #region Private Variables
  11. private Vector3 _min;
  12. private Vector3 _max;
  13. #endregion
  14. #region Public Properties
  15. public Vector3 Min { get { return _min; } set { _min = value; } }
  16. public Vector3 Max { get { return _max; } set { _max = value; } }
  17. public Vector3 Extents { get { return Size * 0.5f; } }
  18. public Vector3 Size
  19. {
  20. get { return _max - _min; }
  21. set
  22. {
  23. Vector3 currentCenter = Center;
  24. Vector3 extents = (value * 0.5f).GetVectorWithPositiveComponents();
  25. _max = currentCenter + extents;
  26. _min = currentCenter - extents;
  27. }
  28. }
  29. public Vector3 Center
  30. {
  31. get { return (_min + _max) * 0.5f; }
  32. set
  33. {
  34. Vector3 extents = Extents;
  35. _max = value + extents;
  36. _min = value - extents;
  37. }
  38. }
  39. #endregion
  40. #region Constructors
  41. public Box(Bounds bounds)
  42. {
  43. _min = bounds.min;
  44. _max = bounds.max;
  45. }
  46. public Box(Vector3 center, Vector3 size)
  47. {
  48. _min = Vector3.zero;
  49. _max = Vector3.zero;
  50. Size = size;
  51. Center = center;
  52. }
  53. public Box(Box source)
  54. {
  55. _min = source.Min;
  56. _max = source.Max;
  57. }
  58. #endregion
  59. #region Public Static Functions
  60. public static Box GetInvalid()
  61. {
  62. var box = new Box();
  63. box.MakeInvalid();
  64. return box;
  65. }
  66. public static Box FromObjectWorldAABB(IEnumerable<GameObject> gameObjects)
  67. {
  68. if (gameObjects == null) return Box.GetInvalid();
  69. Box finalAABB = Box.GetInvalid();
  70. foreach(var gameObject in gameObjects)
  71. {
  72. Box worldAABB = gameObject.GetWorldBox();
  73. if(worldAABB.IsValid())
  74. {
  75. if (finalAABB.IsValid()) finalAABB.Encapsulate(worldAABB);
  76. else finalAABB = worldAABB;
  77. }
  78. }
  79. return finalAABB;
  80. }
  81. public static Box FromPoints(List<Vector3> points, float sizeScale = 1.0f)
  82. {
  83. if (points.Count == 0) return GetInvalid();
  84. Vector3 min = points[0];
  85. Vector3 max = points[0];
  86. for(int pointIndex = 1; pointIndex < points.Count; ++pointIndex)
  87. {
  88. Vector3 point = points[pointIndex];
  89. min = Vector3.Min(min, point);
  90. max = Vector3.Max(max, point);
  91. }
  92. Vector3 center = (min + max) * 0.5f;
  93. Vector3 size = (max - min) * sizeScale;
  94. return new Box(center, size);
  95. }
  96. public static Box FromMinMax(Vector3 min, Vector3 max)
  97. {
  98. Vector3 center = (min + max) * 0.5f;
  99. Vector3 size = (max - min);
  100. return new Box(center, size);
  101. }
  102. #endregion
  103. #region Public Methods
  104. public Bounds ToBounds()
  105. {
  106. return new Bounds(Center, Size);
  107. }
  108. public void MoveInFrontOfPlane(Plane plane)
  109. {
  110. List<Vector3> boxPts = GetCornerPoints();
  111. int ptIndex = plane.GetIndexOfFurthestPointBehind(boxPts);
  112. if (ptIndex < 0) ptIndex = plane.GetIndexOfClosestPointInFrontOrOnPlane(boxPts);
  113. if (ptIndex >= 0)
  114. {
  115. float distToPt = plane.GetDistanceToPoint(boxPts[ptIndex]);
  116. Center -= plane.normal * distToPt;
  117. }
  118. }
  119. public OrientedBox ToOrientedBox()
  120. {
  121. Box modelSpaceBox = new Box(Vector3.zero, Size);
  122. OrientedBox orientedBox = new OrientedBox(modelSpaceBox, Quaternion.identity);
  123. orientedBox.Center = Center;
  124. return orientedBox;
  125. }
  126. public Sphere GetEncpasulatingSphere()
  127. {
  128. return new Sphere(Center, Extents.magnitude);
  129. }
  130. public void Encapsulate(Bounds bounds)
  131. {
  132. Encapsulate(new Box(bounds));
  133. }
  134. public void Encapsulate(Box box)
  135. {
  136. AddPoint(box.Min);
  137. AddPoint(box.Max);
  138. }
  139. public void AddPoint(Vector3 point)
  140. {
  141. if (point.x < _min.x) _min.x = point.x;
  142. if (point.y < _min.y) _min.y = point.y;
  143. if (point.z < _min.z) _min.z = point.z;
  144. if (point.x > _max.x) _max.x = point.x;
  145. if (point.y > _max.y) _max.y = point.y;
  146. if (point.z > _max.z) _max.z = point.z;
  147. }
  148. public bool IntersectsBox(Box box, bool allowFacesToTouch = false, float intersectionEpsilon = 1e-5f)
  149. {
  150. Vector3 center = Center;
  151. Vector3 radius = Extents;
  152. Vector3 secondBoxRadius = box.Extents;
  153. Vector3 secondBoxCenter = box.Center;
  154. float distanceBetweenCentersOnX = Mathf.Abs(center.x - secondBoxCenter.x);
  155. float distanceBetweenCentersOnY = Mathf.Abs(center.y - secondBoxCenter.y);
  156. float distanceBetweenCentersOnZ = Mathf.Abs(center.z - secondBoxCenter.z);
  157. float radiiSumOnX = radius.x + secondBoxRadius.x;
  158. float radiiSumOnY = radius.y + secondBoxRadius.y;
  159. float radiiSumOnZ = radius.z + secondBoxRadius.z;
  160. // 2 boxes intersect if they intersect on all 3 axes. If the distance between the 2 bounds' centers
  161. // is greater than the 2 radii along any of the 3 axes, it means the 2 bounds don't intersect.
  162. if (!allowFacesToTouch)
  163. {
  164. // Note: We use the equal sign because we don't want to return true if the boxes are touching
  165. // faces when 'allowFacesToTouch' is set to false.
  166. if (distanceBetweenCentersOnX >= radiiSumOnX) return false;
  167. if (distanceBetweenCentersOnY >= radiiSumOnY) return false;
  168. if (distanceBetweenCentersOnZ >= radiiSumOnZ) return false;
  169. }
  170. else
  171. {
  172. // Note: We will add 'intersectionEpsilon' to the distance between centers.
  173. if (distanceBetweenCentersOnX + intersectionEpsilon > radiiSumOnX) return false;
  174. if (distanceBetweenCentersOnY + intersectionEpsilon > radiiSumOnY) return false;
  175. if (distanceBetweenCentersOnZ + intersectionEpsilon > radiiSumOnZ) return false;
  176. }
  177. return true;
  178. }
  179. public bool TouchesFacesWith(Box box)
  180. {
  181. Vector3 firstBoxRadius = Extents;
  182. Vector3 secondBoxRadius = box.Extents;
  183. Vector3 firstBoxCenter = Center;
  184. Vector3 secondBoxCenter = box.Center;
  185. float distanceBetweenCentersX = Mathf.Abs(firstBoxCenter.x - secondBoxCenter.x);
  186. float distanceBetweenCentersY = Mathf.Abs(firstBoxCenter.y - secondBoxCenter.y);
  187. float distanceBetweenCentersZ = Mathf.Abs(firstBoxCenter.z - secondBoxCenter.z);
  188. float radiiSumX = firstBoxRadius.x + secondBoxRadius.x;
  189. float radiiSumY = firstBoxRadius.y + secondBoxRadius.y;
  190. float radiiSumZ = firstBoxRadius.z + secondBoxRadius.z;
  191. // In order to detect if 2 faces are touching, we will first have to check for each axis if the
  192. // difference between the center distance and the sum of the radii is close enough to 0. If it
  193. // is, we only have to make sure that the distance between the bounds' centers on the remaining
  194. // 2 axes does not exceed the sum of the radii in which case it would mean that the faces touch
  195. // outside of the permitted area. If the faces are not close enough on a certain axis, we will
  196. // also check if the distance between the centers along the same axis is greater than the sum
  197. // of the radii along that axis. If it is, we return false because it means the 2 AABBs are not
  198. // close enough to be touching in any way.
  199. const float epsilon = 1e-4f;
  200. if (Mathf.Abs(distanceBetweenCentersX - radiiSumX) < epsilon)
  201. {
  202. // Note: We have to make sure the faces touch in the permitted area. If the distance between the 2 centers
  203. // on the remaining 2 axis is greater or equal (with epsilon) to the corresponding radii sum, it means
  204. // the faces touch outside the permitted area.
  205. if (distanceBetweenCentersY > radiiSumY || Mathf.Abs(distanceBetweenCentersY - radiiSumY) < epsilon) return false;
  206. if (distanceBetweenCentersZ > radiiSumZ || Mathf.Abs(distanceBetweenCentersZ - radiiSumZ) < epsilon) return false;
  207. return true;
  208. }
  209. else if (distanceBetweenCentersX > radiiSumX) return false;
  210. if (Mathf.Abs(distanceBetweenCentersY - radiiSumY) < epsilon)
  211. {
  212. if (distanceBetweenCentersX > radiiSumX || Mathf.Abs(distanceBetweenCentersX - radiiSumX) < epsilon) return false;
  213. if (distanceBetweenCentersZ > radiiSumZ || Mathf.Abs(distanceBetweenCentersZ - radiiSumZ) < epsilon) return false;
  214. return true;
  215. }
  216. else if (distanceBetweenCentersY > radiiSumY) return false;
  217. if (Mathf.Abs(distanceBetweenCentersZ - radiiSumZ) < epsilon)
  218. {
  219. if (distanceBetweenCentersX > radiiSumX || Mathf.Abs(distanceBetweenCentersX - radiiSumX) < epsilon) return false;
  220. if (distanceBetweenCentersY > radiiSumY || Mathf.Abs(distanceBetweenCentersY - radiiSumY) < epsilon) return false;
  221. return true;
  222. }
  223. else if (distanceBetweenCentersZ > radiiSumZ) return false;
  224. return false;
  225. }
  226. public bool ContainsPoint(Vector3 point)
  227. {
  228. return point.x >= _min.x && point.x <= _max.x &&
  229. point.y >= _min.y && point.y <= _max.y &&
  230. point.z >= _min.z && point.z <= _max.z;
  231. }
  232. public List<Vector3> GetCenterAndCornerPoints()
  233. {
  234. Vector3[] points = new Vector3[BoxPoints.Count];
  235. points[(int)BoxPoint.Center] = GetBoxPoint(BoxPoint.Center);
  236. points[(int)BoxPoint.FrontTopLeft] = GetBoxPoint(BoxPoint.FrontTopLeft);
  237. points[(int)BoxPoint.FrontTopRight] = GetBoxPoint(BoxPoint.FrontTopRight);
  238. points[(int)BoxPoint.FrontBottomRight] = GetBoxPoint(BoxPoint.FrontBottomRight);
  239. points[(int)BoxPoint.FrontBottomLeft] = GetBoxPoint(BoxPoint.FrontBottomLeft);
  240. points[(int)BoxPoint.BackTopLeft] = GetBoxPoint(BoxPoint.BackTopLeft);
  241. points[(int)BoxPoint.BackTopRight] = GetBoxPoint(BoxPoint.BackTopRight);
  242. points[(int)BoxPoint.BackBottomRight] = GetBoxPoint(BoxPoint.BackBottomRight);
  243. points[(int)BoxPoint.BackBottomLeft] = GetBoxPoint(BoxPoint.BackBottomLeft);
  244. return new List<Vector3>(points);
  245. }
  246. public List<Vector3> GetCornerPoints()
  247. {
  248. Vector3[] points = new Vector3[BoxCornerPoints.Count];
  249. points[(int)BoxCornerPoint.FrontTopLeft] = GetBoxPoint(BoxPoint.FrontTopLeft);
  250. points[(int)BoxCornerPoint.FrontTopRight] = GetBoxPoint(BoxPoint.FrontTopRight);
  251. points[(int)BoxCornerPoint.FrontBottomRight] = GetBoxPoint(BoxPoint.FrontBottomRight);
  252. points[(int)BoxCornerPoint.FrontBottomLeft] = GetBoxPoint(BoxPoint.FrontBottomLeft);
  253. points[(int)BoxCornerPoint.BackTopLeft] = GetBoxPoint(BoxPoint.BackTopLeft);
  254. points[(int)BoxCornerPoint.BackTopRight] = GetBoxPoint(BoxPoint.BackTopRight);
  255. points[(int)BoxCornerPoint.BackBottomRight] = GetBoxPoint(BoxPoint.BackBottomRight);
  256. points[(int)BoxCornerPoint.BackBottomLeft] = GetBoxPoint(BoxPoint.BackBottomLeft);
  257. return new List<Vector3>(points);
  258. }
  259. public Vector3 GetBoxPoint(BoxPoint boxPoint)
  260. {
  261. Vector3 center = Center;
  262. Vector3 extents = Extents;
  263. switch (boxPoint)
  264. {
  265. case BoxPoint.Center:
  266. return center;
  267. case BoxPoint.FrontTopLeft:
  268. return center - BoxFaces.GetFaceRightAxis(BoxFace.Front) * extents.x +
  269. BoxFaces.GetFaceLookAxis(BoxFace.Front) * extents.y +
  270. BoxFaces.GetFaceNormal(BoxFace.Front) * extents.z;
  271. case BoxPoint.FrontTopRight:
  272. return center + BoxFaces.GetFaceRightAxis(BoxFace.Front) * extents.x +
  273. BoxFaces.GetFaceLookAxis(BoxFace.Front) * extents.y +
  274. BoxFaces.GetFaceNormal(BoxFace.Front) * extents.z;
  275. case BoxPoint.FrontBottomRight:
  276. return center + BoxFaces.GetFaceRightAxis(BoxFace.Front) * extents.x -
  277. BoxFaces.GetFaceLookAxis(BoxFace.Front) * extents.y +
  278. BoxFaces.GetFaceNormal(BoxFace.Front) * extents.z;
  279. case BoxPoint.FrontBottomLeft:
  280. return center - BoxFaces.GetFaceRightAxis(BoxFace.Front) * extents.x -
  281. BoxFaces.GetFaceLookAxis(BoxFace.Front) * extents.y +
  282. BoxFaces.GetFaceNormal(BoxFace.Front) * extents.z;
  283. case BoxPoint.BackTopLeft:
  284. return center - BoxFaces.GetFaceRightAxis(BoxFace.Back) * extents.x +
  285. BoxFaces.GetFaceLookAxis(BoxFace.Back) * extents.y +
  286. BoxFaces.GetFaceNormal(BoxFace.Back) * extents.z;
  287. case BoxPoint.BackTopRight:
  288. return center + BoxFaces.GetFaceRightAxis(BoxFace.Back) * extents.x +
  289. BoxFaces.GetFaceLookAxis(BoxFace.Back) * extents.y +
  290. BoxFaces.GetFaceNormal(BoxFace.Back) * extents.z;
  291. case BoxPoint.BackBottomRight:
  292. return center + BoxFaces.GetFaceRightAxis(BoxFace.Back) * extents.x -
  293. BoxFaces.GetFaceLookAxis(BoxFace.Back) * extents.y +
  294. BoxFaces.GetFaceNormal(BoxFace.Back) * extents.z;
  295. case BoxPoint.BackBottomLeft:
  296. return center - BoxFaces.GetFaceRightAxis(BoxFace.Back) * extents.x -
  297. BoxFaces.GetFaceLookAxis(BoxFace.Back) * extents.y +
  298. BoxFaces.GetFaceNormal(BoxFace.Back) * extents.z;
  299. default:
  300. return Vector3.zero;
  301. }
  302. }
  303. public BoxFace GetBoxFaceClosestToPoint(Vector3 point)
  304. {
  305. List<Plane> facePlanes = GetBoxFacePlanes();
  306. float minAbsDistanceFromPlane = float.MaxValue;
  307. BoxFace closestFace = BoxFace.Back;
  308. for(int faceIndex = 0; faceIndex < facePlanes.Count; ++faceIndex)
  309. {
  310. float absDistanceFromPlane = Mathf.Abs(facePlanes[faceIndex].GetDistanceToPoint(point));
  311. if(absDistanceFromPlane < minAbsDistanceFromPlane)
  312. {
  313. minAbsDistanceFromPlane = absDistanceFromPlane;
  314. closestFace = (BoxFace)faceIndex;
  315. }
  316. }
  317. return closestFace;
  318. }
  319. public List<Plane> GetBoxFacePlanes()
  320. {
  321. Plane[] facePlanes = new Plane[Enum.GetValues(typeof(BoxFace)).Length];
  322. facePlanes[(int)BoxFace.Back] = GetBoxFacePlane(BoxFace.Back);
  323. facePlanes[(int)BoxFace.Front] = GetBoxFacePlane(BoxFace.Front);
  324. facePlanes[(int)BoxFace.Left] = GetBoxFacePlane(BoxFace.Left);
  325. facePlanes[(int)BoxFace.Right] = GetBoxFacePlane(BoxFace.Right);
  326. facePlanes[(int)BoxFace.Top] = GetBoxFacePlane(BoxFace.Top);
  327. facePlanes[(int)BoxFace.Bottom] = GetBoxFacePlane(BoxFace.Bottom);
  328. return new List<Plane>(facePlanes);
  329. }
  330. public CoordinateSystem GetBoxFaceCoordinateSystem(BoxFace boxFace)
  331. {
  332. var coordSystem = new CoordinateSystem();
  333. Vector3 origin = GetBoxFaceCenter(boxFace);
  334. Vector3 boxFaceUp = BoxFaces.GetFaceNormal(boxFace);
  335. Vector3 boxFaceLook = BoxFaces.GetFaceLookAxis(boxFace);
  336. coordSystem.SetOriginPosition(origin);
  337. coordSystem.SetRotation(Quaternion.LookRotation(boxFaceLook, boxFaceUp));
  338. return coordSystem;
  339. }
  340. public List<Vector3> GetBoxFaceCenterAndCornerPoints(BoxFace boxFace)
  341. {
  342. var points = new Vector3[BoxFacePoints.Count];
  343. Vector3 boxFaceCenter = GetBoxFaceCenter(boxFace);
  344. Vector2 boxFaceXZSize = GetBoxFaceSizeAlongFaceLocalXZAxes(boxFace, Vector3.one);
  345. Vector2 halfXZSize = boxFaceXZSize * 0.5f;
  346. points[(int)BoxFacePoint.Center] = boxFaceCenter;
  347. points[(int)BoxFacePoint.TopLeft] = boxFaceCenter - BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x + BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  348. points[(int)BoxFacePoint.TopRight] = boxFaceCenter + BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x + BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  349. points[(int)BoxFacePoint.BottomRight] = boxFaceCenter + BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x - BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  350. points[(int)BoxFacePoint.BottomLeft] = boxFaceCenter - BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x - BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  351. return new List<Vector3>(points);
  352. }
  353. public List<Vector3> GetBoxFaceCornerPoints(BoxFace boxFace)
  354. {
  355. var points = new Vector3[BoxFaceCornerPoints.Count];
  356. Vector3 boxFaceCenter = GetBoxFaceCenter(boxFace);
  357. Vector2 boxFaceXZSize = GetBoxFaceSizeAlongFaceLocalXZAxes(boxFace, Vector3.one);
  358. Vector2 halfXZSize = boxFaceXZSize * 0.5f;
  359. points[(int)BoxFaceCornerPoint.TopLeft] = boxFaceCenter - BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x + BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  360. points[(int)BoxFaceCornerPoint.TopRight] = boxFaceCenter + BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x + BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  361. points[(int)BoxFaceCornerPoint.BottomRight] = boxFaceCenter + BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x - BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  362. points[(int)BoxFaceCornerPoint.BottomLeft] = boxFaceCenter - BoxFaces.GetFaceRightAxis(boxFace) * halfXZSize.x - BoxFaces.GetFaceLookAxis(boxFace) * halfXZSize.y;
  363. return new List<Vector3>(points);
  364. }
  365. public Plane GetBoxFacePlane(BoxFace boxFace)
  366. {
  367. switch(boxFace)
  368. {
  369. case BoxFace.Back:
  370. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Back), GetBoxPoint(BoxPoint.BackBottomLeft));
  371. case BoxFace.Front:
  372. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Front), GetBoxPoint(BoxPoint.FrontBottomLeft));
  373. case BoxFace.Left:
  374. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Left), GetBoxPoint(BoxPoint.FrontBottomLeft));
  375. case BoxFace.Right:
  376. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Right), GetBoxPoint(BoxPoint.FrontBottomRight));
  377. case BoxFace.Top:
  378. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Top), GetBoxPoint(BoxPoint.FrontTopLeft));
  379. case BoxFace.Bottom:
  380. return new Plane(BoxFaces.GetFaceNormal(BoxFace.Bottom), GetBoxPoint(BoxPoint.FrontBottomLeft));
  381. default:
  382. return new Plane();
  383. }
  384. }
  385. public Vector2 GetBoxFaceSizeAlongFaceLocalXZAxes(BoxFace boxFace, Vector3 boxXYZScale)
  386. {
  387. Vector3 size = Size;
  388. switch(boxFace)
  389. {
  390. case BoxFace.Front:
  391. case BoxFace.Back:
  392. return new Vector2(size.x * boxXYZScale.x, size.y * boxXYZScale.y);
  393. case BoxFace.Left:
  394. case BoxFace.Right:
  395. return new Vector2(size.z * boxXYZScale.z, size.y * boxXYZScale.y);
  396. case BoxFace.Top:
  397. case BoxFace.Bottom:
  398. return new Vector2(size.x * boxXYZScale.x, size.z * boxXYZScale.z);
  399. default:
  400. return Vector2.zero;
  401. }
  402. }
  403. public Vector3 GetBoxFaceCenter(BoxFace boxFace)
  404. {
  405. Vector3 center = Center;
  406. Vector3 extents = Extents;
  407. switch(boxFace)
  408. {
  409. case BoxFace.Back:
  410. return center + BoxFaces.GetFaceNormal(BoxFace.Back) * extents.z;
  411. case BoxFace.Front:
  412. return center + BoxFaces.GetFaceNormal(BoxFace.Front) * extents.z;
  413. case BoxFace.Left:
  414. return center + BoxFaces.GetFaceNormal(BoxFace.Left) * extents.x;
  415. case BoxFace.Right:
  416. return center + BoxFaces.GetFaceNormal(BoxFace.Right) * extents.x;
  417. case BoxFace.Top:
  418. return center + BoxFaces.GetFaceNormal(BoxFace.Top) * extents.y;
  419. case BoxFace.Bottom:
  420. return center + BoxFaces.GetFaceNormal(BoxFace.Bottom) * extents.y;
  421. default:
  422. return Vector3.zero;
  423. }
  424. }
  425. public List<Vector2> GetScreenCornerPoints(Camera camera)
  426. {
  427. Vector3 boxCenter = Center;
  428. Vector3 boxExtents = Extents;
  429. return new List<Vector2>
  430. {
  431. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x - boxExtents.x, boxCenter.y - boxExtents.y, boxCenter.z - boxExtents.z)),
  432. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x + boxExtents.x, boxCenter.y - boxExtents.y, boxCenter.z - boxExtents.z)),
  433. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x + boxExtents.x, boxCenter.y + boxExtents.y, boxCenter.z - boxExtents.z)),
  434. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x - boxExtents.x, boxCenter.y + boxExtents.y, boxCenter.z - boxExtents.z)),
  435. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x - boxExtents.x, boxCenter.y - boxExtents.y, boxCenter.z + boxExtents.z)),
  436. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x + boxExtents.x, boxCenter.y - boxExtents.y, boxCenter.z + boxExtents.z)),
  437. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x + boxExtents.x, boxCenter.y + boxExtents.y, boxCenter.z + boxExtents.z)),
  438. Vector3Extensions.WorldToScreenPoint(new Vector3(boxCenter.x - boxExtents.x, boxCenter.y + boxExtents.y, boxCenter.z + boxExtents.z)),
  439. };
  440. }
  441. public Rect GetScreenRectangle(Camera camera)
  442. {
  443. List<Vector2> screenPoints = GetScreenCornerPoints(camera);
  444. Vector2 minScreenPoint = screenPoints[0];
  445. Vector2 maxScreenPoint = screenPoints[0];
  446. foreach (Vector2 point in screenPoints)
  447. {
  448. minScreenPoint = Vector2.Min(minScreenPoint, point);
  449. maxScreenPoint = Vector2.Max(maxScreenPoint, point);
  450. }
  451. return new Rect(minScreenPoint.x, minScreenPoint.y, maxScreenPoint.x - minScreenPoint.x, maxScreenPoint.y - minScreenPoint.y);
  452. }
  453. public bool Raycast(Ray ray, out float t)
  454. {
  455. Bounds bounds = ToBounds();
  456. return bounds.IntersectRay(ray, out t);
  457. }
  458. public Box Transform(TransformMatrix transformMatrix)
  459. {
  460. Vector3 rightAxis = transformMatrix.GetNormalizedRightAxisNoScaleSign();
  461. Vector3 upAxis = transformMatrix.GetNormalizedUpAxisNoScaleSign();
  462. Vector3 lookAxis = transformMatrix.GetNormalizedLookAxisNoScaleSign();
  463. Vector3 scale = transformMatrix.Scale;
  464. Vector3 newCenter = transformMatrix.MultiplyPoint(Center);
  465. Vector3 boxExtents = Extents;
  466. Vector3 newExtentsRight = rightAxis * boxExtents.x * scale.x;
  467. Vector3 newExtentsUp = upAxis * boxExtents.y * scale.y;
  468. Vector3 newExtentsLook = lookAxis * boxExtents.z * scale.z;
  469. float newExtentsX = Mathf.Abs(newExtentsRight.x) + Mathf.Abs(newExtentsUp.x) + Mathf.Abs(newExtentsLook.x);
  470. float newExtentsY = Mathf.Abs(newExtentsRight.y) + Mathf.Abs(newExtentsUp.y) + Mathf.Abs(newExtentsLook.y);
  471. float newExtentsZ = Mathf.Abs(newExtentsRight.z) + Mathf.Abs(newExtentsUp.z) + Mathf.Abs(newExtentsLook.z);
  472. Vector3 newSize = new Vector3(newExtentsX, newExtentsY, newExtentsZ) * 2.0f;
  473. return new Box(newCenter, newSize);
  474. }
  475. public void MakeInvalid()
  476. {
  477. _min = Vector3.one;
  478. _max = -Vector3.one;
  479. }
  480. public bool IsValid()
  481. {
  482. return _min.x <= _max.x && _min.y <= _max.y && _min.z <= _max.z;
  483. }
  484. public bool IsInvalid()
  485. {
  486. return !IsValid();
  487. }
  488. #endregion
  489. }
  490. }
  491. #endif