Mapowanie przestrzenne w środowisku Unity

Mapowanie przestrzenne umożliwia pobieranie siatki trójkątów reprezentujących powierzchnie na całym świecie na urządzeniu HoloLens. Możesz użyć danych powierzchni do umieszczania, okluzji i analizy pomieszczeń, aby dać projektom Unity dodatkową dawkęmmersji.

Aparat Unity zapewnia pełną obsługę mapowania przestrzennego, który jest udostępniany deweloperom w następujący sposób:

  1. Składniki mapowania przestrzennego dostępne w zestawie MixedRealityToolkit, które zapewniają wygodną i szybką ścieżkę do rozpoczęcia pracy z mapowaniem przestrzennym
  2. Interfejsy API mapowania przestrzennego niższego poziomu, które zapewniają pełną kontrolę i umożliwiają bardziej zaawansowane dostosowywanie specyficzne dla aplikacji

Aby użyć mapowania przestrzennego w aplikacji, należy ustawić funkcję SpatialPerception w pliku AppxManifest.

Obsługa urządzeń

Cecha HoloLens (pierwsza generacja) HoloLens 2 Immersyjne zestawy słuchawkowe
Mapowanie przestrzenne ✔️ ✔️

Ustawianie możliwości SpatialPerception

Aby aplikacja używała danych mapowania przestrzennego, należy włączyć funkcję SpatialPerception.

Jak włączyć funkcję SpatialPerception:

  1. W Edytorze aparatu Unity otwórz okienko "Ustawienia odtwarzacza" (Edytuj > odtwarzacz ustawień > projektu)
  2. Wybierz kartę "Sklep Windows"
  3. Rozwiń pozycję "Ustawienia publikowania" i sprawdź możliwości "SpatialPerception" na liście "Możliwości"

Uwaga

Jeśli projekt aparatu Unity został już wyeksportowany do rozwiązania programu Visual Studio, musisz wyeksportować go do nowego folderu lub ręcznie ustawić tę funkcję w programie AppxManifest w programie Visual Studio.

Mapowanie przestrzenne wymaga również parametru MaxVersionTest co najmniej 10.0.10586.0:

  1. W programie Visual Studio kliknij prawym przyciskiem myszy plik Package.appxmanifest w Eksplorator rozwiązań i wybierz pozycję Wyświetl kod
  2. Znajdź wiersz określający element TargetDeviceFamily i zmień wartość MaxVersionTest="10.0.10240.0" na MaxVersionTest="10.0.10586.0".
  3. Zapisz plik Package.appxmanifest.

Jak dodać mapowanie w środowisku Unity

System rozpoznawania przestrzennego

W przewodniku MRTK zapoznaj się z przewodnikiem Wprowadzenie do rozpoznawania przestrzennego , aby uzyskać informacje na temat konfigurowania różnych obserwatorów siatki przestrzennej.

Aby uzyskać informacje na temat obserwatorów urządzeń, zapoznaj się z przewodnikiem Konfigurowanie obserwatorów siatki dla urządzeń .

Aby uzyskać informacje na temat obserwacji sceny, zapoznaj się z przewodnikiem obserwatora opis sceny .

Analiza siatki wyższego poziomu: Spatial Understanding

Przestroga

Usługa Spatial Understanding została wycofana na rzecz usługi Scene Understanding.

MixedRealityToolkit to kolekcja kodu narzędziowego do programowania holograficznego opartego na interfejsach API holograficznego aparatu Unity.

Opis przestrzenny

Podczas umieszczania hologramów w świecie fizycznym często pożądane jest, aby wykraczać poza siatkę i płaszczyzny powierzchni mapowania przestrzennego. Gdy umieszczanie odbywa się proceduralnie, pożądany jest wyższy poziom zrozumienia środowiska. Zwykle wymaga to podejmowania decyzji dotyczących tego, co to jest podłoga, sufit i ściany. Istnieje również możliwość optymalizacji pod kątem zestawu ograniczeń umieszczania w celu określenia najlepszych lokalizacji fizycznych dla obiektów holograficznego.

Podczas rozwoju Young Conker i Fragments, Asobo Studios stanął w obliczu tego problemu, rozwijając rozwiązanie pokoju. Każda z tych gier miała specyficzne dla gry potrzeby, ale współdzielili podstawową technologię zrozumienia przestrzennego. Biblioteka HoloToolkit.SpatialUnderstanding hermetyzuje tę technologię, umożliwiając szybkie znajdowanie pustych przestrzeni na ścianach, umieszczanie obiektów na suficie, identyfikowanie miejsca do siedzenia i mnóstwo innych zapytań interpretacji przestrzennych.

Cały kod źródłowy jest uwzględniony, co pozwala 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 ze spadkiem prefab zawartego w zestawie MixedRealityToolkit.

Omówienie modułów

Moduł udostępnia trzy podstawowe interfejsy: topologia dla prostych zapytań powierzchniowych i przestrzennych, kształt wykrywania obiektów oraz moduł rozwiązywania umieszczania obiektów w celu ograniczenia umieszczania zestawów obiektów. Każdy z nich jest opisany poniżej. Oprócz trzech podstawowych interfejsów modułów można użyć interfejsu rzutowania promieniowego do pobierania oznakowanych typów powierzchni i niestandardowej, szczelnej siatki playspace można skopiować.

Rzutowanie rayem

Po zakończeniu skanowania pomieszczeń etykiety są generowane wewnętrznie dla powierzchni, takich jak podłoga, sufit i ściany. Funkcja PlayspaceRaycast przyjmuje ray 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 8-cm sześcianu voxel przestrzeni playspace. Każdy voxel zawiera zestaw elementów powierzchni z przetworzonymi danymi topologii (aka surfels). Surfels zawarte w przecinanej komórce voxel jest porównywany i najlepsze dopasowanie używane do wyszukiwania informacji topologii. Te dane topologii zawierają etykiety zwrócone w postaci wyliczenia "SurfaceTypes", a także powierzchnię przecinanej powierzchni.

W przykładzie aparatu Unity kursor rzutuje promienie każdej ramki. Po pierwsze, przeciwko zderzaczom Unity. Po drugie, w odniesieniu do reprezentacji świata modułu. I wreszcie, ponownie elementy interfejsu użytkownika. W tej aplikacji interfejs użytkownika uzyskuje priorytet, następny wynik zrozumienia, a na koniec zderzacze aparatu Unity. Typ SurfaceType jest raportowany jako tekst obok kursora.

Typ powierzchni jest oznaczony obok kursora
Typ powierzchni jest oznaczony obok kursora

Zapytania topologii

W ramach biblioteki DLL menedżer topologii obsługuje etykietowanie środowiska. Jak wspomniano powyżej, wiele danych jest przechowywanych w surfelach, zawartych 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ę.

Uwaga

Ś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ż przekazana w parametrze "locationCount".

Element "TopologyResult" zawiera środkową pozycję zwróconego woluminu, kierunek skierowany (tj. normalny) oraz wymiary znalezionej przestrzeni.

struct TopologyResult
{
    DirectX::XMFLOAT3 position;
    DirectX::XMFLOAT3 normal;
    float width;
    float length;
};

Uwaga

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.

Kwerendy kształtu

W dll analizator kształtów ("ShapeAnalyzer_W") używa analizatora topologii do dopasowania do kształtów niestandardowych zdefiniowanych przez użytkownika. Przykład aparatu Unity definiuje zestaw kształtów i uwidacznia wyniki za pośrednictwem menu zapytań w aplikacji na karcie kształtów. Intencją jest to, że użytkownik może zdefiniować własne zapytania o kształty obiektu i korzystać z nich zgodnie z potrzebami aplikacji.

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, siedzenie kanapy i tył u góry 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 o kształt 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. Składniki są identyfikowane przez 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ń dotyczących składników i kształtów można znaleźć w plikach "SpatialUnderstandingDll.cs" w strukturach "ShapeComponentConstraint" i "ShapeConstraint".

Kształt prostokąta znajduje się na tej powierzchni
Kształt prostokąta znajduje się na tej powierzchni

Moduł rozwiązywania umieszczania obiektów

Moduł rozwiązywania umieszczania obiektów może służyć do identyfikowania idealnych lokalizacji w pomieszczeniu fizycznym w celu umieszczania obiektów. Moduł rozwiązywania znajdzie najlepszą lokalizację dopasowania, 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# udostępniają funkcje pomocnicze konstrukcji, aby ułatwić tworzenie reguł i ograniczeń. Definicja umieszczania zawiera typ zapytania — czyli jeden z poniższych.

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 statycznych funkcji pomocnika do tworzenia tych definicji. Aby na przykład znaleźć miejsce do umieszczenia obiektu na podłodze, można użyć następującej funkcji. publiczny statyczny obiektPlacementDefinition 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 optymalizowane pod kątem zestawu ograniczeń w celu wybrania optymalnej lokalizacji umieszczania. Każda z reguł i ograniczeń może zostać utworzona przez udostępnione funkcje tworzenia statycznego. Poniżej przedstawiono 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)

Poniższe zapytanie dotyczące umieszczania obiektów szuka miejsca do umieszczenia półmetrowego 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, wymiary i orientację umieszczania. Ponadto umieszczanie jest dodawane do wewnętrznej listy umieszczonych obiektó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ń.

Wyniki umieszczania obiektów
Rysunek 3. Niebieskie pola, jak wynik z trzech miejsc na podłodze zapytania z dala od reguł położenia aparatu

Podczas rozwiązywania problemów dotyczących umieszczania 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 użyć mniej ograniczonych konfiguracji. Posiadanie zestawu konfiguracji rezerwowych ma kluczowe znaczenie dla obsługi funkcji w wielu konfiguracjach pomieszczeń.

Proces skanowania pomieszczeń

Chociaż rozwiązanie do mapowania przestrzennego dostarczone przez urządzenie HoloLens ma być wystarczająco ogólne, aby zaspokoić potrzeby całej gamy przestrzeni problemów, moduł zrozumienia przestrzennego został utworzony w celu obsługi potrzeb dwóch konkretnych gier. Jego rozwiązanie jest ustrukturyzowane wokół określonego procesu i zestawu założeń, podsumowane poniżej.

Fixed size playspace – The user specifies the maximum playspace size in the init call.

One-time scan process –
    The process requires a discrete scanning phase where the user walks around,
    defining the playspace.
    Query functions will not function until after the scan has been finalized.

User driven playspace "obraz" — podczas fazy skanowania użytkownik porusza się i patrzy wokół tempa 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. Dołączony plik SpatialUnderstanding.cs zarządza procesem fazy skanowania. Wywołuje ona następujące funkcje.

SpatialUnderstanding_Init – Called once at the start.

GeneratePlayspace_InitScan – Indicates that the scan phase should begin.

GeneratePlayspace_UpdateScan_DynamicScan –
    Called each frame to update the scanning process. The camera position and
    orientation is passed in and is used for the playspace painting process,
    described above.

GeneratePlayspace_RequestFinish –
    Called to finalize the playspace. This will use the areas “painted” during
    the scan phase to define and lock the playspace. The application can query
    statistics during the scanning phase as well as query the custom mesh for
    providing user feedback.

Import_UnderstandingMesh –
    During scanning, the “SpatialUnderstandingCustomMesh” behavior provided by
    the module and placed on the understanding prefab will periodically query the
    custom mesh generated by the process. In addition, this is done once more
    after scanning has been finalized.

Przepływ skanowania sterowany zachowaniem "SpatialUnderstanding" wywołuje metodę InitScan, a następnie zaktualizuj każdą ramkę. Gdy zapytanie statystyczne zgłasza uzasadnione pokrycie, użytkownik może wywołać metodę RequestFinish, aby wskazać koniec fazy skanowania. Funkcja UpdateScan będzie nadal wywoływana, dopóki jej wartość zwracana nie wskazuje, że biblioteka DLL zakończyła przetwarzanie.

Informacje o siatce

Biblioteka dll wewnętrznie przechowuje przestrzeń odtwarzania jako siatkę 8 cm wielkości modułów voxel. 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.

Wygenerowana siatka utworzona na podstawie objętości voxel
Wygenerowana siatka utworzona na podstawie objętości voxel

Rozwiązywanie problemów

  • Upewnij się, że ustawiono funkcję SpatialPerception
  • Po utracie śledzenia następne zdarzenie OnSurfaceChanged usunie wszystkie siatki.

Mapowanie przestrzenne w zestawie narzędzi Mixed Reality Toolkit

Aby uzyskać więcej informacji na temat używania mapowania przestrzennego z zestawem narzędzi Mixed Reality Toolkit, zobacz sekcję rozpoznawania przestrzennego dokumentacji zestawu narzędzi MRTK.

Następny punkt kontrolny programowania

Jeśli śledzisz określoną przez nas podróż dewelopera aparatu Unity, jesteś w trakcie eksplorowania podstawowych bloków konstrukcyjnych zestawu narzędzi MRTK. W tym miejscu możesz przejść do następnego bloku konstrukcyjnego:

Możesz też przejść do Mixed Reality możliwości platformy i interfejsów API:

Zawsze możesz wrócić do punktów kontrolnych tworzenia aparatu Unity w dowolnym momencie.

Zobacz też