diff --git a/.clang-format b/.clang-format index 565f28130e..04e0284f97 100644 --- a/.clang-format +++ b/.clang-format @@ -46,7 +46,7 @@ SortIncludes: true SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: false SpaceBeforeAssignmentOperators: true -SpaceBeforeCpp11BracedList: true +SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements diff --git a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h index ba1d2d1e06..749f457286 100644 --- a/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h +++ b/Code/Framework/AzFramework/AzFramework/Render/GeometryIntersectionBus.h @@ -12,6 +12,7 @@ #pragma once #include +#include #include namespace AzFramework @@ -35,12 +36,12 @@ namespace AzFramework AzFramework::EntityContextId m_contextId; }; - //! Interface for intersection requests, implement this interface for making your component - //! render geometry intersectable. + //! Interface for intersection requests. + //! Implement this interface to make your component 'intersectable'. class IntersectionRequests : public AZ::EBusTraits { - //! Policy for notifying the Intersector bus of entities connected/disconnected to this ebus + //! Policy for notifying the Intersector bus of entities connected/disconnected to this EBus //! so it updates the internal data of the entities template struct IntersectionRequestsConnectionPolicy diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index e4833ccb3c..d5f02c957c 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -144,7 +144,7 @@ namespace AzFramework z = AZStd::atan2(-orientation.GetElement(1, 2), orientation.GetElement(1, 1)); } - return {x, y, z}; + return { x, y, z }; } void UpdateCameraFromTransform(Camera& camera, const AZ::Transform& transform) @@ -179,7 +179,7 @@ namespace AzFramework { const auto nextCamera = m_cameras.StepCamera(targetCamera, m_motionDelta, m_scrollDelta, deltaTime); - m_motionDelta = ScreenVector{0, 0}; + m_motionDelta = ScreenVector{ 0, 0 }; m_scrollDelta = 0.0f; return nextCamera; @@ -213,7 +213,10 @@ namespace AzFramework auto& cameraInput = m_idleCameraInputs[i]; const bool canBegin = cameraInput->Beginning() && AZStd::all_of(m_activeCameraInputs.cbegin(), m_activeCameraInputs.cend(), - [](const auto& input) { return !input->Exclusive(); }) && + [](const auto& input) + { + return !input->Exclusive(); + }) && (!cameraInput->Exclusive() || (cameraInput->Exclusive() && m_activeCameraInputs.empty())); if (canBegin) @@ -231,7 +234,8 @@ namespace AzFramework const Camera nextCamera = AZStd::accumulate( AZStd::begin(m_activeCameraInputs), AZStd::end(m_activeCameraInputs), targetCamera, - [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) { + [cursorDelta, scrollDelta, deltaTime](Camera acc, auto& camera) + { acc = camera->StepCamera(acc, cursorDelta, scrollDelta, deltaTime); return acc; }); @@ -284,7 +288,8 @@ namespace AzFramework bool RotateCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, [[maybe_unused]] float scrollDelta) { - const ClickDetector::ClickEvent clickEvent = [&event, this] { + const ClickDetector::ClickEvent clickEvent = [&event, this] + { if (const auto& input = AZStd::get_if(&event)) { if (input->m_channelId == m_rotateChannelId) @@ -330,7 +335,10 @@ namespace AzFramework nextCamera.m_pitch -= float(cursorDelta.m_y) * ed_cameraSystemRotateSpeed; nextCamera.m_yaw -= float(cursorDelta.m_x) * ed_cameraSystemRotateSpeed; - const auto clampRotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clampRotation = [](const float angle) + { + return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); + }; nextCamera.m_yaw = clampRotation(nextCamera.m_yaw); // clamp pitch to be +-90 degrees @@ -377,9 +385,10 @@ namespace AzFramework const auto deltaPanX = float(cursorDelta.m_x) * panAxes.m_horizontalAxis * ed_cameraSystemPanSpeed; const auto deltaPanY = float(cursorDelta.m_y) * panAxes.m_verticalAxis * ed_cameraSystemPanSpeed; - const auto inv = [](const bool invert) { - constexpr float Dir[] = {1.0f, -1.0f}; - return Dir[static_cast(invert)]; + const auto inv = [](const bool invert) + { + constexpr float Dir[] = { 1.0f, -1.0f }; + return Dir[aznumeric_cast(invert)]; }; nextCamera.m_lookAt += deltaPanX * inv(ed_cameraSystemPanInvertX); @@ -475,7 +484,8 @@ namespace AzFramework const auto axisY = translationBasis.GetBasisY(); const auto axisZ = translationBasis.GetBasisZ(); - const float speed = [boost = m_boost]() { + const float speed = [boost = m_boost]() + { return ed_cameraSystemTranslateSpeed * (boost ? ed_cameraSystemBoostMultiplier : 1.0f); }(); @@ -555,10 +565,12 @@ namespace AzFramework if (Beginning()) { - const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] { + const auto hasLookAt = [&nextCamera, &targetCamera, &lookAtFn = m_lookAtFn] + { if (lookAtFn) { - if (const auto lookAt = lookAtFn()) + // pass through the camera's position and look vector for use in the lookAt function + if (const auto lookAt = lookAtFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY())) { auto transform = AZ::Transform::CreateLookAt(targetCamera.m_lookAt, *lookAt); nextCamera.m_lookDist = -lookAt->GetDistance(targetCamera.m_lookAt); @@ -692,14 +704,20 @@ namespace AzFramework Camera SmoothCamera(const Camera& currentCamera, const Camera& targetCamera, const float deltaTime) { - const auto clamp_rotation = [](const float angle) { return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); }; + const auto clamp_rotation = [](const float angle) + { + return AZStd::fmod(angle + AZ::Constants::TwoPi, AZ::Constants::TwoPi); + }; // keep yaw in 0 - 360 range float targetYaw = clamp_rotation(targetCamera.m_yaw); const float currentYaw = clamp_rotation(currentCamera.m_yaw); // return the sign of the float input (-1, 0, 1) - const auto sign = [](const float value) { return aznumeric_cast((0.0f < value) - (value < 0.0f)); }; + const auto sign = [](const float value) + { + return aznumeric_cast((0.0f < value) - (value < 0.0f)); + }; // ensure smooth transition when moving across 0 - 360 boundary const float yawDelta = targetYaw - currentYaw; @@ -727,26 +745,28 @@ namespace AzFramework const auto& inputChannelId = inputChannel.GetInputChannelId(); const auto& inputDeviceId = inputChannel.GetInputDevice().GetInputDeviceId(); - const bool wasMouseButton = - AZStd::any_of(InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), [inputChannelId](const auto& button) { + const bool wasMouseButton = AZStd::any_of( + InputDeviceMouse::Button::All.begin(), InputDeviceMouse::Button::All.end(), + [inputChannelId](const auto& button) + { return button == inputChannelId; }); if (inputChannelId == InputDeviceMouse::Movement::X) { - return HorizontalMotionEvent{(int)inputChannel.GetValue()}; + return HorizontalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) }; } else if (inputChannelId == InputDeviceMouse::Movement::Y) { - return VerticalMotionEvent{(int)inputChannel.GetValue()}; + return VerticalMotionEvent{ aznumeric_cast(inputChannel.GetValue()) }; } else if (inputChannelId == InputDeviceMouse::Movement::Z) { - return ScrollEvent{inputChannel.GetValue()}; + return ScrollEvent{ inputChannel.GetValue() }; } else if (wasMouseButton || InputDeviceKeyboard::IsKeyboardDevice(inputDeviceId)) { - return DiscreteInputEvent{inputChannelId, inputChannel.GetState()}; + return DiscreteInputEvent{ inputChannelId, inputChannel.GetState() }; } return AZStd::monostate{}; diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index ec70fc00de..a02f796899 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -34,9 +34,9 @@ namespace AzFramework AZ::Vector3 m_lookAt = AZ::Vector3::CreateZero(); //!< Position of camera when m_lookDist is zero, //!< or position of m_lookAt when m_lookDist is greater //!< than zero. - float m_yaw{0.0}; - float m_pitch{0.0}; - float m_lookDist{0.0}; //!< Zero gives first person free look, otherwise orbit about m_lookAt + float m_yaw{ 0.0 }; + float m_pitch{ 0.0 }; + float m_lookDist{ 0.0 }; //!< Zero gives first person free look, otherwise orbit about m_lookAt //! View camera transform (v in MVP). AZ::Transform View() const; @@ -195,7 +195,11 @@ namespace AzFramework inline bool Cameras::Exclusive() const { return AZStd::any_of( - m_activeCameraInputs.begin(), m_activeCameraInputs.end(), [](const auto& cameraInput) { return cameraInput->Exclusive(); }); + m_activeCameraInputs.begin(), m_activeCameraInputs.end(), + [](const auto& cameraInput) + { + return cameraInput->Exclusive(); + }); } //! Responsible for updating a series of cameras given various inputs. @@ -209,7 +213,7 @@ namespace AzFramework private: ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional. - float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional. + float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional. }; class RotateCameraInput : public CameraInput @@ -237,7 +241,7 @@ namespace AzFramework inline PanAxes LookPan(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); - return {orientation.GetBasisX(), orientation.GetBasisZ()}; + return { orientation.GetBasisX(), orientation.GetBasisZ() }; } inline PanAxes OrbitPan(const Camera& camera) @@ -245,12 +249,13 @@ namespace AzFramework const AZ::Matrix3x3 orientation = camera.Rotation(); const auto basisX = orientation.GetBasisX(); - const auto basisY = [&orientation] { + const auto basisY = [&orientation] + { const auto forward = orientation.GetBasisY(); return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized(); }(); - return {basisX, basisY}; + return { basisX, basisY }; } class PanCameraInput : public CameraInput @@ -285,7 +290,8 @@ namespace AzFramework const AZ::Matrix3x3 orientation = camera.Rotation(); const auto basisX = orientation.GetBasisX(); - const auto basisY = [&orientation] { + const auto basisY = [&orientation] + { const auto forward = orientation.GetBasisY(); return AZ::Vector3(forward.GetX(), forward.GetY(), 0.0f).GetNormalized(); }(); @@ -398,7 +404,7 @@ namespace AzFramework class OrbitCameraInput : public CameraInput { public: - using LookAtFn = AZStd::function()>; + using LookAtFn = AZStd::function(const AZ::Vector3& position, const AZ::Vector3& direction)>; // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index ecd11da817..989d6e407d 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -1221,50 +1221,73 @@ void EditorViewportWidget::SetViewportId(int id) AzFramework::ReloadCameraKeyBindings(); auto controller = AZStd::make_shared(); - controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras) - { - auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton); - auto firstPersonPanCamera = - AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan); - auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation); - auto firstPersonWheelCamera = AZStd::make_shared(); + controller->SetCameraListBuilderCallback( + [](AzFramework::Cameras& cameras) + { + auto firstPersonRotateCamera = AZStd::make_shared(AzFramework::CameraFreeLookButton); + auto firstPersonPanCamera = + AZStd::make_shared(AzFramework::CameraFreePanButton, AzFramework::LookPan); + auto firstPersonTranslateCamera = AZStd::make_shared(AzFramework::LookTranslation); + auto firstPersonWheelCamera = AZStd::make_shared(); - auto orbitCamera = AZStd::make_shared(); - orbitCamera->SetLookAtFn([]() -> AZStd::optional { - AZStd::optional manipulatorTransform; - AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( - manipulatorTransform, AzToolsFramework::GetEntityContextId(), - &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); + auto orbitCamera = AZStd::make_shared(); + orbitCamera->SetLookAtFn( + [](const AZ::Vector3& position, const AZ::Vector3& direction) -> AZStd::optional + { + AZStd::optional manipulatorTransform; + AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult( + manipulatorTransform, AzToolsFramework::GetEntityContextId(), + &AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform); - if (manipulatorTransform) - { - return manipulatorTransform->GetTranslation(); - } + // initially attempt to use manipulator transform if one exists (there is a selection) + if (manipulatorTransform) + { + return manipulatorTransform->GetTranslation(); + } - return {}; + const float RayDistance = 1000.0f; + AzFramework::RenderGeometry::RayRequest ray; + ray.m_startWorldPosition = position; + ray.m_endWorldPosition = position + direction * RayDistance; + ray.m_onlyVisible = true; + + AzFramework::RenderGeometry::RayResult renderGeometryIntersectionResult; + AzFramework::RenderGeometry::IntersectorBus::EventResult( + renderGeometryIntersectionResult, AzToolsFramework::GetEntityContextId(), + &AzFramework::RenderGeometry::IntersectorInterface::RayIntersect, ray); + + // attempt a ray intersection with any visible mesh and return the intersection position if successful + if (renderGeometryIntersectionResult) + { + return renderGeometryIntersectionResult.m_worldPosition; + } + + // if there is no selection or no intersection, fallback to default camera orbit behavior (ground plane + // intersection) + return {}; + }); + + auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton); + auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation); + auto orbitDollyWheelCamera = AZStd::make_shared(); + auto orbitDollyMoveCamera = + AZStd::make_shared(AzFramework::CameraOrbitDollyButton); + auto orbitPanCamera = + AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan); + + orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); + orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); + + cameras.AddCamera(firstPersonRotateCamera); + cameras.AddCamera(firstPersonPanCamera); + cameras.AddCamera(firstPersonTranslateCamera); + cameras.AddCamera(firstPersonWheelCamera); + cameras.AddCamera(orbitCamera); }); - auto orbitRotateCamera = AZStd::make_shared(AzFramework::CameraOrbitLookButton); - auto orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation); - auto orbitDollyWheelCamera = AZStd::make_shared(); - auto orbitDollyMoveCamera = - AZStd::make_shared(AzFramework::CameraOrbitDollyButton); - auto orbitPanCamera = - AZStd::make_shared(AzFramework::CameraOrbitPanButton, AzFramework::OrbitPan); - - orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyWheelCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitDollyMoveCamera); - orbitCamera->m_orbitCameras.AddCamera(orbitPanCamera); - - cameras.AddCamera(firstPersonRotateCamera); - cameras.AddCamera(firstPersonPanCamera); - cameras.AddCamera(firstPersonTranslateCamera); - cameras.AddCamera(firstPersonWheelCamera); - cameras.AddCamera(orbitCamera); - }); - m_renderViewport->GetControllerList()->Add(controller); } else diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h index 1acaa6fdf8..41ea80f8d1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.h @@ -35,14 +35,13 @@ namespace AZ , private MeshComponentNotificationBus::Handler { public: - using BaseClass = EditorRenderComponentAdapter; AZ_EDITOR_COMPONENT(AZ::Render::EditorMeshComponent, EditorMeshComponentTypeId, BaseClass); static void Reflect(AZ::ReflectContext* context); EditorMeshComponent() = default; - EditorMeshComponent(const MeshComponentConfig& config); + explicit EditorMeshComponent(const MeshComponentConfig& config); // AZ::Component overrides ... void Activate() override; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h index a57780c384..fe7f45d7d1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponent.h @@ -25,12 +25,11 @@ namespace AZ : public AzFramework::Components::ComponentAdapter { public: - using BaseClass = AzFramework::Components::ComponentAdapter; AZ_COMPONENT(AZ::Render::MeshComponent, MeshComponentTypeId, BaseClass); MeshComponent() = default; - MeshComponent(const MeshComponentConfig& config); + explicit MeshComponent(const MeshComponentConfig& config); static void Reflect(AZ::ReflectContext* context); }; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp index a4a91cf708..c089dd01f9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.cpp @@ -177,28 +177,33 @@ namespace AZ FixUpModelAsset(m_configuration.m_modelAsset); } - void MeshComponentController::Activate(AZ::EntityId entityId) + void MeshComponentController::Activate(const AZ::EntityComponentIdPair& entityComponentIdPair) { FixUpModelAsset(m_configuration.m_modelAsset); - m_entityId = entityId; + const AZ::EntityId entityId = entityComponentIdPair.GetEntityId(); + m_entityComponentIdPair = entityComponentIdPair; - m_transformInterface = TransformBus::FindFirstHandler(m_entityId); + m_transformInterface = TransformBus::FindFirstHandler(entityId); AZ_Warning("MeshComponentController", m_transformInterface, "Unable to attach to a TransformBus handler. This mesh will always be rendered at the origin."); - m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(m_entityId); + m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity(entityId); AZ_Error("MeshComponentController", m_meshFeatureProcessor, "Unable to find a MeshFeatureProcessorInterface on the entityId."); m_cachedNonUniformScale = AZ::Vector3::CreateOne(); - AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, m_entityId, &AZ::NonUniformScaleRequests::GetScale); - AZ::NonUniformScaleRequestBus::Event(m_entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, + AZ::NonUniformScaleRequestBus::EventResult(m_cachedNonUniformScale, entityId, &AZ::NonUniformScaleRequests::GetScale); + AZ::NonUniformScaleRequestBus::Event(entityId, &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, m_nonUniformScaleChangedHandler); - MeshComponentRequestBus::Handler::BusConnect(m_entityId); - TransformNotificationBus::Handler::BusConnect(m_entityId); - MaterialReceiverRequestBus::Handler::BusConnect(m_entityId); - MaterialComponentNotificationBus::Handler::BusConnect(m_entityId); - AzFramework::BoundsRequestBus::Handler::BusConnect(m_entityId); + MeshComponentRequestBus::Handler::BusConnect(entityId); + TransformNotificationBus::Handler::BusConnect(entityId); + MaterialReceiverRequestBus::Handler::BusConnect(entityId); + MaterialComponentNotificationBus::Handler::BusConnect(entityId); + AzFramework::BoundsRequestBus::Handler::BusConnect(entityId); + AzFramework::EntityContextId contextId; + AzFramework::EntityIdContextQueryBus::EventResult( + contextId, entityId, &AzFramework::EntityIdContextQueries::GetOwningContextId); + AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusConnect({entityId, contextId}); //Buses must be connected before RegisterModel in case requests are made as a result of HandleModelChange RegisterModel(); @@ -209,6 +214,7 @@ namespace AZ // Buses must be disconnected after unregistering the model, otherwise they can't deliver the events during the process. UnregisterModel(); + AzFramework::RenderGeometry::IntersectionRequestBus::Handler::BusDisconnect(); AzFramework::BoundsRequestBus::Handler::BusDisconnect(); MeshComponentRequestBus::Handler::BusDisconnect(); TransformNotificationBus::Handler::BusDisconnect(); @@ -219,7 +225,7 @@ namespace AZ m_meshFeatureProcessor = nullptr; m_transformInterface = nullptr; - m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId); + m_entityComponentIdPair = AZ::EntityComponentIdPair(AZ::EntityId(), AZ::InvalidComponentId); m_configuration.m_modelAsset.Release(); } @@ -293,10 +299,11 @@ namespace AZ Data::Asset modelAsset = m_meshFeatureProcessor->GetModelAsset(m_meshHandle); if (model && modelAsset) { + const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId(); m_configuration.m_modelAsset = modelAsset; - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model); - MaterialReceiverNotificationBus::Event(m_entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged); - AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(m_entityId); + MeshComponentNotificationBus::Event(entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model); + MaterialReceiverNotificationBus::Event(entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged); + AZ::Interface::Get()->RefreshEntityLocalBoundsUnion(entityId); } } @@ -304,8 +311,10 @@ namespace AZ { if (m_meshFeatureProcessor && m_configuration.m_modelAsset.GetId().IsValid()) { + const AZ::EntityId entityId = m_entityComponentIdPair.GetEntityId(); + MaterialAssignmentMap materials; - MaterialComponentRequestBus::EventResult(materials, m_entityId, &MaterialComponentRequests::GetMaterialOverrides); + MaterialComponentRequestBus::EventResult(materials, entityId, &MaterialComponentRequests::GetMaterialOverrides); m_meshFeatureProcessor->ReleaseMesh(m_meshHandle); m_meshHandle = m_meshFeatureProcessor->AcquireMesh(m_configuration.m_modelAsset, materials, @@ -330,7 +339,8 @@ namespace AZ { if (m_meshFeatureProcessor && m_meshHandle.IsValid()) { - MeshComponentNotificationBus::Event(m_entityId, &MeshComponentNotificationBus::Events::OnModelPreDestroy); + MeshComponentNotificationBus::Event( + m_entityComponentIdPair.GetEntityId(), &MeshComponentNotificationBus::Events::OnModelPreDestroy); m_meshFeatureProcessor->ReleaseMesh(m_meshHandle); } } @@ -462,5 +472,34 @@ namespace AZ return Aabb::CreateNull(); } } + + AzFramework::RenderGeometry::RayResult MeshComponentController::RenderGeometryIntersect( + const AzFramework::RenderGeometry::RayRequest& ray) + { + AzFramework::RenderGeometry::RayResult result; + if (const Data::Instance model = GetModel()) + { + float t; + AZ::Vector3 normal; + if (model->RayIntersection( + m_transformInterface->GetWorldTM(), m_cachedNonUniformScale, ray.m_startWorldPosition, + ray.m_endWorldPosition - ray.m_startWorldPosition, t, normal)) + { + // note: this is a temporary workaround to handle cases where model->RayIntersection + // returns negative distances, follow-up ATOM-15673 + const auto absT = AZStd::abs(t); + + // fill in ray result structure after successful intersection + const auto intersectionLine = (ray.m_endWorldPosition - ray.m_startWorldPosition); + result.m_uv = AZ::Vector2::CreateZero(); + result.m_worldPosition = ray.m_startWorldPosition + intersectionLine * absT; + result.m_worldNormal = normal; + result.m_distance = intersectionLine.GetLength() * absT; + result.m_entityAndComponent = m_entityComponentIdPair; + } + } + + return result; + } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h index 0cda34ea42..4d63e5e88d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshComponentController.h @@ -13,11 +13,13 @@ #pragma once #include +#include #include #include #include +#include #include #include @@ -32,9 +34,7 @@ namespace AZ { namespace Render { - /** - * A configuration structure for the MeshComponentController - */ + //! A configuration structure for the MeshComponentController class MeshComponentConfig final : public AZ::ComponentConfig { @@ -57,6 +57,7 @@ namespace AZ class MeshComponentController final : private MeshComponentRequestBus::Handler , public AzFramework::BoundsRequestBus::Handler + , public AzFramework::RenderGeometry::IntersectionRequestBus::Handler , private TransformNotificationBus::Handler , private MaterialReceiverRequestBus::Handler , private MaterialComponentNotificationBus::Handler @@ -77,7 +78,7 @@ namespace AZ MeshComponentController() = default; MeshComponentController(const MeshComponentConfig& config); - void Activate(AZ::EntityId entityId); + void Activate(const AZ::EntityComponentIdPair& entityComponentIdPair); void Deactivate(); void SetConfiguration(const MeshComponentConfig& config); const MeshComponentConfig& GetConfiguration() const; @@ -103,10 +104,13 @@ namespace AZ void SetVisibility(bool visible) override; bool GetVisibility() const override; - // BoundsRequestBus and MeshComponentRequestBus ... + // BoundsRequestBus and MeshComponentRequestBus overrides ... AZ::Aabb GetWorldBounds() override; AZ::Aabb GetLocalBounds() override; + // IntersectionRequestBus overrides ... + AzFramework::RenderGeometry::RayResult RenderGeometryIntersect(const AzFramework::RenderGeometry::RayRequest& ray) override; + // TransformNotificationBus::Handler overrides ... void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; @@ -134,7 +138,7 @@ namespace AZ Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; Render::MeshFeatureProcessorInterface::MeshHandle m_meshHandle; TransformInterface* m_transformInterface = nullptr; - AZ::EntityId m_entityId; + AZ::EntityComponentIdPair m_entityComponentIdPair; bool m_isVisible = true; MeshComponentConfig m_configuration; AZ::Vector3 m_cachedNonUniformScale = AZ::Vector3::CreateOne();