الاستعلامات المكانية

الاستعلامات المكانية هي العمليات التي يمكنك من خلالها طلب خدمة العرض عن بعد الكائنات الموجودة في منطقة ما. تستخدم الاستعلامات المكانية بشكل متكرر لتنفيذ التفاعلات، مثل معرفة العنصر الذي يشير إليه المستخدم.

يتم تقييم جميع الاستعلامات المكانية على الخادم. وفقا لذلك، الاستعلامات هي عمليات غير متزامنة والنتائج تصل مع تأخير يعتمد على زمن انتقال الشبكة.

أشعة المدلى بها

الأشعة المدلى بها هي استعلام مكاني حيث يتحقق وقت التشغيل من الكائنات التي تتقاطع مع شعاع، بدءا من موضع معين والإشارة إلى اتجاه معين. ك تحسين، يتم أيضا إعطاء الحد الأقصى لمسافة الأشعة، لعدم البحث عن الكائنات البعيدة جدا. على الرغم من أن القيام بمئات من الأشعة يلقي كل إطار ممكن حسابيا على جانب الخادم، فإن كل استعلام يولد أيضا حركة مرور الشبكة، لذلك يجب الاحتفاظ بعدد الاستعلامات لكل إطار منخفضا قدر الإمكان.

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. يمكن استخدامها للفهرسة والبحث MeshComponent.UsedMaterials عن المواد في تلك المرحلة.
  • HitPosition: موقع الفضاء العالمي حيث تداخل الشعاع مع الكائن.
  • HitNormal: سطح الفضاء العالمي العادي من الشبكة في موضع التقاطع.
  • DistanceToHit: المسافة من موقع بدء الشعاع إلى ضرب.
  • HitType: ما يضربه الشعاع: TriangleFrontFace، TriangleBackFace أو Point. بشكل افتراضي، يتم عرض ARR على الوجهين بحيث لا تكون المثلثات التي يراها المستخدم أمامية بالضرورة. إذا كنت تريد التمييز بين TriangleFrontFace التعليمات البرمجية الخاصة بك وفيها TriangleBackFace ، فتأكد من تأليف النماذج الخاصة بك مع اتجاهات الوجه الصحيحة أولا.

الاستعلامات المكانية

يسمح الاستعلام المكاني لوقت التشغيل بالتحقق من تداخل MeshComponents مع وحدة تخزين معرفة من قبل المستخدم. يكون هذا الفحص مؤدية حيث يتم إجراء الفحص الفردي استنادا إلى حدود كل جزء شبكة في المشهد، وليس على أساس مثلث فردي. لتحسين الأداء، يمكن توفير الحد الأقصى لعدد مكونات شبكة الوصول.
في حين يمكن تشغيل مثل هذا الاستعلام يدويا على جانب العميل، بالنسبة للمشاهد الكبيرة، يمكن أن يكون ترتيبا بحجم أسرع للخادم لحساب هذا.

يوضح المثال التالي التعليمات البرمجية كيفية إجراء الاستعلامات مقابل مربع إحاطة محاذاة المحور (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

الخطوات التالية