WhiteBoxManipulatorBounds.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "Util/WhiteBoxMathUtil.h"
  9. #include "WhiteBoxManipulatorBounds.h"
  10. #include <AzCore/Math/IntersectSegment.h>
  11. namespace WhiteBox
  12. {
  13. AZ_CLASS_ALLOCATOR_IMPL(ManipulatorBoundPolygon, AZ::SystemAllocator)
  14. AZ_CLASS_ALLOCATOR_IMPL(ManipulatorBoundEdge, AZ::SystemAllocator)
  15. AZ_CLASS_ALLOCATOR_IMPL(BoundShapePolygon, AZ::SystemAllocator)
  16. AZ_CLASS_ALLOCATOR_IMPL(BoundShapeEdge, AZ::SystemAllocator)
  17. bool IntersectRayVertex(
  18. const VertexBound& vertexBound, const float vertexScreenRadius, const AZ::Vector3& rayOrigin,
  19. const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
  20. {
  21. float distance;
  22. if (AZ::Intersect::IntersectRaySphere(
  23. rayOrigin, rayDirection, vertexBound.m_center, vertexScreenRadius, distance))
  24. {
  25. rayIntersectionDistance = distance;
  26. return true;
  27. }
  28. return false;
  29. }
  30. bool IntersectRayPolygon(
  31. const PolygonBound& polygonBound, const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection,
  32. float& rayIntersectionDistance, int64_t& intersectedTriangleIndex)
  33. {
  34. AZ_Assert(polygonBound.m_triangles.size() % 3 == 0, "Invalid number of points to represent triangles");
  35. const float rayLength = 1000.0f;
  36. AZ::Intersect::SegmentTriangleHitTester hitTester(rayOrigin, rayOrigin + rayDirection * rayLength);
  37. for (size_t triangleIndex = 0; triangleIndex < polygonBound.m_triangles.size(); triangleIndex += 3)
  38. {
  39. AZ::Vector3 p0 = polygonBound.m_triangles[triangleIndex];
  40. AZ::Vector3 p1 = polygonBound.m_triangles[triangleIndex + 1];
  41. AZ::Vector3 p2 = polygonBound.m_triangles[triangleIndex + 2];
  42. float time;
  43. AZ::Vector3 normal;
  44. const bool intersected = hitTester.IntersectSegmentTriangleCCW(p0, p1, p2, normal, time);
  45. if (intersected)
  46. {
  47. rayIntersectionDistance = time * rayLength;
  48. intersectedTriangleIndex = triangleIndex / 3;
  49. return true;
  50. }
  51. }
  52. return false;
  53. }
  54. bool ManipulatorBoundPolygon::IntersectRay(
  55. const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance) const
  56. {
  57. int64_t intersectedTriangleIndex = 0;
  58. return IntersectRayPolygon(
  59. m_polygonBound, rayOrigin, rayDirection, rayIntersectionDistance, intersectedTriangleIndex);
  60. }
  61. void ManipulatorBoundPolygon::SetShapeData(const AzToolsFramework::Picking::BoundRequestShapeBase& shapeData)
  62. {
  63. if (const auto* polygonData = azrtti_cast<const BoundShapePolygon*>(&shapeData))
  64. {
  65. m_polygonBound.m_triangles = polygonData->m_triangles;
  66. }
  67. }
  68. AZStd::shared_ptr<AzToolsFramework::Picking::BoundShapeInterface> BoundShapePolygon::MakeShapeInterface(
  69. AzToolsFramework::Picking::RegisteredBoundId id) const
  70. {
  71. AZStd::shared_ptr<AzToolsFramework::Picking::BoundShapeInterface> quad =
  72. AZStd::make_shared<ManipulatorBoundPolygon>(id);
  73. quad->SetShapeData(*this);
  74. return quad;
  75. }
  76. bool IntersectRayEdge(
  77. const EdgeBound& edgeBound, const float edgeScreenWidth, const AZ::Vector3& rayOrigin,
  78. const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
  79. {
  80. const float rayLength = 1000.0f; // this is arbitrary to turn it into a ray
  81. const AZ::Vector3 sa = rayOrigin;
  82. const AZ::Vector3 sb = rayOrigin + rayDirection * rayLength;
  83. const AZ::Vector3 p = edgeBound.m_start;
  84. const AZ::Vector3 q = edgeBound.m_end;
  85. const float r = edgeScreenWidth;
  86. float t = 0.0f;
  87. if (IntersectSegmentCylinder(sa, sb, p, q, r, t) != 0)
  88. {
  89. // intersected, t is normalized distance along the ray
  90. rayIntersectionDistance = t * rayLength;
  91. return true;
  92. }
  93. return false;
  94. }
  95. bool ManipulatorBoundEdge::IntersectRay(
  96. const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance) const
  97. {
  98. return IntersectRayEdge(m_edgeBound, m_edgeBound.m_radius, rayOrigin, rayDirection, rayIntersectionDistance);
  99. }
  100. void ManipulatorBoundEdge::SetShapeData(const AzToolsFramework::Picking::BoundRequestShapeBase& shapeData)
  101. {
  102. if (const auto* edgeData = azrtti_cast<const BoundShapeEdge*>(&shapeData))
  103. {
  104. m_edgeBound = {edgeData->m_start, edgeData->m_end, edgeData->m_radius};
  105. }
  106. }
  107. AZStd::shared_ptr<AzToolsFramework::Picking::BoundShapeInterface> BoundShapeEdge::MakeShapeInterface(
  108. AzToolsFramework::Picking::RegisteredBoundId id) const
  109. {
  110. AZStd::shared_ptr<ManipulatorBoundEdge> edge = AZStd::make_shared<ManipulatorBoundEdge>(id);
  111. edge->SetShapeData(*this);
  112. return edge;
  113. }
  114. } // namespace WhiteBox