in Gems/Umbra/Code/Source/UmbraSceneComponent/UmbraSceneComponentController.cpp [548:607]
AZStd::vector<AzFramework::OcclusionState> UmbraSceneComponentController::UmbraOcclusionView::GetAabbToAabbVisibility(const AZ::Aabb& sourceAabb, const AZStd::vector<AZ::Aabb>& targetAabbs) const
{
AZ_Assert(m_controller.IsSceneReady(), "Umbra scene component controller and assets must be valid and ready before query.");
AZ_Assert(m_query, "Umbra query object must be valid before query.");
if (!m_controller.IsSceneReady() || !m_query)
{
return {};
}
// Return early if any of the bounding boxes are invalid or there are no target bounding boxes to test
if (!sourceAabb.IsValid() || targetAabbs.empty() || !AZStd::all_of(targetAabbs.begin(), targetAabbs.end(), [](const auto& aabb) { return aabb.IsValid(); }))
{
return {};
}
// Convert all of the O3DE data types into Umbra data types for the query
Umbra::Vector3 sourceMin = {};
Umbra::Vector3 sourceMax = {};
sourceAabb.GetMin().StoreToFloat3(sourceMin.v);
sourceAabb.GetMax().StoreToFloat3(sourceMax.v);
const int targetCount = aznumeric_cast<int>(targetAabbs.size());
AZStd::vector<Umbra::Vector3> targetMin(targetCount, Umbra::Vector3{});
AZStd::vector<Umbra::Vector3> targetMax(targetCount, Umbra::Vector3{});
for (int i = 0; i < targetCount; ++i)
{
targetAabbs[i].GetMin().StoreToFloat3(targetMin[i].v);
targetAabbs[i].GetMax().StoreToFloat3(targetMax[i].v);
}
// Create a container for all of the intersection results, defaulting all objects to being visible.
AZStd::vector<Umbra::QueryExt::IntersectionResult> intersections(targetCount, Umbra::QueryExt::IntersectionResult::IRESULT_NO_INTERSECTION);
const Umbra::Query::ErrorCode errorCode = m_query->queryAABBVisibility(sourceMin, sourceMax, targetMin.data(), targetMax.data(), targetCount, 0, intersections.data());
if (errorCode != Umbra::Query::ErrorCode::ERROR_OK)
{
Internal::PrintQueryErrorMessage(errorCode);
return {};
}
// Convert all of the intersection data into flags, returning true if source and target into these can see each other.
AZStd::vector<AzFramework::OcclusionState> results(targetCount, AzFramework::OcclusionState::Unknown);
for (int i = 0; i < targetCount; ++i)
{
switch (intersections[i])
{
case Umbra::QueryExt::IntersectionResult::IRESULT_INTERSECTION:
results[i] = AzFramework::OcclusionState::Hidden;
break;
case Umbra::QueryExt::IntersectionResult::IRESULT_NO_INTERSECTION:
results[i] = AzFramework::OcclusionState::Visible;
break;
default:
results[i] = AzFramework::OcclusionState::Unknown;
break;
}
}
return results;
}