ProjectedBoxFacePivotPoints.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #if UNITY_EDITOR
  2. using UnityEngine;
  3. using System;
  4. using System.Linq;
  5. using System.Collections.Generic;
  6. namespace O3DWB
  7. {
  8. [Serializable]
  9. public class ProjectedBoxFacePivotPoints
  10. {
  11. #region Private Variables
  12. [SerializeField]
  13. private PivotPointCollection _pivotPointCollection = new PivotPointCollection();
  14. [SerializeField]
  15. private List<Vector3> _unprojectedPivotPoints = new List<Vector3> { Vector3.zero };
  16. [SerializeField]
  17. private Plane _pointsPlane = new Plane();
  18. [SerializeField]
  19. private float _area = 0.0f;
  20. #endregion
  21. #region Public Static Properties
  22. public static int NumberOfBoundarySegments { get { return 4; } }
  23. public static int IndexOfPointInCenter { get { return 0; } }
  24. #endregion
  25. #region Public Properties
  26. public int NumberOfPoints { get { return _pivotPointCollection.NumberOfPoints; } }
  27. public Vector3 ActivePoint { get { return _pivotPointCollection.ActivePoint; } }
  28. public Vector3 CenterPoint { get { return _pivotPointCollection.GetPointByIndex(IndexOfPointInCenter); } }
  29. public int IndexOfActivePoint { get { return _pivotPointCollection.IndexOfActivePoint; } }
  30. public List<Vector3> AllPoints { get { return _pivotPointCollection.AllPoints; } }
  31. public Plane PointsPlane { get { return _pointsPlane; } }
  32. public float Area { get { return _area; } }
  33. #endregion
  34. #region Public Methods
  35. public ProjectedBoxFacePivotPoints TakeSnapshot()
  36. {
  37. var projectedBoxFacePivotPoints = new ProjectedBoxFacePivotPoints();
  38. projectedBoxFacePivotPoints._pivotPointCollection = _pivotPointCollection.TakeSnapshot();
  39. projectedBoxFacePivotPoints._unprojectedPivotPoints = GetUnprojectedPivotPoints();
  40. projectedBoxFacePivotPoints._pointsPlane = PointsPlane;
  41. return projectedBoxFacePivotPoints;
  42. }
  43. public void FromOrientedBoxAndSnapSurface(OrientedBox orientedBox, SnapSurface objectSnapSurface)
  44. {
  45. if (!objectSnapSurface.IsValid) return;
  46. Vector3 surfacePlaneNormal = objectSnapSurface.Plane.normal;
  47. if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive()) surfacePlaneNormal *= -1.0f;
  48. BoxFace boxFaceMostAlignedWithSurface = orientedBox.GetBoxFaceWhichFacesNormal(surfacePlaneNormal);
  49. List<Vector3> cornerPointsOfFaceMostAlignedWithSurface = orientedBox.GetBoxFaceCornerPoints(boxFaceMostAlignedWithSurface);
  50. CalculatePointsPlane(orientedBox, objectSnapSurface);
  51. StoreObjectPivotPoints(_pointsPlane.ProjectAllPoints(cornerPointsOfFaceMostAlignedWithSurface));
  52. StoreUnprojectedPivotPoints(cornerPointsOfFaceMostAlignedWithSurface);
  53. CalculateArea();
  54. }
  55. public void FromOrientedBoxAndDecorStrokeSurface(OrientedBox orientedBox, DecorPaintStrokeSurface decorPaintStrokeSurface)
  56. {
  57. if (!decorPaintStrokeSurface.IsValid) return;
  58. Vector3 surfacePlaneNormal = decorPaintStrokeSurface.Plane.normal;
  59. if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive()) surfacePlaneNormal *= -1.0f;
  60. BoxFace boxFaceMostAlignedWithSurface = orientedBox.GetBoxFaceWhichFacesNormal(surfacePlaneNormal);
  61. List<Vector3> cornerPointsOfFaceMostAlignedWithSurface = orientedBox.GetBoxFaceCornerPoints(boxFaceMostAlignedWithSurface);
  62. CalculatePointsPlane(orientedBox, decorPaintStrokeSurface);
  63. StoreObjectPivotPoints(_pointsPlane.ProjectAllPoints(cornerPointsOfFaceMostAlignedWithSurface));
  64. StoreUnprojectedPivotPoints(cornerPointsOfFaceMostAlignedWithSurface);
  65. CalculateArea();
  66. }
  67. public List<Vector3> GetAllPointsExcludingCenter()
  68. {
  69. List<Vector3> pivotPoints = AllPoints;
  70. if (pivotPoints.Count == 0) return pivotPoints;
  71. pivotPoints.RemoveAt(IndexOfPointInCenter);
  72. return pivotPoints;
  73. }
  74. public int GetIndexOfPointClosestToPoint(Vector3 point)
  75. {
  76. return Vector3Extensions.GetIndexOfPointClosestToPoint(AllPoints, point);
  77. }
  78. public List<Vector3> GetUnprojectedPivotPoints()
  79. {
  80. return new List<Vector3>(_unprojectedPivotPoints);
  81. }
  82. public void ActivatePoint(int pointIndex)
  83. {
  84. _pivotPointCollection.ActivatePoint(pointIndex);
  85. }
  86. public void ActivateNextPivotPoint()
  87. {
  88. _pivotPointCollection.ActivateNextPoint();
  89. }
  90. public Vector3 GetPointByIndex(int pointIndex)
  91. {
  92. return _pivotPointCollection.GetPointByIndex(pointIndex);
  93. }
  94. public List<Segment3D> GetAllBoundarySegments()
  95. {
  96. List<Vector3> allPointsNoCenter = GetAllPointsExcludingCenter();
  97. return Vector3Extensions.GetSegmentsBetweenPoints(allPointsNoCenter, true);
  98. }
  99. public List<Plane> GetAllBoundarySegmentPlanes()
  100. {
  101. List<Segment3D> allBoundarySegments = GetAllBoundarySegments();
  102. var allBoundarySegmentPlanes = new List<Plane>(allBoundarySegments.Count);
  103. for(int segmentIndex = 0; segmentIndex < allBoundarySegments.Count; ++segmentIndex)
  104. {
  105. allBoundarySegmentPlanes.Add(GetBoundarySegmentPlane(segmentIndex));
  106. }
  107. return allBoundarySegmentPlanes;
  108. }
  109. public Segment3D GetBoundarySegment(int segmentIndex)
  110. {
  111. segmentIndex %= NumberOfBoundarySegments;
  112. List<Vector3> allPointsNoCenter = GetAllPointsExcludingCenter();
  113. return new Segment3D(allPointsNoCenter[segmentIndex], allPointsNoCenter[(segmentIndex + 1) % NumberOfBoundarySegments]);
  114. }
  115. public Plane GetBoundarySegmentPlane(int segmentIndex)
  116. {
  117. Segment3D boundarySegment = GetBoundarySegment(segmentIndex);
  118. Vector3 centerPivotPoint = GetPointByIndex(IndexOfPointInCenter);
  119. Vector3 centerPivotPointProjectedOnSegment = centerPivotPoint.CalculateProjectionPointOnSegment(boundarySegment.StartPoint, boundarySegment.EndPoint);
  120. Vector3 planeNormal = centerPivotPointProjectedOnSegment - centerPivotPoint;
  121. planeNormal.Normalize();
  122. return new Plane(planeNormal, boundarySegment.StartPoint);
  123. }
  124. public void MovePoints(Vector3 moveVector)
  125. {
  126. _unprojectedPivotPoints = Vector3Extensions.ApplyOffsetToPoints(_unprojectedPivotPoints, moveVector);
  127. _pivotPointCollection.MovePoints(moveVector);
  128. _pointsPlane = new Plane(_pointsPlane.normal, _pivotPointCollection.GetPointByIndex(0));
  129. }
  130. #endregion
  131. #region Private Methods
  132. private void StoreUnprojectedPivotPoints(List<Vector3> cornerPointsOfFaceMostAlignedWithSurface)
  133. {
  134. _unprojectedPivotPoints = new List<Vector3>(cornerPointsOfFaceMostAlignedWithSurface);
  135. _unprojectedPivotPoints.Insert(IndexOfPointInCenter, Vector3Extensions.GetAveragePoint(cornerPointsOfFaceMostAlignedWithSurface));
  136. }
  137. private void CalculatePointsPlane(OrientedBox orientedBox, SnapSurface objectSnapSurface)
  138. {
  139. // Note: It is necessary to ensure that all projected points sit right below the oriented box in order
  140. // to avoid situations in which the object hierarchy floats in the air or becomes embedded
  141. // inside other objects. In order to do this, we adjust the surface plane such that the box
  142. // sits right in front of it (or behind) depending on the settings.
  143. _pointsPlane = objectSnapSurface.Plane;
  144. if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive()) _pointsPlane = _pointsPlane.AdjustSoBoxSitsBehind(orientedBox);
  145. else _pointsPlane = _pointsPlane.AdjustSoBoxSitsInFront(orientedBox);
  146. }
  147. private void CalculatePointsPlane(OrientedBox orientedBox, DecorPaintStrokeSurface decorPaintSurface)
  148. {
  149. _pointsPlane = decorPaintSurface.Plane;
  150. if (AllShortcutCombos.Instance.PlaceGuideBehindSurfacePlane.IsActive()) _pointsPlane = _pointsPlane.AdjustSoBoxSitsBehind(orientedBox);
  151. else _pointsPlane = _pointsPlane.AdjustSoBoxSitsInFront(orientedBox);
  152. }
  153. private void StoreObjectPivotPoints(List<Vector3> projectedFacePoints)
  154. {
  155. List<Vector3> projectedPointsAndCenter = new List<Vector3>(projectedFacePoints);
  156. projectedPointsAndCenter.Insert(IndexOfPointInCenter, Vector3Extensions.GetAveragePoint(projectedFacePoints));
  157. _pivotPointCollection.SetPivotPoints(projectedPointsAndCenter, _pivotPointCollection.IndexOfActivePoint);
  158. }
  159. private void CalculateArea()
  160. {
  161. List<Segment3D> boundarySegments = GetAllBoundarySegments();
  162. for(int segmentIndex = 0; segmentIndex < boundarySegments.Count; ++segmentIndex)
  163. {
  164. Segment3D currentSegment = boundarySegments[segmentIndex];
  165. for(int perpSegmentIndex = segmentIndex + 1; perpSegmentIndex < boundarySegments.Count; ++perpSegmentIndex)
  166. {
  167. Segment3D perpSegment = boundarySegments[perpSegmentIndex];
  168. if(perpSegment.IsPerpendicualrTo(currentSegment))
  169. {
  170. Vector3 cross = Vector3.Cross(perpSegment.Direction, currentSegment.Direction);
  171. _area = cross.magnitude;
  172. return;
  173. }
  174. }
  175. }
  176. }
  177. #endregion
  178. }
  179. }
  180. #endif