Megosztás a következőn keresztül:


Térbeli leképezés a Unityben

A térbeli leképezés lehetővé teszi a HoloLens-eszköz körüli világfelületeket ábrázoló háromszöghálók lekérését. A felületi adatokat elhelyezésre, elzáródásra és helyiségelemzésre használhatja, hogy a Unity-projektek további mértékű bemerítést biztosítsanak.

A Unity teljes körű támogatást nyújt a térbeli leképezéshez, amelyet a fejlesztők az alábbi módokon érhetnek el:

  1. A MixedRealityToolkitben elérhető térbeli leképezési összetevők, amelyek kényelmes és gyors utat biztosítanak a térbeli leképezés használatának megkezdéséhez
  2. Alacsonyabb szintű térbeli leképezési API-k, amelyek teljes körű vezérlést biztosítanak, és kifinomultabb alkalmazásspecifikus testreszabást tesznek lehetővé

A térbeli leképezés alkalmazásbeli használatához be kell állítani a SpatialPerception képességet az AppxManifestben.

Eszköztámogatás

Szolgáltatás HoloLens (első gen) HoloLens 2 Modern fejhallgatók
Térbeli leképezés ✔️ ✔️

A SpatialPerception képesség beállítása

Ahhoz, hogy egy alkalmazás térbeli leképezési adatokat használhasson fel, engedélyezni kell a SpatialPerception képességet.

A SpatialPerception funkció engedélyezése:

  1. A Unity-szerkesztőben nyissa meg a "Lejátszó beállításai" panelt (Project Settings > Player szerkesztése>)
  2. Kiválasztás a "Windows Áruház" lapon
  3. Bontsa ki a "Közzétételi beállítások" elemet, és ellenőrizze a "SpatialPerception" képességet a "Képességek" listában

Feljegyzés

Ha már exportálta a Unity-projektet egy Visual Studio-megoldásba, vagy exportálnia kell egy új mappába, vagy manuálisan kell beállítania ezt a képességet a Visual Studióban található AppxManifestben.

A térbeli leképezéshez legalább 10.0.10586.0 MaxVersionTested is szükséges:

  1. A Visual Studióban kattintson a jobb gombbal a Package.appxmanifest elemre a Megoldáskezelő, és válassza a Kód megtekintése lehetőséget
  2. Keresse meg a TargetDeviceFamily értéket megjelölő sort, és módosítsa a MaxVersionTested="10.0.10240.0" értéket MaxVersionTested="10.0.10586.0" értékre.
  3. Mentse a Package.appxmanifest fájlt.

Leképezés hozzáadása a Unityben

Térbeli tudatossági rendszer

Az MRTK-ban tekintse meg a térbeli tudatosság első lépéseit ismertető útmutatót, amely a különböző térbeli hálós megfigyelők beállításával kapcsolatos információkat tartalmazza.

Az eszköz megfigyelőivel kapcsolatos információkért tekintse meg a hálófigyelők eszközre való konfigurálását ismertető útmutatót.

A megfigyelőket megértő jelenetekkel kapcsolatos információkért tekintse meg a Jelenet megértése megfigyelői útmutatót.

Magasabb szintű hálóelemzés: Térbeli megértés

Figyelemfelhívás

A térbeli megértés elavult a Jelenetfelismerés javára.

A MixedRealityToolkit a Unity holografikus API-jára épülő holografikus fejlesztéshez használható segédprogramkód gyűjteménye.

Térbeli megértés

Amikor hologramokat helyez el a fizikai világban, gyakran kívánatos túllépni a térbeli leképezés háló- és felületsíkjain. Ha az elhelyezést eljárási módon végzik el, a környezettudatosság magasabb szintje szükséges. Ehhez általában döntéseket kell hozni arról, hogy mi a padló, a mennyezet és a falak. Emellett számos elhelyezési korlátozással optimalizálhatja a holografikus objektumok legjobb fizikai helyét.

A Young Conker és a Fragments fejlesztése során az Asobo Studios szembesült ezzel a problémával egy szobamegoldó fejlesztésével. Mindegyik játéknak játékspecifikus igényei voltak, de megosztották az alapvető térbeli megértési technológiát. A HoloToolkit.SpatialUnderstanding könyvtár magában foglalja ezt a technológiát, lehetővé téve, hogy gyorsan megtalálja a falak üres tereit, tárgyakat helyezzen a mennyezetre, azonosítsa a karakterek elhelyezésére szolgáló helyet, és számtalan egyéb térbeli megértési lekérdezést.

Az összes forráskód megtalálható benne, így testre szabhatja az igényeinek megfelelően, és megoszthatja a fejlesztéseket a közösséggel. A C++ solver kódját egy UWP dll-be burkolták, és a Unity számára elérhetővé tették egy, a MixedRealityToolkitben található előfab cseppeléssel.

Modulok ismertetése

A modul három elsődleges felületet fed le: az egyszerű felületi és térbeli lekérdezések topológiáját, az objektumészleléshez használható alakzatot, valamint az objektumkészletek kényszeralapú elhelyezésére szolgáló objektumelhelyezési solvert. Ezeket az alábbiakban ismertetjük. A három elsődleges modul interfészen kívül egy sugáröntvény interfész is használható a címkézett felülettípusok lekéréséhez, és egy egyéni, vízmentes játéktérháló is kimásolható.

Ray Casting

A helyiség vizsgálatának befejezése után a címkék belsőleg jönnek létre olyan felületekhez, mint a padló, a mennyezet és a falak. A PlayspaceRaycast függvény egy sugarat vesz fel, és visszaadja, ha a sugár egy ismert felülettel ütközik, és ha igen, az adott felületre vonatkozó információk egy 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;
};

A raycast belsőleg a playspace számított 8 cm-nyi kockás voxel-ábrázolása alapján lesz kiszámítva. Minden voxel több felületi elemet tartalmaz feldolgozott topológiai adatokkal (más néven szörfösökkel). A metszetben lévő voxel cellában található surfeleket összehasonlítjuk, és a topológia adatainak kereséséhez a legjobb egyezést használjuk. Ezek a topológiaadatok tartalmazzák a "SurfaceTypes" enumerálás formájában visszaadott címkézést, valamint a metszett felület felületét.

A Unity-mintában a kurzor minden képkockán egy-egy sugarat vet. Először is, Unity ütközői ellen. Másodszor, a megértési modul világábrázolása ellen. Végül pedig ismét felhasználói felületi elemeket. Ebben az alkalmazásban a felhasználói felület prioritást kap, a megértési eredmény, végül pedig a Unity ütközői. A SurfaceType a kurzor melletti szövegként van jelentve.

A Surface-típus a kurzor mellett van címkézve
A Surface-típus a kurzor mellett van címkézve

Topológia-lekérdezések

A DLL-ben a topológiakezelő kezeli a környezet címkézését. Ahogy fentebb említettük, az adatok nagy része a surfelekben van tárolva, amelyek egy voxel köteten belül találhatók. Ezen kívül a "PlaySpaceInfos" szerkezet a játéktérre vonatkozó információk tárolására szolgál, beleértve a világ igazítását (további részletek az alábbiakban), a padlót és a mennyezet magasságát. A heurisztika a padló, a mennyezet és a falak meghatározására szolgál. Az 1 m2-nél nagyobb felületű legnagyobb és legalacsonyabb vízszintes felület például a padló.

Feljegyzés

Ebben a folyamatban a vizsgálati folyamat során a kamera elérési útja is használható.

A Topológia-kezelő által közzétett lekérdezések egy részhalmaza a dll-ben jelenik meg. A közzétett topológia-lekérdezések a következők.

QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable

Mindegyik lekérdezés paraméterkészlettel rendelkezik, amelyek a lekérdezés típusára vonatkoznak. A következő példában a felhasználó megadja a kívánt kötet minimális magasságát és szélességét, a padló feletti minimális elhelyezési magasságot és a kötet előtti minimális térközt. Minden mérés mérőben van.

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)

Ezek a lekérdezések a "TopologyResult" struktúrák előre lefoglalt tömbjéhez tartoznak. A "locationCount" paraméter az átadott tömb hosszát adja meg. A visszatérési érték a visszaadott helyek számát jelenti. Ez a szám soha nem nagyobb, mint a "locationCount" paraméterben megadott érték.

A "TopologyResult" tartalmazza a visszaadott kötet középhelyzetét, az irányt (azaz a normált) és a talált tér méreteit.

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

Feljegyzés

A Unity-mintában ezek a lekérdezések a virtuális felhasználói felület paneljének egy gombjához vannak csatolva. A mintául szolgáló kemény kód az egyes lekérdezések paramétereit ésszerű értékekre kódozza. További példákért lásd a mintakód SpaceVisualizer.cs.

Alakzat-lekérdezések

A dll-ben az alakzatelemző ("ShapeAnalyzer_W") a topológiaelemzővel egyezik a felhasználó által definiált egyéni alakzatokkal. A Unity-minta alakzatokat határoz meg, és az eredményeket az alkalmazáson belüli lekérdezési menüben, az alakzatok lapján teszi közzé. A cél az, hogy a felhasználó saját objektumalakzat-lekérdezéseket definiáljon, és az alkalmazásnak megfelelően használja őket.

Az alakzatelemzés csak vízszintes felületeken működik. A kanapét például a sík ülésfelület és a kanapé hátlapja határozza meg. Az alakzat lekérdezése két, adott méretű, magasságú és mérettartományú felületet keres, a két felület egymáshoz igazítva és csatlakoztatva van. Az API-k terminológiájának használatával a kanapé ülése és a hátlap alakzatösszetevők, az igazítási követelmények pedig az alakzatösszetevők korlátozásai.

A Unity-mintában (ShapeDefinition.cs) definiált példa lekérdezés a "sittable" objektumok esetében a következő.

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

Az egyes alakzat-lekérdezéseket alakzatösszetevők halmaza határozza meg, amelyek mindegyike összetevő-kényszerekkel és az összetevők közötti függőségeket felsoroló alakzatkényszerekkel rendelkezik. Ez a példa három kényszert tartalmaz egyetlen összetevő definíciójában, és nincsenek alakzatkényszerek az összetevők között (mivel csak egy összetevő van).

Ezzel szemben a kanapé alakzat két alakzatösszetevőt és négy alakzatkényszert tartalmaz. Az összetevőket az indexük azonosítja a felhasználó összetevőlistájában (ebben a példában 0 és 1).

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

A Burkoló függvények a Unity modulban érhetők el az egyéni alakzatdefiníciók egyszerű létrehozásához. Az összetevő- és alakzatkorlátozások teljes listája a "SpatialUnderstandingDll.cs" alatt található az "ShapeComponentConstraint" és a "ShapeConstraint" struktúrákban.

Téglalap alakzat található ezen a felületen
Téglalap alakzat található ezen a felületen

Objektumelhelyezési solver

Az objektumelhelyezési solver segítségével azonosíthatók a fizikai helyiség ideális helyei az objektumok elhelyezéséhez. A solver megtalálja az objektumszabályok és megkötések alapján a legjobban illeszkedő helyet. Emellett az objektum-lekérdezések mindaddig megmaradnak, amíg el nem távolítják az objektumot "Solver_RemoveObject" vagy "Solver_RemoveAllObjects" hívásokkal, ami lehetővé teszi a korlátozott többobjektumos elhelyezést. Az objektumelhelyezési lekérdezések három részből állnak: elhelyezési típus paraméterekkel, szabályok listája és kényszerek listája. Lekérdezés futtatásához használja az alábbi API-t.

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)

Ez a függvény egy objektumnevet, elhelyezési definíciót, valamint a szabályok és korlátozások listáját tartalmazza. A C#-burkolók építési segédfunkciókat biztosítanak a szabály- és kényszerépítés megkönnyítéséhez. Az elhelyezés definíciója tartalmazza a lekérdezés típusát, vagyis az alábbiak egyikét.

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

Az elhelyezési típusok mindegyike egyedi paraméterkészlettel rendelkezik. Az "ObjectPlacementDefinition" struktúra statikus segédfüggvényeket tartalmaz a definíciók létrehozásához. Ha például egy objektumot a padlóra szeretne helyezni, az alábbi függvényt használhatja. public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) Az elhelyezés típusán kívül számos szabályt és korlátozást is megadhat. A szabályok nem sérthetők meg. A típusnak és szabályoknak megfelelő lehetséges elhelyezési helyeket a rendszer a kényszerek alapján optimalizálja az optimális elhelyezési hely kiválasztásához. Az egyes szabályokat és korlátozásokat a megadott statikus létrehozási függvények hozhatják létre. Az alábbiakban egy példaszabályt és kényszer-építési függvényt talál.

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

Az alábbi objektumelhelyezési lekérdezés egy olyan helyet keres, ahová egy félméteres kockát helyezhet a felület szélére, távol a többi korábban elhelyezett objektumtól és a helyiség középpontjának közelében.

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

Ha sikeres, a rendszer visszaad egy "ObjectPlacementResult" struktúrát, amely tartalmazza az elhelyezési pozíciót, a dimenziókat és a tájolást. Emellett az elhelyezés hozzáadódik a DLL által az elhelyezett objektumok belső listájához. A későbbi elhelyezési lekérdezések figyelembe veszik ezt az objektumot. A Unity-mintában található "LevelSolver.cs" fájl további példákat tartalmaz.

Az objektum elhelyezésének eredményei
3. ábra: A kék dobozok, hogy az eredmény a padlón három helyről lekérdezi a kamera helyzetének szabályaitól távol

Egy szinthez vagy alkalmazáshoz szükséges több objektum elhelyezésének megoldásakor először oldja meg a nélkülözhetetlen és nagy objektumokat annak érdekében, hogy a lehető legnagyobb valószínűséggel találhasson helyet. Az elhelyezési sorrend fontos. Ha az objektumelhelyezések nem találhatók, próbálkozzon kevésbé korlátozott konfigurációkkal. A tartalék konfigurációk készlete kritikus fontosságú a funkciók számos helyiségkonfigurációban való támogatásához.

Helyiségvizsgálati folyamat

Bár a HoloLens által biztosított térbeli leképezési megoldás úgy lett kialakítva, hogy elég általános legyen ahhoz, hogy megfeleljen a problématerek teljes skálájának igényeinek, a térbeli megértési modul két konkrét játék igényeinek kielégítésére készült. A megoldás egy konkrét folyamat és feltételezések köré épül, az alábbiakban összefoglalva.

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.

Felhasználó által hajtott játéktér "festés" – A vizsgálati fázisban a felhasználó mozog, és körülnéz a lejátszási ütemben, hatékonyan festi a területeket, amelyeket tartalmaznia kell. A létrehozott háló fontos, hogy felhasználói visszajelzést adjon ebben a fázisban. Beltéri otthoni vagy irodai beállítás – A lekérdezési függvények sík felületek és falak köré vannak tervezve, derékszögben. Ez egy puha korlátozás. A vizsgálati fázis során azonban az elsődleges tengely elemzése befejeződött a fő- és altengely mentén történő hálóelválasztás optimalizálásához. A mellékelt SpatialUnderstanding.cs fájl kezeli a vizsgálati fázis folyamatát. A következő függvényeket hívja meg.

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.

A "SpatialUnderstanding" viselkedés által hajtott vizsgálati folyamat meghívja az InitScant, majd frissíti az egyes kereteket. Amikor a statisztikai lekérdezés ésszerű lefedettséget jelez, a felhasználónak lehetősége van arra, hogy a RequestFinish hívásával jelezze a vizsgálati fázis végét. Az UpdateScan hívása mindaddig folytatódik, amíg a visszatérési érték azt nem jelzi, hogy a dll feldolgozása befejeződött.

A Mesh ismertetése

A értelmező dll belsőleg 8 cm méretű voxel kockák rácsaként tárolja a playspace-t. A vizsgálat kezdeti szakaszában egy elsődleges összetevő elemzése fejeződik be a helyiség tengelyeinek meghatározásához. Belsőleg ezekhez a tengelyekhez igazítva tárolja a voxel térközét. A háló körülbelül másodpercenként jön létre az ioszurface kinyerésével a voxel kötetből.

A voxel kötetből előállított háló
A voxel kötetből előállított háló

Hibaelhárítás

  • Győződjön meg arról, hogy beállította a SpatialPerception képességet
  • Ha a nyomon követés elveszik, a következő OnSurfaceChanged esemény eltávolítja az összes hálót.

Térbeli leképezés a Vegyes valóság eszközkészletben

A térbeli leképezés vegyes valóság eszközkészlettel való használatáról az MRTK-dokumentáció térbeli tudatossági szakaszában olvashat bővebben.

Következő fejlesztési ellenőrzőpont

Ha a Unity fejlesztési útját követi, akkor az MRTK alapvető építőelemeinek felfedezése közben jár. Innen továbbléphet a következő építőelemre:

Vagy ugorjon a Mixed Reality platform képességeire és API-ira:

Bármikor visszatérhet a Unity fejlesztési ellenőrzőpontjaihoz .

Lásd még