空間查詢

空間查詢是您可以向遠端轉譯服務詢問哪些物件位於區域中的作業。 空間查詢經常用來實作互動,例如找出使用者指向的物件。

所有空間查詢都會在伺服器上進行評估。 因此,查詢是非同步作業,結果會隨著您的網路延遲而延遲而抵達。

光線轉換

光線轉換 是空間查詢,執行時間會檢查哪些物件與光線交集,從指定的位置開始,並指向特定方向。 作為優化,也會提供最大光線距離,以不搜尋太遠的物件。 雖然在伺服器端執行數百個光線轉換是可行的,但每個查詢也會產生網路流量,因此每個畫面的查詢數目應盡可能低。

async void CastRay(RenderingSession session)
{
    // trace a line from the origin into the +z direction, over 10 units of distance.
    RayCast rayCast = new RayCast(new Double3(0, 0, 0), new Double3(0, 0, 1), 10);

    // only return the closest hit
    rayCast.HitCollection = HitCollectionPolicy.ClosestHit;

    RayCastQueryResult result = await session.Connection.RayCastQueryAsync(rayCast);
    RayCastHit[] hits = result.Hits;
    if (hits.Length > 0)
    {
        var hitObject = hits[0].HitObject;
        var hitPosition = hits[0].HitPosition;
        var hitNormal = hits[0].HitNormal;
        var hitType = hits[0].HitType;
        // do something with the hit information
    }
}
void CastRay(ApiHandle<RenderingSession> session)
{
    // trace a line from the origin into the +z direction, over 10 units of distance.
    RayCast rayCast;
    rayCast.StartPos = {0, 0, 0};
    rayCast.EndPos = {0, 0, 10};

    // only return the closest hit
    rayCast.HitCollection = HitCollectionPolicy::ClosestHit;

    session->Connection()->RayCastQueryAsync(rayCast, [](Status status, ApiHandle<RayCastQueryResult> result)
    {
        if (status == Status::OK)
        {
            std::vector<RayCastHit> hits;
            result->GetHits(hits);

            if (hits.size() > 0)
            {
                auto hitObject = hits[0].HitObject;
                auto hitPosition = hits[0].HitPosition;
                auto hitNormal = hits[0].HitNormal;
                auto hitType = hits[0].HitType;

                // do something with the hit information
            }
        }
    });
}

點擊收集模式有三種:

  • Closest 在此模式中,只會報告最接近的點擊數。
  • Any 當您想要知道 光線是否會 擊中任何專案時,偏好此模式,但不在乎所擊中的內容。 此查詢可大幅降低評估成本,但只有少數應用程式。
  • All 在此模式中,會報告沿著光線的所有點擊,依距離排序。 除非您真的需要超過第一次點擊,否則請勿使用此模式。 使用 MaxHits 選項來限制回報點擊數目。

若要選擇性地排除物件不考慮光線轉換, 可以使用 HierarchicalStateOverrideComponent 元件。

點擊結果

光線轉換查詢的結果是點擊陣列。 如果未叫用任何物件,則陣列是空的。

Hit 具有下列屬性:

  • HitEntity 已叫用哪一個 實體
  • SubPartId 在 MeshComponent 中叫用哪 一個 submesh 。 可用來編制索引, MeshComponent.UsedMaterials 並在該時間點查閱 材質
  • HitPosition 光線與物件交集所在的世界空間位置。
  • HitNormal 世界空間表面在交集位置的網格正常。
  • DistanceToHit 從光線開始位置到點擊的距離。
  • HitType 光線擊中的內容: TriangleFrontFaceTriangleBackFacePoint 。 根據預設, ARR 會呈現雙面, 因此使用者看到的三角形不一定是正面。 如果您想要區分 TriangleFrontFace 程式碼中的 和 TriangleBackFace ,請確定您的模型會先以正確的臉部指示撰寫。

空間查詢

空間查詢 可讓執行時間檢查 哪些 MeshComponent 與使用者定義的磁片區相交。 由於個別檢查是根據場景中每個網格部分的界限執行,而不是個別的三角形,因此此檢查的執行效能是有效的。 作為優化,可以提供命中網格元件的數目上限。
雖然這類查詢可以在用戶端手動執行,但對於大型場景,伺服器可以更快速地計算此查詢。

下列範例程式碼示範如何針對座標軸對齊周框方塊執行查詢(AABB)。 查詢的變體也允許導向周框方塊磁片區 ( SpatialQueryObbAsync ) 和球體磁片區 ( SpatialQuerySphereAsync )。

async void QueryAABB(RenderingSession session)
{
    // Query all mesh components in a 2x2x2m cube.
    SpatialQueryAabb query = new SpatialQueryAabb();
    query.Bounds = new Microsoft.Azure.RemoteRendering.Bounds(new Double3(-1, -1, -1), new Double3(1, 1, 1));
    query.MaxResults = 100;

    SpatialQueryResult result = await session.Connection.SpatialQueryAabbAsync(query);
    foreach (MeshComponent meshComponent in result.Overlaps)
    {
        Entity owner = meshComponent.Owner;
        // do something with the hit MeshComponent / Entity
    }
}
void QueryAABB(ApiHandle<RenderingSession> session)
{
    // Query all mesh components in a 2x2x2m cube.
    SpatialQueryAabb query;
    query.Bounds.Min = {-1, -1, -1};
    query.Bounds.Max = {1, 1, 1};
    query.MaxResults = 100;

    session->Connection()->SpatialQueryAabbAsync(query, [](Status status, ApiHandle<SpatialQueryResult> result)
        {
            if (status == Status::OK)
            {
                std::vector<ApiHandle<MeshComponent>> overlaps;
                result->GetOverlaps(overlaps);

                for (ApiHandle<MeshComponent> meshComponent : overlaps)
                {
                    ApiHandle<Entity> owner = meshComponent->GetOwner();
                    // do something with the hit MeshComponent / Entity
                }
            }
        });
}

API 文件

下一步