Sdílet prostřednictvím


Prostorové mapování v Unity

Prostorové mapování umožňuje načíst trojúhelníkové sítě, které představují povrchy na světě kolem zařízení HoloLens. Data povrchu můžete použít k umístění, okluzi a analýze místnosti, abyste svým projektům Unity poskytli dodatečnou dávku ponořování.

Unity zahrnuje plnou podporu prostorového mapování, které je vystaveno vývojářům následujícími způsoby:

  1. Součásti prostorového mapování dostupné v sadě MixedRealityToolkit, které poskytují pohodlnou a rychlou cestu pro zahájení práce s prostorovým mapováním
  2. Rozhraní API prostorového mapování na nižší úrovni, která poskytují úplnou kontrolu a umožňují sofistikovanější přizpůsobení specifické pro aplikace

Pokud chcete v aplikaci použít prostorové mapování, je potřeba nastavit funkci SpatialPerception ve vašem AppxManifestu.

Podpora zařízení

Funkce HoloLens (první generace) HoloLens 2 Imerzivní náhlavní soupravy
Prostorové mapování ✔️ ✔️

Nastavení funkce SpatialPerception

Aby aplikace mohla využívat data prostorového mapování, musí být povolená funkce SpatialPerception.

Jak povolit funkci SpatialPerception:

  1. V Unity Editoru otevřete podokno Nastavení přehrávače (Upravit > přehrávač nastavení > projektu)
  2. Výběr na kartě Windows Store
  3. Rozbalte položku Nastavení publikování a v seznamu Možnosti zkontrolujte možnost SpatialPerception.

Poznámka:

Pokud jste projekt Unity už exportovali do řešení sady Visual Studio, budete muset buď exportovat do nové složky, nebo tuto funkci v sadě Visual Studio nastavit ručně.

Prostorové mapování také vyžaduje MaxVersionTested minimálně 10.0.10586.0:

  1. V sadě Visual Studio klikněte pravým tlačítkem na Package.appxmanifest v Průzkumník řešení a vyberte Zobrazit kód.
  2. Vyhledejte řádek určující TargetDeviceFamily a změňte MaxVersionTested="10.0.10240.0" na MaxVersionTested="10.0.10586.0"
  3. Uložte soubor Package.appxmanifest.

Přidání mapování v Unity

Systém prostorového povědomí

V MRTK se podívejte na úvodní příručku prostorového povědomí o nastavení různých pozorovatelů prostorových sítí.

Informace o pozorovatelích na zařízení najdete v průvodci konfigurací pozorovatelů sítě.

Informace o pozorovatelích pro pochopení scény najdete v průvodci pozorovatelem pro pochopení scény .

Analýza sítě vyšší úrovně: Spatial Understanding

Upozornění

Funkce Spatial Understanding je ve prospěch služby Scene Understanding zastaralá.

MixedRealityToolkit je kolekce kódu nástroje pro holografický vývoj založených na holografických rozhraních API Unity.

Prostorové porozumění

Při umísťování hologramů do fyzického světa je často žádoucí překročit prostorové mapování sítě a roviny povrchu. Když je umístění provedeno procedurálně, je žádoucí vyšší úroveň porozumění životnímu prostředí. To obvykle vyžaduje rozhodnutí o tom, co je podlaha, strop a stěny. K určení nejlepších fyzických umístění pro holografické objekty máte také možnost optimalizovat sadu omezení umístění.

Během vývoje Young Conker a Fragments, Asobo Studios čelí tomuto problému čelem vývojem řešitele místnosti. Každá z těchto her měla potřeby specifické pro hry, ale sdílela základní technologie prostorového porozumění. Knihovna HoloToolkit.SpatialUnderstanding zapouzdřuje tuto technologii, což vám umožní rychle najít prázdné prostory na stěnách, umístit objekty na strop, identifikovat postavu pro postavu sedět a řadu dalších dotazů prostorového porozumění.

Součástí je veškerý zdrojový kód, který vám umožní přizpůsobit ho vašim potřebám a sdílet vylepšení s komunitou. Kód řešitele jazyka C++ byl zabalen do knihovny DLL upW a vystavený Unity s poklesem v prefabu obsaženém v sadě MixedRealityToolkit.

Principy modulů

Modul vystavuje tři primární rozhraní: topologie pro jednoduché povrchové a prostorové dotazy, tvar pro detekci objektů a řešitel umístění objektů pro umístění objektů založené na omezeních sad objektů. Každá z těchto možností je popsaná níže. Kromě tří primárních rozhraní modulů lze použít rozhraní pro přetypování paprsků k načtení označených typů povrchu a vlastní síť playspace s vodou lze zkopírovat.

Ray Casting

Po dokončení skenování místnosti se štítky interně generují pro povrchy, jako je podlaha, strop a stěny. Funkce PlayspaceRaycast vezme paprsek a vrátí, pokud paprsek koliduje se známým povrchem, a pokud ano, informace o této ploše ve formě 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;
};

Interně se raycast počítá s vypočítanou 8 cm datovou krychlí voxel reprezentace playspace. Každý voxel obsahuje sadu povrchových prvků s zpracovanými daty topologie (neboli surfels). Surfely obsažené v protínané voxelové buňce jsou porovnány a nejlepší shoda použitá k vyhledání informací o topologii. Tato data topologie obsahují popisky vrácené ve formě výčtu SurfaceTypes a také povrchovou plochu protínaného povrchu.

V ukázce Unity kurzor přetypuje paprsek na každý snímek. Za prvé, proti kolidátorům Unity. Za druhé, proti světové reprezentaci modulu. A konečně, znovu prvky uživatelského rozhraní. V této aplikaci získá uživatelské rozhraní prioritu, další výsledek porozumění a nakonec kolidátory Unity. SurfaceType je hlášen jako text vedle kurzoru.

Typ povrchu je označený vedle kurzoru.
Typ povrchu je označený vedle kurzoru.

Dotazy topologie

Správce topologie v knihovně DLL zpracovává popisky prostředí. Jak je uvedeno výše, velká část dat je uložena v surfelech obsažených v svazku voxelu. Kromě toho se struktura "PlaySpaceInfos" používá k ukládání informací o playspace, včetně zarovnání světa (další podrobnosti o tomto níže), podlaha a výška stropu. Heuristika se používá k určení podlahy, stropu a stěn. Za podlahu se považuje například největší a nejnižší vodorovný povrch s plochou větší než 1 m2.

Poznámka:

V tomto procesu se také používá cesta kamery během procesu skenování.

Podmnožina dotazů vystavených správcem topologie je vystavena prostřednictvím knihovny DLL. Vystavené dotazy topologie jsou následující.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Každý z dotazů má sadu parametrů specifických pro typ dotazu. V následujícím příkladu určuje uživatel minimální výšku a šířku požadovaného objemu, minimální výšku umístění nad podlahou a minimální volný prostor před objemem. Všechna měření jsou v metrech.

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ždý z těchto dotazů přebírá předem přidělené pole struktur TopologyResult. Parametr locationCount určuje délku předaného pole. Vrácená hodnota hlásí počet vrácených umístění. Toto číslo není nikdy větší než předaný parametr "locationCount".

TopologyResult obsahuje středové umístění vráceného svazku, směr směru (tj. normální) a rozměry nalezeného prostoru.

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

Poznámka:

V ukázce Unity je každý z těchto dotazů propojený s tlačítkem na panelu virtuálního uživatelského rozhraní. Vzorek pevně kóduje parametry pro každý z těchto dotazů na přiměřené hodnoty. Další příklady najdete v SpaceVisualizer.cs v ukázkovém kódu.

Dotazy obrazců

V knihovně DLL analyzátor obrazců ("ShapeAnalyzer_W") používá analyzátor topologie ke shodě s vlastními obrazci definovanými uživatelem. Ukázka Unity definuje sadu obrazců a výsledky zveřejňuje prostřednictvím nabídky dotazu v aplikaci na kartě obrazce. Záměrem je, že uživatel může definovat vlastní dotazy na tvar objektu a využívat je podle potřeby aplikace.

Analýza obrazce funguje pouze na vodorovných plochách. Gauč je například definován plochou sedací plochou a plochou horní částí zadního gauče. Dotaz na obrazec hledá dva povrchy konkrétní velikosti, výšky a rozsahu stran se dvěma plochami zarovnanými a propojenými. Pomocí terminologie rozhraní API jsou sedadlo gauče a zadní část součástí obrazce a požadavky na zarovnání jsou omezení součástí obrazce.

Příklad dotazu definovaný v ukázce Unity (ShapeDefinition.cs) pro "sittable" objekty je následující.

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ždý dotaz obrazce je definován sadou součástí obrazce, každý se sadou omezení součástí a sadou omezení obrazců, které uvádějí závislosti mezi komponentami. Tento příklad zahrnuje tři omezení v definici jedné komponenty a žádná omezení obrazce mezi komponentami (protože existuje pouze jedna komponenta).

Naproti tomu obrazec gauče má dvě součásti obrazce a čtyři omezení obrazce. Komponenty jsou identifikovány jejich indexem v seznamu komponent uživatele (0 a 1 v tomto příkladu).

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),
};

Funkce obálky jsou k dispozici v modulu Unity pro snadné vytváření vlastních definic obrazců. Úplný seznam omezení součástí a obrazců najdete v části "SpatialUnderstandingDll.cs" v rámci struktur ShapeComponentConstraint a ShapeConstraint.

Na tomto povrchu se nachází tvar obdélníku.
Na tomto povrchu se nachází tvar obdélníku.

Řešitel umístění objektů

Řešitel umístění objektů lze použít k identifikaci ideálních umístění ve fyzické místnosti pro umístění objektů. Řešitel najde nejvhodnější umístění vzhledem k pravidlu a omezením objektů. Dotazy na objekt se navíc uchovávají, dokud se objekt neodebere pomocí volání "Solver_RemoveObject" nebo "Solver_RemoveAllObjects", což umožňuje omezené umístění více objektů. Dotazy na umístění objektů se skládají ze tří částí: typ umístění s parametry, seznam pravidel a seznam omezení. Ke spuštění dotazu použijte následující rozhraní 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)

Tato funkce přebírá název objektu, definici umístění a seznam pravidel a omezení. Obálky jazyka C# poskytují pomocné funkce konstrukce, které usnadňují vytváření pravidel a omezení. Definice umístění obsahuje typ dotazu – to znamená jednu z následujících možností.

public enum PlacementType
{
    Place_OnFloor,
    Place_OnWall,
    Place_OnCeiling,
    Place_OnShape,
    Place_OnEdge,
    Place_OnFloorAndCeiling,
    Place_RandomInAir,
    Place_InMidAir,
    Place_UnderFurnitureEdge,
};

Každý typ umístění má sadu parametrů jedinečných pro typ. Struktura ObjectPlacementDefinition obsahuje sadu statických pomocných funkcí pro vytváření těchto definic. Pokud chcete například najít místo pro umístění objektu do podlahy, můžete použít následující funkci. public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) Kromě typu umístění můžete zadat sadu pravidel a omezení. Pravidla nelze porušit. Možná umístění, která vyhovují typu a pravidlům, se pak optimalizují proti sadě omezení, aby bylo možné vybrat optimální umístění. Každou z pravidel a omezení může vytvořit poskytnutá statická funkce pro vytváření. Níže je uvedena ukázková funkce pravidla a konstrukce omezení.

public static ObjectPlacementRule Create_AwayFromPosition(
    Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
    Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)

Níže uvedený dotaz na umístění objektů hledá místo, kam umístit půlmetrové krychle na okraj povrchu, mimo jiné dříve umístit objekty a blízko středu místnosti.

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());

V případě úspěchu se vrátí struktura ObjectPlacementResult obsahující pozici umístění, rozměry a orientaci. Kromě toho je umístění přidáno do interního seznamu umístěných objektů knihovny DLL. Další dotazy na umísťování budou tento objekt brát v úvahu. Soubor "LevelSolver.cs" v ukázce Unity obsahuje další ukázkové dotazy.

Výsledky umístění objektů
Obrázek 3: Modrá pole, jak výsledek ze tří míst v dotazech na podlahu, které jsou mimo pravidla umístění kamery

Při řešení umístění více objektů požadovaných pro scénář úrovně nebo aplikace nejprve vyřešte nepostradatelné a velké objekty, aby se maximalizovala pravděpodobnost, že lze najít prostor. Pořadí umístění je důležité. Pokud nelze najít umístění objektů, zkuste méně omezené konfigurace. Sada náhradních konfigurací je důležitá pro podporu funkcí v mnoha konfiguracích místností.

Proces skenování místností

I když řešení prostorového mapování, které poskytuje HoloLens, je navržené tak, aby vyhovovalo potřebám celého gamutu problémových prostorů, byl modul prostorového porozumění vytvořen tak, aby podporoval potřeby dvou specifických her. Jeho řešení je strukturované kolem konkrétního procesu a sady předpokladů, které jsou shrnuty níže.

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 "malování" – Během fáze skenování se uživatel pohybuje a dívá se kolem přehrávání tempa, efektivně malovat oblasti, které by měly být zahrnuty. Vygenerovaná síť je důležitá k poskytnutí zpětné vazby uživatelů během této fáze. Vnitřní nastavení domácnosti nebo kanceláře – Funkce dotazů jsou navrženy kolem plochých ploch a stěn v pravých úhlech. Jedná se o měkké omezení. Během fáze skenování je však dokončena analýza primární osy pro optimalizaci tessellace sítě podél hlavní a vedlejší osy. Zahrnutý SpatialUnderstanding.cs soubor spravuje proces fáze skenování. Volá následující funkce.

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.

Tok skenování řízený chováním SpatialUnderstanding volá InitScan a pak UpdateScan každý rámec. Když statistika hlásí přiměřené pokrytí, uživatel může airtap volat RequestFinish, aby označil konec fáze skenování. UpdateScan se bude nadále volat, dokud jeho návratová hodnota indikuje, že knihovna DLL dokončila zpracování.

Principy sítě

Knihovna DLL interně ukládá playspace jako mřížku 8 cm velkých voxelových krychlí. Během počáteční části skenování je dokončena analýza primární komponenty k určení os místnosti. Interně ukládá prostor voxelu zarovnaný k těmto osám. Síť se generuje přibližně každou sekundu extrakcí isosurface ze svazku voxelu.

Vygenerovaná síť vytvořená ze svazku voxelu
Vygenerovaná síť vytvořená ze svazku voxelu

Řešení problému

  • Ujistěte se, že jste nastavili funkci SpatialPerception .
  • Při ztrátě sledování se při další události OnSurfaceChanged odeberou všechny sítě.

Spatial Mapping in Mixed Reality Toolkit

Další informace o používání prostorového mapování se sadou nástrojů Mixed Reality najdete v části věnované prostorovým povědomí v dokumentaci k MRTK.

Kontrolní bod dalšího vývoje

Pokud sledujete cestu vývoje Unity, kterou jsme vytvořili, jste uprostřed zkoumání základních stavebních bloků MRTK. Odtud můžete pokračovat k dalšímu stavebnímu bloku:

Nebo přejděte na možnosti platformy a rozhraní API hybridní reality:

Kdykoli se můžete vrátit k kontrolním bodům vývoje Unity.

Viz také