Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Podczas tworzenia pierwszych aplikacji dla Microsoft HoloLens chętnie zobaczyliśmy, jak daleko możemy przesunąć granice mapowania przestrzennego na urządzeniu. Jeff Evertt, inżynier oprogramowania w Firmie Microsoft Studios, wyjaśnia, w jaki sposób nowa technologia została opracowana z potrzeby większej kontroli nad tym, jak hologramy są umieszczane w rzeczywistym środowisku użytkownika.
Uwaga
HoloLens 2 implementuje nowe środowisko uruchomieniowe Scene Understanding, które zapewnia deweloperom Mixed Reality ustrukturyzowaną reprezentację środowiska wysokiego poziomu zaprojektowaną w celu zapewnienia intuicyjnego tworzenia aplikacji obsługujących środowisko.
Obejrzyj film
Poza mapowaniem przestrzennym
Podczas pracy nad fragmentami i Young Conkerem, dwie z pierwszych gier dla urządzenia HoloLens, odkryliśmy, że kiedy robiliśmy proceduralne umieszczanie hologramów w świecie fizycznym, potrzebowaliśmy wyższego poziomu zrozumienia środowiska użytkownika. Każda gra miała własne potrzeby dotyczące umieszczania: na przykład w fragmentach chcieliśmy odróżnić różne powierzchnie — takie jak podłoga lub stół — aby umieścić wskazówki w odpowiednich lokalizacjach. Chcieliśmy również zidentyfikować powierzchnie, na których mogą usiąść znaki holograficzne wielkości życia, takie jak kanapa lub krzesło. W Young Conker chcieliśmy, aby Conker i jego przeciwnicy mogli używać podniesionych powierzchni w pokoju gracza jako platform.
Asobo Studios, nasz partner rozwoju dla tych gier, w obliczu tego problemu head-on i stworzył technologię, która rozszerza możliwości mapowania przestrzennego urządzenia HoloLens. Dzięki temu możemy przeanalizować pokój gracza i zidentyfikować powierzchnie, takie jak ściany, stoły, krzesła i podłogi. Dało nam to również możliwość optymalizacji pod kątem zestawu ograniczeń w celu określenia najlepszego umieszczania obiektów holograficznych.
Kod zrozumienia przestrzennego
Wzięliśmy oryginalny kod Asobo i utworzyliśmy bibliotekę, która hermetyzuje tę technologię. Firma Microsoft i Asobo mają teraz otwarty kod i udostępnili go w zestawie MixedRealityToolkit do użycia we własnych projektach. Cały kod źródłowy jest dołączony, dzięki czemu możesz dostosować go do własnych potrzeb i udostępnić swoje ulepszenia społeczności. Kod modułu rozwiązywania języka C++ został opakowany w bibliotekę DLL platformy UWP i uwidoczniony dla aparatu Unity z prefabem drop-in zawartym w zestawie MixedRealityToolkit.
Istnieje wiele przydatnych zapytań zawartych w przykładzie aparatu Unity, które umożliwią znalezienie pustych przestrzeni na ścianach, umieszczenie obiektów na suficie lub na dużych przestrzeniach na podłodze, zidentyfikowanie miejsc, w których można usiąść znaków, oraz mnóstwo innych zapytań interpretacji przestrzennej.
Chociaż rozwiązanie do mapowania przestrzennego dostarczone przez urządzenie HoloLens zostało zaprojektowane tak, aby było wystarczająco ogólne, aby zaspokoić potrzeby całej gamy przestrzeni problemów, moduł zrozumienia przestrzennego został skompilowany w celu obsługi potrzeb dwóch konkretnych gier. W związku z tym jego rozwiązanie ma strukturę wokół określonego procesu i zestawu założeń:
- Przestrzeń odtwarzania o stałym rozmiarze: użytkownik określa maksymalny rozmiar przestrzeni odtwarzania w wywołaniu inicjowania.
- Jednorazowy proces skanowania: proces wymaga odrębnej fazy skanowania, w której użytkownik przechodzi przez definiowanie przestrzeni odtwarzania. Funkcje zapytań nie będą działać dopiero po zakończeniu skanowania.
- User driven playspace "painting": Podczas fazy skanowania użytkownik porusza się i rozgląda się po przestrzeni odtwarzania, skutecznie malując obszary, które powinny być uwzględnione. Wygenerowana siatka jest ważna, aby przekazać opinię użytkowników w tej fazie.
- Konfiguracja domu lub biura w pomieszczeniach: funkcje zapytań są projektowane wokół płaskich powierzchni i ścian pod kątem prostym. Jest to ograniczenie miękkie. Jednak podczas fazy skanowania analiza osi podstawowej jest zakończona w celu zoptymalizowania tessellacji siatki wzdłuż głównej i pomocniczej osi.
Proces skanowania pomieszczeń
Podczas ładowania modułu interpretacji przestrzennej najpierw przeskanujesz przestrzeń, więc wszystkie powierzchnie, takie jak podłoga, sufit i ściany, są identyfikowane i oznaczane etykietami. Podczas procesu skanowania rozejrzysz się po pomieszczeniu i "maluj" obszary, które powinny zostać uwzględnione w skanowaniu.
Siatka widziana w tej fazie jest ważnym elementem wizualnym opinii, który informuje użytkowników, jakie części pomieszczenia są skanowane. Biblioteka DLL dla modułu zrozumienia przestrzennego wewnętrznie przechowuje przestrzeń odtwarzania jako siatkę modułów voxel o rozmiarze 8 cm. Podczas początkowej części skanowania analiza podstawowego składnika jest zakończona w celu określenia osi pomieszczenia. Wewnętrznie przechowuje przestrzeń voxel wyrównaną do tych osi. Siatka jest generowana mniej więcej co sekundę przez wyodrębnienie izopochirurgi z objętości voxel.
Siatka mapowania przestrzennego w kolorze białym i interpretacja siatki przestrzeni odtwarzania w kolorze zielonym
Dołączony plik SpatialUnderstanding.cs zarządza procesem fazy skanowania. Wywołuje ona następujące funkcje:
- SpatialUnderstanding_Init: wywoływane raz na początku.
- GeneratePlayspace_InitScan: wskazuje, że faza skanowania powinna się rozpocząć.
- GeneratePlayspace_UpdateScan_DynamicScan: każda ramka jest wywoływana w celu zaktualizowania procesu skanowania. Pozycja i orientacja aparatu są przekazywane i są używane do procesu malowania przestrzeni playspace, opisanego powyżej.
- GeneratePlayspace_RequestFinish: Wezwano do sfinalizowania przestrzeni playspace. Spowoduje to użycie obszarów "malowanych" w fazie skanowania w celu zdefiniowania i zablokowania przestrzeni odtwarzania. Aplikacja może wykonywać zapytania dotyczące statystyk w fazie skanowania, a także wykonywać zapytania dotyczące niestandardowej siatki w celu przekazywania opinii użytkowników.
- Import_UnderstandingMesh: podczas skanowania zachowanie SpatialUnderstandingCustomMesh dostarczone przez moduł i umieszczone w prefabie będzie okresowo wykonywać zapytania dotyczące niestandardowej siatki wygenerowanej przez proces. Ponadto odbywa się to po raz kolejny po sfinalizowaniu skanowania.
Przepływ skanowania sterowany przez zachowanie SpatialUnderstanding wywołuje metodę InitScan, a następnie UpdateScan każdą ramkę. Gdy zapytanie statystyczne zgłasza rozsądny zakres, użytkownik może wysłać zrzut, aby wywołać metodę RequestFinish , aby wskazać koniec fazy skanowania. Funkcja UpdateScan będzie nadal wywoływana, dopóki nie zostanie zwrócona wartość wskazująca, że biblioteka DLL zakończyła przetwarzanie.
Zapytania
Po zakończeniu skanowania będziesz mieć dostęp do trzech różnych typów zapytań w interfejsie:
- Zapytania topologii: są to szybkie zapytania oparte na topologii zeskanowanego pokoju.
- Zapytania dotyczące kształtów: wykorzystują wyniki zapytań topologii do znajdowania powierzchni poziomych, które są dobrym dopasowaniem do kształtów niestandardowych, które definiujesz.
- Zapytania dotyczące umieszczania obiektów: są to bardziej złożone zapytania, które znajdują lokalizację najlepiej dopasowaną na podstawie zestawu reguł i ograniczeń dla obiektu.
Oprócz trzech podstawowych zapytań dostępny jest interfejs raycastingu, który może służyć do pobierania oznakowanych typów powierzchni, a niestandardowa wodoszczelna siatka pomieszczenia można skopiować.
Zapytania topologii
W ramach biblioteki DLL menedżer topologii obsługuje etykietowanie środowiska. Jak wspomniano powyżej, wiele danych jest przechowywanych w surfelach, które znajdują się w woluminie voxel. Ponadto struktura PlaySpaceInfos służy do przechowywania informacji o przestrzeni odtwarzania, w tym wyrównania świata (więcej szczegółów na ten temat poniżej), wysokości podłogi i sufitu.
Heurystyka służy do określania podłogi, sufitu i ścian. Na przykład największa i najniższa powierzchnia pozioma o powierzchni większej niż 1 m2 jest uznawana za podłogę. Należy pamiętać, że ścieżka aparatu podczas procesu skanowania jest również używana w tym procesie.
Podzbiór zapytań uwidocznionych przez menedżera topologii jest udostępniany za pośrednictwem biblioteki DLL. Uwidocznione zapytania topologii są następujące:
- QueryTopology_FindPositionsOnWalls
- QueryTopology_FindLargePositionsOnWalls
- QueryTopology_FindLargestWall
- QueryTopology_FindPositionsOnFloor
- QueryTopology_FindLargestPositionsOnFloor
- QueryTopology_FindPositionsSittable
Każde zapytanie ma zestaw parametrów specyficznych dla typu zapytania. W poniższym przykładzie użytkownik określa minimalną wysokość & szerokość żądanego woluminu, minimalną wysokość umieszczania nad podłogą i minimalną ilość odstępu przed woluminem. Wszystkie pomiary znajdują się w metrach.
EXTERN_C __declspec(dllexport) int QueryTopology_FindPositionsOnWalls(
_In_ float minHeightOfWallSpace,
_In_ float minWidthOfWallSpace,
_In_ float minHeightAboveFloor,
_In_ float minFacingClearance,
_In_ int locationCount,
_Inout_ Dll_Interface::TopologyResult* locationData)
Każde z tych zapytań przyjmuje wstępnie przydzieloną tablicę struktur TopologyResult . Parametr locationCount określa długość przekazanej tablicy. Wartość zwracana zgłasza liczbę zwróconych lokalizacji. Liczba ta nigdy nie jest większa niż przekazany parametr locationCount .
Element TopologyResult zawiera środkową pozycję zwracanego woluminu, kierunek skierowany (tj. normalny) oraz wymiary znalezionej przestrzeni.
struct TopologyResult
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT3 normal;
float width;
float length;
};
Należy pamiętać, że w przykładzie aparatu Unity każde z tych zapytań jest połączone z przyciskiem w panelu wirtualnego interfejsu użytkownika. Przykładowy twardy koduje parametry dla każdego z tych zapytań do rozsądnych wartości. Aby uzyskać więcej przykładów , zobacz SpaceVisualizer.cs w przykładowym kodzie.
Zapytania dotyczące kształtów
Wewnątrz biblioteki DLL analizator kształtów (ShapeAnalyzer_W) używa analizatora topologii do dopasowywania do kształtów niestandardowych zdefiniowanych przez użytkownika. Przykład aparatu Unity zawiera wstępnie zdefiniowany zestaw kształtów, które są wyświetlane w menu zapytania na karcie kształtów.
Należy pamiętać, że analiza kształtu działa tylko na powierzchniach poziomych. Kanapa, na przykład, jest definiowana przez płaską powierzchnię siedzenia i płaską górną część kanapy z tyłu. Zapytanie o kształt szuka dwóch powierzchni o określonym rozmiarze, wysokości i zakresie aspektów, z dwoma powierzchniami wyrównanymi i połączonymi. Korzystając z terminologii interfejsów API, siedzenia kanapy i górnej części kanapy są składnikami kształtu, a wymagania dotyczące wyrównania są ograniczeniami składników kształtu.
Przykładowe zapytanie zdefiniowane w przykładzie aparatu Unity (ShapeDefinition.cs) dla obiektów "sittable" jest następujące:
shapeComponents = new List<ShapeComponent>()
{
new ShapeComponent(
new List<ShapeComponentConstraint>()
{
ShapeComponentConstraint.Create_SurfaceHeight_Between(0.2f, 0.6f),
ShapeComponentConstraint.Create_SurfaceCount_Min(1),
ShapeComponentConstraint.Create_SurfaceArea_Min(0.035f),
}),
};
AddShape("Sittable", shapeComponents);
Każde zapytanie kształtu jest definiowane przez zestaw składników kształtu, z których każdy ma zestaw ograniczeń składników i zestaw ograniczeń kształtu, które zawierają listę zależności między składnikami. Ten przykład obejmuje trzy ograniczenia w definicji pojedynczego składnika i brak ograniczeń kształtu między składnikami (ponieważ istnieje tylko jeden składnik).
Z kolei kształt kanapy ma dwa składniki kształtu i cztery ograniczenia kształtu. Należy pamiętać, że składniki są identyfikowane przez ich indeks na liście składników użytkownika (0 i 1 w tym przykładzie).
shapeConstraints = new List<ShapeConstraint>()
{
ShapeConstraint.Create_RectanglesSameLength(0, 1, 0.6f),
ShapeConstraint.Create_RectanglesParallel(0, 1),
ShapeConstraint.Create_RectanglesAligned(0, 1, 0.3f),
ShapeConstraint.Create_AtBackOf(1, 0),
};
Funkcje otoki są udostępniane w module Aparatu Unity w celu łatwego tworzenia niestandardowych definicji kształtów. Pełną listę ograniczeń składników i kształtów można znaleźć w pliku SpatialUnderstandingDll.cs w strukturze ShapeComponentConstraint i ShapeConstraint .
Niebieski prostokąt wyróżnia wyniki zapytania kształtu krzesła.
Rozwiązywanie problemów z umieszczaniem obiektów
Zapytania umieszczania obiektów mogą służyć do identyfikowania idealnych lokalizacji w pomieszczeniu fizycznym w celu umieszczania obiektów. Rozwiązanie znajdzie najlepszą lokalizację, biorąc pod uwagę reguły obiektów i ograniczenia. Ponadto zapytania dotyczące obiektów są utrwalane do momentu usunięcia obiektu z wywołaniami Solver_RemoveObject lub Solver_RemoveAllObjects , co pozwala na ograniczone umieszczanie wielu obiektów.
Zapytania umieszczania obiektów składają się z trzech części: typu umieszczania z parametrami, listą reguł i listą ograniczeń. Aby uruchomić zapytanie, użyj następującego interfejsu API:
public static int Solver_PlaceObject(
[In] string objectName,
[In] IntPtr placementDefinition, // ObjectPlacementDefinition
[In] int placementRuleCount,
[In] IntPtr placementRules, // ObjectPlacementRule
[In] int constraintCount,
[In] IntPtr placementConstraints, // ObjectPlacementConstraint
[Out] IntPtr placementResult)
Ta funkcja przyjmuje nazwę obiektu, definicję umieszczania oraz listę reguł i ograniczeń. Otoki języka C# zapewniają funkcje pomocnika budowlanego, aby ułatwić tworzenie reguł i ograniczeń. Definicja umieszczania zawiera typ zapytania — czyli jeden z następujących elementów:
public enum PlacementType
{
Place_OnFloor,
Place_OnWall,
Place_OnCeiling,
Place_OnShape,
Place_OnEdge,
Place_OnFloorAndCeiling,
Place_RandomInAir,
Place_InMidAir,
Place_UnderFurnitureEdge,
};
Każdy z typów umieszczania ma zestaw parametrów unikatowych dla typu. Struktura ObjectPlacementDefinition zawiera zestaw funkcji statycznych pomocników do tworzenia tych definicji. Aby na przykład znaleźć miejsce do umieszczania obiektu na podłodze, można użyć następującej funkcji:
public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims)
Oprócz typu umieszczania można podać zestaw reguł i ograniczeń. Nie można naruszać reguł. Możliwe lokalizacje umieszczania spełniające typ i reguły są następnie zoptymalizowane pod kątem zestawu ograniczeń, aby wybrać optymalną lokalizację umieszczania. Każda z reguł i ograniczeń może zostać utworzona przez udostępnione funkcje tworzenia statycznego. Poniżej podano przykładową regułę i funkcję budowy ograniczeń.
public static ObjectPlacementRule Create_AwayFromPosition(
Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)
Zapytanie dotyczące umieszczania obiektów poniżej szuka miejsca, które umieścić pół metra modułu na krawędzi powierzchni, z dala od innych wcześniej umieszczonych obiektów i w pobliżu środka pomieszczenia.
List<ObjectPlacementRule> rules =
new List<ObjectPlacementRule>() {
ObjectPlacementRule.Create_AwayFromOtherObjects(1.0f),
};
List<ObjectPlacementConstraint> constraints =
new List<ObjectPlacementConstraint> {
ObjectPlacementConstraint.Create_NearCenter(),
};
Solver_PlaceObject(
“MyCustomObject”,
new ObjectPlacementDefinition.Create_OnEdge(
new Vector3(0.25f, 0.25f, 0.25f),
new Vector3(0.25f, 0.25f, 0.25f)),
rules.Count,
UnderstandingDLL.PinObject(rules.ToArray()),
constraints.Count,
UnderstandingDLL.PinObject(constraints.ToArray()),
UnderstandingDLL.GetStaticObjectPlacementResultPtr());
W przypadku powodzenia zwracana jest struktura ObjectPlacementResult zawierająca położenie położenia, wymiary i orientację. Ponadto umieszczanie jest dodawane do wewnętrznej listy obiektów umieszczonych w dll. Kolejne zapytania umieszczania będą uwzględniać ten obiekt. Plik LevelSolver.cs w przykładzie aparatu Unity zawiera więcej przykładowych zapytań.
Niebieskie pola pokazują wynik z trzech zapytań Place On Floor z regułami "z dala od pozycji kamery".
Porady:
- Podczas rozwiązywania problemów z lokalizacją wielu obiektów wymaganych w scenariuszu poziomu lub aplikacji należy najpierw rozwiązać niezbędne i duże obiekty, aby zmaksymalizować prawdopodobieństwo znalezienia miejsca.
- Kolejność umieszczania jest ważna. Jeśli nie można odnaleźć umieszczania obiektów, spróbuj wykonać mniej ograniczonych konfiguracji. Posiadanie zestawu konfiguracji rezerwowych ma kluczowe znaczenie dla obsługi funkcji w wielu konfiguracjach pomieszczeń.
Rzutowanie promieniami
Oprócz trzech podstawowych zapytań interfejs odlewu promieni może służyć do pobierania otagowanych typów powierzchni, a niestandardowa siatka playspace z hermetyzowaną wodą można skopiować po zeskanowaniu i sfinalizowaniu pomieszczenia etykiety są wewnętrznie generowane dla powierzchni, takich jak podłoga, sufit i ściany. Funkcja PlayspaceRaycast przyjmuje promienie i zwraca, jeśli promienie zderzają się ze znaną powierzchnią, a jeśli tak, informacje o tej powierzchni w postaci RaycastResult.
struct RaycastResult
{
enum SurfaceTypes
{
Invalid, // No intersection
Other,
Floor,
FloorLike, // Not part of the floor topology,
// but close to the floor and looks like the floor
Platform, // Horizontal platform between the ground and
// the ceiling
Ceiling,
WallExternal,
WallLike, // Not part of the external wall surface,
// but vertical surface that looks like a
// wall structure
};
SurfaceTypes SurfaceType;
float SurfaceArea; // Zero if unknown
// (i.e. if not part of the topology analysis)
DirectX::XMFLOAT3 IntersectPoint;
DirectX::XMFLOAT3 IntersectNormal;
};
Wewnętrznie raycast jest obliczany względem obliczonej reprezentacji 8cm sześcianu voxel przestrzeni playspace. Każdy voxel zawiera zestaw elementów powierzchni z przetworzonymi danymi topologii (nazywanymi również surfelami). Surfels zawarte w przeciętej komórce voxel są porównywane i najlepsze dopasowanie używane do wyszukiwania informacji o topologii. Te dane topologii zawierają etykiety zwrócone w postaci wyliczenia SurfaceTypes , a także powierzchni przeciętej.
W przykładzie aparatu Unity kursor rzutuje na każdą ramkę. Po pierwsze, przeciwko zderzaczom Unity; po drugie, w odniesieniu do reprezentacji świata modułu; i wreszcie, względem elementów interfejsu użytkownika. W tej aplikacji interfejs użytkownika otrzymuje priorytet, a następnie wynik zrozumienia, a na koniec zderzacze aparatu Unity. Typ SurfaceType jest zgłaszany jako tekst obok kursora.
Raycast wynik raportowania skrzyżowania z podłogą.
Uzyskiwanie kodu
Kod typu open source jest dostępny w zestawie MixedRealityToolkit. Poinformuj nas na forach deweloperów HoloLens , jeśli używasz kodu w projekcie. Nie możemy się doczekać, aby zobaczyć, co z tym zrobisz!
Informacje o autorze
![]() | Jeff Evertt jest liderem inżynierii oprogramowania, który od wczesnych dni pracował nad urządzeniem HoloLens, od inkubacji po rozwój. Przed HoloLens pracował nad konsolą Xbox Kinect i w branży gier na wielu różnych platformach i grach. Jeff jest pasjonatem robotyki, grafiki i rzeczy z błyskliwymi światłami, które idą sygnałem dźwiękowym. Lubi uczyć się nowych rzeczy i pracować nad oprogramowaniem, sprzętem, a zwłaszcza w przestrzeni, w której te dwie przecinają się. |