Mapowanie przestrzenne w aucie 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 Aparatu Unity dodatkową dawkę zanurzenia.
Aparat Unity zapewnia pełną obsługę mapowania przestrzennego, który jest udostępniany deweloperom w następujący sposób:
- Składniki mapowania przestrzennego dostępne w zestawie MixedRealityToolkit, które zapewniają wygodną i szybką ścieżkę do rozpoczęcia pracy z mapowaniem przestrzennym
- Interfejsy API mapowania przestrzennego niższego poziomu, które zapewniają pełną kontrolę i umożliwiają bardziej zaawansowane dostosowywanie specyficzne dla aplikacji
Aby można było używać mapowania przestrzennego w aplikacji, należy ustawić funkcję SpatialPerception w pliku AppxManifest.
Obsługa urządzeń
Funkcja | HoloLens (pierwsza generacja) | HoloLens 2 | Immersyjne zestawy nagłowne |
---|---|---|---|
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:
- W Edytorze aparatu Unity otwórz okienko "Ustawienia odtwarzacza" (Edytuj > odtwarzacz ustawień > projektu)
- Wybierz kartę "Sklep Windows"
- 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ż wartości MaxVersionTest co najmniej 10.0.10586.0:
- W programie Visual Studio kliknij prawym przyciskiem myszy plik Package.appxmanifest w Eksplorator rozwiązań i wybierz polecenie Wyświetl kod
- Znajdź wiersz określający element TargetDeviceFamily i zmień wartość MaxVersionTest="10.0.10240.0" na Wartość MaxVersionTest="10.0.10586.0"
- Zapisz plik Package.appxmanifest.
Jak dodać mapowanie w aucie 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 obserwatorów zrozumienia sceny, zapoznaj się z przewodnikiem obserwatora opis sceny.
Analiza siatki wyższego poziomu: Informacje przestrzenne
Uwaga
Usługa Spatial Understanding jest przestarzała na rzecz usługi Scene Understanding.
MixedRealityToolkit to kolekcja kodu narzędziowego do programowania holograficznego opartego na interfejsach API holograficznych aparatu Unity.
Opis przestrzenny
Podczas umieszczania hologramów w świecie fizycznym często pożądane jest przejście poza siatki i płaszczyzny powierzchni mapowania przestrzennego. Gdy umieszczanie odbywa się proceduralnie, pożądany jest wyższy poziom zrozumienia środowiska. Zwykle wymaga to podejmowania decyzji o tym, 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 holograficznych.
Podczas rozwoju Young Conker i Fragments, Asobo Studios stanęło w obliczu tego problemu, opracowując rozwiązanie pokoju. Każda z tych gier miała specyficzne dla gry potrzeby, ale dzieliły podstawową technologię zrozumienia przestrzennego. Biblioteka HoloToolkit.SpatialUnderstanding hermetyzuje tę technologię, umożliwiając szybkie znajdowanie pustych miejsc na ścianach, umieszczanie obiektów na suficie, identyfikowanie umieszczone do usiąść znaków i niezliczone inne zapytania rozumienia przestrzennego.
Dołączono cały kod źródłowy, dzięki czemu możesz dostosować go do własnych potrzeb i udostępnić ulepszenia społeczności. Kod modułu rozwiązywania języka C++ został opakowany w bibliotekę DLL platformy UWP i uwidoczniony w aplecie aparatu Unity ze spadkiem prefab zawartej w zestawie MixedRealityToolkit.
Opis 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 na potrzeby umieszczania na podstawie ograniczeń 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 promieni do pobierania oznakowanych typów powierzchni, a niestandardowa siatka przestrzeni playspace z wodoszczelną można skopiować.
Rzutowanie raya
Po zakończeniu skanowania pomieszczeń etykiety są generowane wewnętrznie 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 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ę powierzchni międzysected powierzchni.
W przykładzie aparatu Unity kursor rzutuje promienie na każdą ramkę. Po pierwsze, przeciwko zderzaczom Aparatu 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 zgłaszany jako tekst 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, większość danych jest przechowywana 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 uważana 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 uwidaczniony 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ść i szerokość żądanego woluminu, minimalną wysokość umieszczania nad podłogą i minimalną ilość prześwitu 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ę zwracanych lokalizacji. Liczba ta nigdy nie jest większa niż przekazana w parametrze "locationCount".
"TopologyResult" zawiera położenie środkowe zwróconej objętości, kierunek skierowany (tj. normalny) i 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ładowe twarde kody parametrów 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
W dll analizator kształtu ("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 zapytania w aplikacji na karcie kształtów. Celem jest to, że użytkownik może zdefiniować własne zapytania kształtu obiektu i korzystać z nich zgodnie z potrzebami aplikacji.
Analiza kształtu działa tylko na powierzchniach poziomych. Na przykład kanapa jest definiowana przez płaską powierzchnię siedzenia i płaską górną część kanapy. Zapytanie o kształt szuka dwóch powierzchni o określonym rozmiarze, wysokości i zakresie proporcji, z dwoma powierzchniami wyrównanymi i połączonymi. Korzystając z terminologii interfejsów API, kanapa i tylne siedzenie 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, każdy z zestawem ograniczeń składników i zestawem ograniczeń kształtu, które wyświetlają 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).
Natomiast kształt kanapy ma dwa składniki kształtu i cztery ograniczenia kształtu. 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, aby ułatwić tworzenie niestandardowych definicji kształtów. Pełną listę ograniczeń dotyczących składników i kształtów można znaleźć w strukturach "SpatialUnderstandingDll.cs" w strukturach "ShapeComponentConstraint" i "ShapeConstraint".
Kształt prostokąta znajduje się na tej powierzchni
Moduł rozwiązywania umieszczania obiektów
Narzędzie do 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ę, 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 pomocnika budowlanego, 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żesz 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 zoptymalizowane 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, w które umieścić pół metra sześcianu 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ę. 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ń.
Rysunek 3. Niebieskie pola wyników z trzech miejsc na zapytaniach podłogowych z dala od reguł położenia aparatu
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 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 zostało zaprojektowane tak, aby było wystarczająco ogólne, aby zaspokoić potrzeby całej gamy przestrzeni problemów, moduł rozumienia przestrzennego został skompilowany w celu obsługi potrzeb dwóch konkretnych gier. Jego rozwiązanie jest ustrukturyzowane w ramach 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.
"malowanie" oparte na użytkowniku — w fazie skanowania użytkownik porusza się i rozgląda się wokół tempa odtwarzania, skutecznie malując obszary, które należy uwzględnić. 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 miękkie ograniczenie. Jednak w fazie 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 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 ZaktualizujScan każdą ramkę. Gdy zapytanie statystyczne zgłasza uzasadnione pokrycie, użytkownik może nadawać nalot, aby wywołać metodę RequestFinish, aby wskazać koniec fazy skanowania. Funkcja UpdateScan będzie nadal wywoływana, dopóki jego wartość zwracana nie wskazuje, że biblioteka DLL zakończyła przetwarzanie.
Opis siatki
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 w przybliżeniu co sekundę przez wyodrębnienie izopochyń z objętości wokselu.
Wygenerowana siatka wytwarzana na podstawie objętości wokselu
Rozwiązywanie problemów
- Upewnij się, że ustawiono funkcję SpatialPerception
- Po utracie śledzenia następne zdarzenie OnSurfaceChanged spowoduje usunięcie wszystkich siatk.
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ę świadomość przestrzenną dokumentacji zestawu narzędzi MRTK.
Następny punkt kontrolny programowania
Jeśli śledzisz określoną podróż do opracowywania aparatu Unity, jesteś w środku 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 możliwości i interfejsów API platformy rzeczywistości mieszanej:
Zawsze możesz wrócić do punktów kontrolnych programowania aparatu Unity w dowolnym momencie.