Esettanulmány – A tanulmány térbeli leképezési képességeinek HoloLens

Az első alkalmazás létrehozásakor a Microsoft HoloLens kíváncsiak voltak arra, hogy milyen messze lehet leküldni a térbeli leképezés határait az eszközön. Jeff Evertt, a Microsoft Studióval egy szoftvermérnök elmagyarázza, hogyan fejlesztettek ki egy új technológiát annak érdekében, hogy jobban szabályozható, hogyan kerülnek a hologramok a felhasználók valós környezetében.

Megjegyzés

HoloLens 2. implementál egy új Scene Understanding Runtime-t,amely strukturált, magas szintű környezetre vonatkozó ábrázolásokat biztosít az Mixed Reality-fejlesztők számára, hogy intuitív módon fejlesztsen a tudatos alkalmazásokhoz.

Videó megtekintése

A térbeli leképezésen túl

A Fragments és a Young Conker(a HoloLens két első játéka) során kiderült, hogy amikor a hologramok eljárási elhelyezését a fizikai világban végzünk, magasabb szintű ismeretekre volt szükségünk a felhasználó környezetével kapcsolatban. Minden játéknak saját elhelyezési igényei voltak: A töredékekben például meg kellett különböztetni a különböző felületeket – például a padlót vagy a táblázatot –, hogy a nyomokat a megfelelő helyeken helyezzük el. Emellett olyan felületeket is szeretnénk azonosítani, amelyeken életméretű holografikus karakterek, például egy dívány vagy egy fotel. Young Conkernél azt szerettük volna, ha Conker és az ő életfeltevései a játékos helyiségében megemelt tárgyakat használhatnak platformként.

Az Asobo Studióval,ezeknek a játékoknak a fejlesztői partnerével a probléma behatóan szembesült, és létrehozott egy olyan technológiát, amely kibővíti a játék térbeli leképezési HoloLens. Ezzel elemezhetnénk egy játékos helyiségét, és azonosíthatnánk a tárgyakat, például a falat, a táblákat, a padlót és az emeleteket. Arra is lehetőséget adott, hogy a holografikus objektumok optimális elhelyezésének meghatározásához optimalizáljuk a korlátozások készletét.

A spatial understanding kód

Az Asobo eredeti kódját használva létrehoztunk egy kódtárat, amely ezt a technológiát tartalmazza. A Microsoft és az Asobo már nyílt forráskódú kódot készített, és elérhetővé tette a MixedRealityToolkiten, hogy a saját projektjeiben is használva legyen. Minden 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++-megoldó kódja egy UWP-DLL-be van csomagolva, és elérhetővé lett téve a Unityben a MixedRealityToolkitfájlban található legördülő menüvel.

A Unity-mintában számos hasznos lekérdezés található, amelyek lehetővé teszik, hogy üres helyeket keressen a falon, objektumokat helyezzen a felső vagy a nagy terekre a padlóra, azonosítsa a elhelyezhető karaktereket, és számtalan egyéb térérthető lekérdezést.

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ája igényeinek, a térbeli megismerési modul úgy lett kialakítva, hogy két adott játék igényeit támogassa. Ennek megfelelően a megoldása egy adott folyamat és feltételezések köré épül:

  • Rögzített méretű playspace:A felhasználó megadja a playspace maximális méretét az init hívásban.
  • Egyszeres vizsgálati folyamat:A folyamathoz különálló vizsgálati fázisra van szükség, amelyben a felhasználó végigvezeti a felhasználót, és meghatározza a playspace-t. A lekérdezési függvények csak a vizsgálat véglegesített futtatása után fognak működni.
  • Felhasználó által vezérelt playspace "festmény":A vizsgálat fázisában a felhasználó a playspace-t áthelyezi és körbeolvassa, gyakorlatilag le is festményt ad a szükséges területekről. A létrehozott háló fontos ahhoz, hogy felhasználói visszajelzést nyújtson ebben a fázisban.
  • Beltéri otthoni vagy irodai környezet:A lekérdezési funkciók a sima felületek és a megfelelő szögben a fal köré vannak tervezve. Ez egy soft korlátozás. A vizsgálat fázisában azonban egy elsődleges tengelyelemzést is végre kell hajtottunk, hogy optimalizáljuk a hálószellellációt a fő- és kisebb tengely mentén.

Helyiség vizsgálatának folyamata

A térértés modul betöltésekor először be kell olvasnia a teret, hogy az összes használható felületet – például a padló, a felső határ és a fal – azonosítva és címkézze. A vizsgálati folyamat során megvizsgálja a helyiséget, és "meg kell"festődni" a vizsgálathoz érintett területeket.

Az ebben a fázisban látható háló fontos vizuális visszajelzés, amely tudatja a felhasználókkal, hogy a helyiség melyik részét ellenőrzik. A spatial understanding modul DLL-je belsőleg 8cm méretű voxel-kockák rácsaként tárolja a playspace-t. A vizsgálat kezdeti részében egy elsődleges összetevő-elemzésnek kell befejeződni a helyiség tengelyének meghatározásához. Belsőleg ezekhez a tengelyekhez igazítva tárolja a voxeles teret. A háló körülbelül másodpercenként jön létre az isosurface a voxel kötetből való kinyerével.

Térbeli leképezési háló fehérben és a playspace mesh zöld színnel való megértéséhez

Térbeli leképezési háló fehérben és a playspace mesh zöld színnel való megértéséhez

A mellékelt SpatialUnderstanding.cs fájl kezeli a vizsgálat fázisának folyamatát. A következő függvényeket hívja meg:

  • SpatialUnderstanding_Init:Egyszer hívható meg az elején.
  • GeneratePlayspace_InitScan:Azt jelzi, hogy a vizsgálati fázisnak el kell kezdődni.
  • GeneratePlayspace_UpdateScan_DynamicScan:Minden képkockát meghívott a vizsgálat folyamatának frissítéséhez. A kamera pozíciója és tájolása a (fent leírt) playspace festményi folyamathoz lesz használva.
  • GeneratePlayspace_RequestFinish:A meg van hívva a playspace véglegesít útjára. Ez a vizsgálati fázisban a "leeredő" területeket fogja használni a playspace meghatározásához és zároláshoz. Az alkalmazás lekérdezheti a statisztikákat a vizsgálat fázisában, valamint lekérdezheti az egyéni hálót a felhasználói visszajelzések biztosításához.
  • Import_UnderstandingMesh:A vizsgálat során a modul spatialUnderstandingCustomMesh viselkedése, amelyet a rendszer az előzetes hitelesítésre helyez, rendszeres időközönként lekérdezi a folyamat által létrehozott egyéni hálót. Ez a vizsgálat véglegesített véglegesített után még egyszer meg is történik.

A SpatialUnderstanding viselkedés által vezérelt beolvasási folyamat initScan-et hív meg, majd UpdateScan minden keretet. Ha a statisztikai lekérdezés ésszerű lefedettséget jelez, a felhasználó airtap használatával hívhatja meg a RequestFinish (Kérelem vége) adatokat, jelezve a vizsgálat fázisának végét. Az UpdateScan függvény addig lesz hívva, amíg a visszatérési értéke azt nem jelzi, hogy a DLL feldolgozása befejeződött.

A lekérdezések

A vizsgálat befejezése után három különböző típusú lekérdezést fog tudni elérni a felületen:

  • Topológiai lekérdezések:Ezek gyors lekérdezések, amelyek a beolvasott helyiség topológiája alapján épülnek fel.
  • Alakzatlekérdezések:Ezek a topológialekérdezések eredményeit felhasználva olyan vízszintes felületeket keresnek, amelyek megfelelnek az Ön által létrehozott egyéni alakzatoknak.
  • Objektumelhelyezéses lekérdezések:Ezek összetettebb lekérdezések, amelyek az objektumra vonatkozó szabályok és megkötések alapján találják meg a legmegfelelőbb helyet.

A három elsődleges lekérdezés mellett egy sugárcímzési felület is létezik, amely a címkézett felülettípusok lekérésére használható, és egy egyéni vízmentes helyiségháló is kimásolható.

Topológiai lekérdezések

A DLL-ben a topológiakezelő kezeli a környezet címkézését. Ahogy korábban említettük, az adatok nagy része egy voxel-kötetben található surfel-ökben van tárolva. Emellett a PlaySpaceInfos struktúra a playspace-ről tárol információkat, beleértve a világ igazítását (további részleteket alább), a padló és a felső határ magasságát.

A heurisztika a padló, a felső határ és a fal meghatározására használatos. A legnagyobb és legalacsonyabb vízszintes, 1 m2-esnél nagyobb felület tekinthető a padlónak. Vegye figyelembe, hogy ebben a folyamatban a kamera elérési útja is használatos a vizsgálat során.

A Topológiakezelő által elérhetővétett lekérdezések egy része a DLL-fájlon keresztül lesz elérhető. Az elérhető topológialekérdezések a következők:

  • QueryTopology_FindPositionsOnWalls
  • QueryTopology_FindLargePositionsOnWalls
  • QueryTopology_FindLargestWall
  • QueryTopology_FindPositionsOnFloor
  • QueryTopology_FindLargestPositionsOnFloor
  • QueryTopology_FindPositionsSittable

Minden lekérdezéshez a lekérdezés típusának megfelelő paraméterkészlet van meg. A következő példában a felhasználó megadja a kívánt kötet minimális magassági szélességét, a padló fölötti minimális elhelyezési magasságot és a kötet előtt található minimális & magasságot. Minden mérés fogyasztásmé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)

Ezen lekérdezések mindegyikéhez a TopologyResult struktúrák egy előre lefoglalt tömbje szükséges. A locationCount paraméter a megadott tömb hosszát határozza meg. A visszaadott érték a visszaadott helyek számát jelenti. Ez a szám soha nem nagyobb a megadott locationCount paraméternél.

A TopologyResult tartalmazza a visszaadott kötet középponti pozícióját, az irányt (azaz a normál irányt) és a megtalált tér méreteit.

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

Vegye figyelembe, hogy a Unity-mintában mindegyik lekérdezés egy gombra van csatolva a virtuális felhasználói felület panelén. A minta az egyes lekérdezések paramétereit ésszerű értékekre kódba kódja. További példákat a mintakód SpaceVisualizer.cs fájlban talál.

Alakzatlekérdezések

A DLL-ben az alakzatelemző (ShapeAnalyzer_W) a topológiaelemzőt használja a felhasználó által meghatározott egyéni alakzatokhoz való illeszkedéshez. A Unity-minta egy előre definiált alakzatkészletet tartalmaz, amelyek a lekérdezési menüben, az alakzat lapon jelennek meg.

Vegye figyelembe, hogy az alakzatelemzés csak vízszintes felületeken működik. A heverőt például a lapos helyfelület és a háta lapos teteje határozza meg. Az alakzatlekérdezés két adott méretű, magasságú és oldaltartományú felületet keres, a két felületet igazítva és csatlakoztatva. Az API-k terminológiáját használva a heverőhely és a háta is alakzatösszetevők, az igazítási követelmények pedig alakzatösszetevő-korlátozások.

A Unity-mintában (ShapeDefinition.cs) definiált példalekérdezés "sittable" objektumokhoz 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 alakzatlekérdezéseket alakzatösszetevők halmaza határozza meg, amelyek mindegyikét összetevőkre vonatkozó megkötések és alakzatmegkötések határozzák meg, amelyek az összetevők közötti függőségeket listázzák. Ez a példa három korlátozást tartalmaz egyetlen összetevő-definícióban, és nincsenek alakzatkorlátozások az összetevők között (mivel csak egy összetevő van).

Ezzel szemben a heverő alakzat két alakzatösszetevővel és négy alakzatkorlátozásokkal rendelkezik. Vegye figyelembe, hogy az összetevőket az indexük azonosítja a felhasználó összetevő-listájában (ebben a példában a 0 és az 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 biztosítanak az egyéni alakzatdefiníciók egyszerű létrehozásához. Az összetevő- és alakzatkorlátozások teljes listája a SpatialUnderstandingDll.cs fájlban, a ShapeComponentConstraint és a ShapeConstraint struktúrákban található.

A kék téglalap kiemeli a fotel alakú lekérdezés eredményeit.

A kék téglalap kiemeli a fotel alakú lekérdezés eredményeit.

Objektumelhelyezés-megoldó

Az objektumelhelyezés-lekérdezésekkel azonosíthatók az objektumok elhelyezésére ideális helyek a fizikai helyiségben. A megoldó megkeresi a legmegfelelőbb helyet az objektumszabályok és -megkötések alapján. Emellett az objektumlekérdezések mindaddig megmaradnak, amíg az objektumot Solver_RemoveObject vagy Solver_RemoveAllObjects el, ami lehetővé teszi a korlátozott többobjektumos elhelyezést.

Az objektumelhelyezés-lekérdezések három részből állnak: elhelyezési típus paraméterekkel, szabályok listájával és megkötések listájával. Lekérdezés futtatásához használja a következő 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, egy elhelyezési definíciót, valamint a szabályok és megkötések listáját veszi fel. A C#-burkolók olyan szerkezet-segítő függvényeket biztosítanak, amelyek megkönnyítik a szabályok és a megkötések szerkezetét. Az elhelyezési definíció tartalmazza a lekérdezés típusát, vagyis a következők egyikét:

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

Minden elhelyezési típushoz a típus egyedi paramétereinek halmaza van. Az ObjectPlacementDefinition struktúra statikus segítő függvények készletét tartalmazza ezen definíciók létrehozásához. Ha például olyan helyet keres, ahol egy objektumot a padlóra lehet tenni, használhatja a következő függvényt:

public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims)

Az elhelyezés típusa mellett szabályokat és korlátozásokat is meg lehet adni. A szabályokat nem lehet megsérteni. A típusnak és szabályoknak megfelelő lehetséges elhelyezési helyeket a rendszer ezután a megkötések 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ényekkel lehet létrehozni. Alább egy példát mutatunk be a szabályra és a megkötési konstrukcióra.

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, ahol egy félmérő típusú kocka egy felület szélére kerül, a többi korábban elhelyezési objektumtól távol, a helyiség közepéhez közel.

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

Sikeres művelet esetén a rendszer egy ObjectPlacementResult szerkezetet ad vissza, amely tartalmazza az elhelyezési pozíciót, a méreteket és a tájolást. Emellett az elhelyezés bekerül a DLL-fájl elhelyezve objektumok belső listájába. A további elhelyezési lekérdezések ezt az objektumot veszik figyelembe. A Unity-mintában található LevelSolver.cs fájl további példalekérdezéseket tartalmaz.

A kék mezőkben három Place On Floor lekérdezés eredménye van, amelyekben a

A kék mezőkben három Place On Floor lekérdezés eredménye van, amelyekben a "kamerapozíciótól távol" szabályok vonatkoznak.

Tippek:

  • Ha egy szinthez vagy alkalmazáshoz szükséges több objektum elhelyezését oldja meg, először oldja meg a tárgyakat és a nagy méretű objektumokat, hogy maximalizálja a hely helyének valószínűségét.
  • Az elhelyezés sorrendje fontos. Ha nem található objektumelhelyezés, próbálkozzon kevésbé korlátozott konfigurációval. A tartalék konfigurációk készlete kritikus fontosságú a funkciók támogatásában számos helyiségkonfigurációban.

Ray casting

A három elsődleges lekérdezés mellett egy sugáröntési felület is használható a címkézett felülettípusok lekérésére, és egy egyéni vízmentes playspace-háló is kimásolható a helyiség vizsgálata és véglegesített futtatása után. A címkék belsőleg jönnek létre olyan felületekhez, mint a padló, a felső határ és a fal. A PlayspaceRaycast függvény egy sugarat vesz fel, és visszaadja, hogy a sugár ütközik-e egy ismert felülettel, és ha igen, a felülettel kapcsolatos információkat egy RaycastResultformájában adja vissza.

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

Belsőleg a sugárképet a rendszer a playspace számított 8cm-es kockás voxel ábrázolása szerint számítja ki. Minden voxel több felületi elemet tartalmaz feldolgozott topológiaadatokkal (más néven surfel-ekkel). A rendszer összehasonlítja az interkected voxel cellában található felületeket, és a legjobb egyezést használja a topológiainformációk ki keressenek. Ezek a topológiai adatok a SurfaceTypes enum formájában visszaadott címkézést, valamint az interszektált felület felületét is tartalmazják.

A Unity-mintában a kurzor minden képkockát átképez. Először is, a Unity ütköztetőivel szemben; másodszor, a megértési modul világi ábrázolása ellen; és végül a felhasználói felület elemeihez. Ebben az alkalmazásban a felhasználói felület kap prioritást, majd az eredmények megértését, végül a Unity ütköztetőit. A SurfaceType szövegként van jelentve a kurzor mellett.

A Raycast eredményjelentési metszete a padlóval.

A Raycast eredményjelentési metszete a padlóval.

A kód letöltése

A nyílt forráskód a MixedRealityToolkit fájlban érhető el. Ha a kódot egy projektben használja HoloLens a fejlesztői fórumokon tudatja velünk. Már nem várjuk, hogy lássuk, mire használhatja.

A szerzőről

Jeff Evertt, a Microsoft vezető szoftvermérnöke Jeff Evertt egy szoftvermérnöki vezető, aki már a HoloLens óta dolgozik a cégen, az inkubációtól a fejlesztési tapasztalatig. Mielőtt HoloLens, az Xbox Kinect és a játékiparban dolgozott számos platformon és játékon. Jeff elkötelezett a robotika, a grafikák és a villámgyanús világítással kapcsolatos dolgokért. Szeret új dolgokat tanulni, szoftverekkel, hardverekkel dolgozni, és különösen abban a térben, ahol a két intersect.

Lásd még