Support mesh intersection for camera orbit (#982)
* wip support for mesh intersection with intersector bus * WIP camera mesh intersection orbit logic * remove unneeded template argument * add bus connect/disconnect * fix intersection logic * small updates, additional comments, some tidy-up * update formatting options slightly * use aznumeric_cast * temp workaround for negative distances with RayIntersection
This commit is contained in:
committed by
GitHub
parent
c9f7cd03bb
commit
36ceff84c9
@@ -35,14 +35,13 @@ namespace AZ
|
||||
, private MeshComponentNotificationBus::Handler
|
||||
{
|
||||
public:
|
||||
|
||||
using BaseClass = EditorRenderComponentAdapter<MeshComponentController, MeshComponent, MeshComponentConfig>;
|
||||
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;
|
||||
|
||||
@@ -25,12 +25,11 @@ namespace AZ
|
||||
: public AzFramework::Components::ComponentAdapter<MeshComponentController, MeshComponentConfig>
|
||||
{
|
||||
public:
|
||||
|
||||
using BaseClass = AzFramework::Components::ComponentAdapter<MeshComponentController, MeshComponentConfig>;
|
||||
AZ_COMPONENT(AZ::Render::MeshComponent, MeshComponentTypeId, BaseClass);
|
||||
|
||||
MeshComponent() = default;
|
||||
MeshComponent(const MeshComponentConfig& config);
|
||||
explicit MeshComponent(const MeshComponentConfig& config);
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
};
|
||||
|
||||
+56
-17
@@ -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<MeshFeatureProcessorInterface>(m_entityId);
|
||||
m_meshFeatureProcessor = RPI::Scene::GetFeatureProcessorForEntity<MeshFeatureProcessorInterface>(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<RPI::ModelAsset> 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<AzFramework::IEntityBoundsUnion>::Get()->RefreshEntityLocalBoundsUnion(m_entityId);
|
||||
MeshComponentNotificationBus::Event(entityId, &MeshComponentNotificationBus::Events::OnModelReady, m_configuration.m_modelAsset, model);
|
||||
MaterialReceiverNotificationBus::Event(entityId, &MaterialReceiverNotificationBus::Events::OnMaterialAssignmentsChanged);
|
||||
AZ::Interface<AzFramework::IEntityBoundsUnion>::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<RPI::Model> 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
|
||||
|
||||
@@ -13,11 +13,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
|
||||
#include <AtomCore/Instance/InstanceDatabase.h>
|
||||
|
||||
#include <AzFramework/Render/GeometryIntersectionBus.h>
|
||||
#include <AzFramework/Visibility/BoundsBus.h>
|
||||
|
||||
#include <Atom/RPI.Public/Model/Model.h>
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user