Пространственные запросы
Пространственные запросы — это операции, с помощью которых можно опрашивать службу удаленной визуализации о том, какие объекты расположены в области. Пространственные запросы часто используются для реализации взаимодействий, например, для выяснения того, на какой объект указывает пользователь.
Все пространственные запросы вычисляются на сервере. Соответственно, запросы являются асинхронными операциями и результаты прибывают с задержкой, которая зависит от задержки в сети.
Пересечение лучами
Приведение лучей — это пространственный запрос, в котором среда выполнения проверка, которые объекты пересекают луч, начиная с заданной позиции и указывая на определенное направление. Для оптимизации производительности можно указать максимальную дальность луча, чтобы не искать слишком далекие объекты. Несмотря на то, что на стороне сервера выполняется вычисление сотни приведения лучей, каждый запрос также создает сетевой трафик, поэтому количество запросов на кадр должно храниться как можно ниже.
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
: Какой подмеш был поражен в СеткеComponent. Можно использовать для индексированияMeshComponent.UsedMaterials
и поиска материала в этой точке.HitPosition
: положение мирового пространства, в котором луч пересекал объект.HitNormal
: мировая поверхность пространства нормальной сетки в расположении пересечения.DistanceToHit
: расстояние от луча начальной позиции к удару.HitType
: Что ударяется лучом:TriangleFrontFace
TriangleBackFace
илиPoint
. По умолчанию ARR отображает двойную сторону, поэтому треугольники, которые пользователь видит, не обязательно передней. Если вы хотите различать иTriangleBackFace
различатьTriangleFrontFace
модели в коде, сначала убедитесь, что модели создаются с правильными направлениями лиц.
Пространственные запросы
Пространственный запрос позволяет среде выполнения проверка, которые СеткаComponents пересекаются с определяемым пользователем томом. Этот проверка выполняется как отдельный проверка выполняется на основе границ каждой части сетки в сцене, а не на отдельном треугольнике. В качестве оптимизации можно предоставить максимальное количество компонентов сетки.
Хотя такой запрос может выполняться вручную на стороне клиента, для больших сцен это может быть значительно быстрее, чтобы сервер вычислил это.
В следующем примере кода показано, как выполнять запросы к выровненной ось ограничивающей рамке (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
- C# RenderingConnection.RayCastQueryAsync()
- Отрисовка C#Подключение. SpatialQueryAabbAsync()
- Отрисовка C#Подключение. SpatialQuerySphereAsync()
- Отрисовка C#Подключение. SpatialQueryObbAsync()
- C++ RenderingConnection::RayCastQueryAsync()
- Отрисовка C++Подключение ion::SpatialQueryAabbAsync()
- Отрисовка C++Подключение ion::SpatialQuerySphereAsync()
- Отрисовка C++Подключение ion::SpatialQueryObbAsync()