Share via


Uzamsal sorgular

Uzamsal sorgular, uzak işleme hizmetine bir alanda hangi nesnelerin bulunduğunu sorabileceğiniz işlemlerdir. Uzamsal sorgular, kullanıcının hangi nesneye işaret ettiği gibi etkileşimleri uygulamak için sıklıkla kullanılır.

Tüm uzamsal sorgular sunucuda değerlendirilir. Buna göre, sorgular zaman uyumsuz işlemlerdir ve sonuçlar ağ gecikmenize bağlı bir gecikmeyle gelir.

Ray casts

Işın ataması, çalışma zamanının belirli bir konumdan başlayıp belirli bir yöne işaret eden bir ışınla kesişen nesneleri denetlediği uzamsal bir sorgudur. İyileştirme olarak, çok uzak olan nesneleri aramamak için maksimum ışın uzaklığı da verilir. Her çerçevenin sunucu tarafında yüzlerce ışın ataması yapılması işlem açısından uygun olsa da, her sorgu ağ trafiği de oluşturur, bu nedenle çerçeve başına sorgu sayısı mümkün olduğunca düşük tutulmalıdır.

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

Üç isabet toplama modu vardır:

  • Closest: Bu modda yalnızca en yakın isabet bildirilir.
  • Any: Tek bilmek istediğiniz bir ışın herhangi bir şeye çarpar mı , ancak tam olarak neyin isabet edildiği önemli değilse bu modu tercih edin. Bu sorguyu değerlendirmek çok daha ucuz olabilir, ancak yalnızca birkaç uygulaması da vardır.
  • All: Bu modda, ışın boyunca yapılan tüm isabetler, mesafeye göre sıralanmış olarak raporlanır. İlk vuruştan daha fazlasına ihtiyacınız yoksa bu modu kullanmayın. Seçeneğiyle bildirilen isabet sayısını sınırlayın MaxHits .

Nesneleri işın atamaları için seçmeli olarak dikkate alınmadan dışlamak için HierarchicalStateOverrideComponent bileşeni kullanılabilir.

İsabet sonucu

Bir ışın atama sorgusunun sonucu, isabet dizisidir. Hiçbir nesneye isabet verilmediyse dizi boş olur.

İsabet aşağıdaki özelliklere sahiptir:

  • HitEntity: Hangi varlığa isabet edildi.
  • SubPartId: MeshComponent'te hangi alt bileşene isabet edildi? Bu noktada içine dizin MeshComponent.UsedMaterials oluşturmak ve malzemeyi aramak için kullanılabilir.
  • HitPosition: Ray'in nesnenin kesiştiği dünya uzay konumu.
  • HitNormal: Dünya uzayı kesişim konumunda ağın normal yüzeyidir.
  • DistanceToHit: Işın başlangıç konumundan vuruşa olan uzaklık.
  • HitType: Ray tarafından ne isabet edilir: TriangleFrontFace, TriangleBackFace veya Point. Varsayılan olarak ARR, kullanıcının gördüğü üçgenlerin ön tarafa dönük olması gerekmeyecek şekilde çift taraflı olarak işlenir. Kodunuzda ve TriangleBackFace arasında TriangleFrontFace ayrım yapmak istiyorsanız, önce modellerinizin doğru yüz tarifleriyle yazıldığından emin olun.

Uzamsal sorgular

Uzamsal sorgu , çalışma zamanının hangi MeshComponents'in kullanıcı tanımlı bir birimle kesiştiği denetlemesini sağlar. Tek tek denetim, tek tek üçgen temelinde değil, sahnedeki her bir mesh parçasının sınırları temelinde yapıldığından bu denetim gerçekleştirilir. İyileştirme olarak en fazla isabetli ağ bileşeni sayısı sağlanabilir.
Böyle bir sorgu istemci tarafında el ile çalıştırılabilirken, büyük sahneler için sunucunun bunu hesaplaması daha hızlı bir şekilde sıralanabilir.

Aşağıdaki örnek kod, eksene hizalanmış sınırlayıcı kutuya (AABB) karşı sorguların nasıl yapılacağını gösterir. Sorgunun varyantları, yönlendirmeli sınırlayıcı kutu birimlerine (SpatialQueryObbAsync) ve küre birimlerine (SpatialQuerySphereAsync) de olanak sağlar.

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 belgeleri

Sonraki adımlar