AZStd::vector UmbraSceneComponentController::UmbraOcclusionView::GetAabbToAabbVisibility()

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;
    }