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:
Tom Hulton-Harrop
2021-05-28 14:37:17 +01:00
committed by GitHub
parent c9f7cd03bb
commit 36ceff84c9
9 changed files with 191 additions and 100 deletions
@@ -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