Örnek olay inceleme - Uygulamanın uzamsal eşleme özelliklerini HoloLens

Microsoft HoloLens için ilk uygulamamızı oluştururken, cihaza uzamsal eşleme sınırlarını ne kadar ileri itmek için istekliydik. Microsoft Studios'ta yazılım mühendisi olan Jeff Evertt, hologramların kullanıcının gerçek dünya ortamına nasıl yerleştiril olduğu üzerinde daha fazla denetime ihtiyaçtan yeni bir teknolojinin nasıl geliştiril olduğunu anlatıyor.

Not

HoloLens 2, Karma Gerçeklik geliştiricilerine çevreye duyarlı uygulamalar için geliştirmeyi sezgisel hale getirirken tasarlanmış yapılandırılmış, üst düzey bir ortam gösterimi sağlayan yeni bir Scene Understanding Runtime'i uygulamaya almaktadır.

Videoyu izleme

Uzamsal eşlemenin ötesinde

HoloLens için ilk iki oyun olan Parçalar ve Young Conkerüzerinde çalışırken fiziksel dünyada hologramların yordamsal yerleşimini yaparken kullanıcının ortamı hakkında daha yüksek bir anlayış düzeyine ihtiyacımız olduğunu bulduk. Her oyunun kendine özgü yerleştirme ihtiyaçları vardı: Örneğin Parçalar'da, ilgili konumlara ipuçları vermek için zemin veya tablo gibi farklı yüzeyleri ayırt etmek istiyorduk. Ayrıca, yaşam boyutu holografik karakterlerin üzerine yer kaplaması mümkün olan yüzeyleri (örneğin, bir yer veya bir zemin) tanımlamak da istiyorduk. Young Conker'da Conker'in ve onun oyunlarının bir oyuncunun odasındaki yükseltilmiş yüzeyleri platform olarak kullanabiliyor olması istiyorduk.

Bu oyunlar için geliştirme iş ortağımız olan Asobo Studios,bu sorunla karşılaştı ve bu problemin uzamsal eşleme özelliklerini genişleten bir HoloLens. Bunu kullanarak bir oyuncunun odalarını analiz edebilir ve duvarları, tabloları, masaları, masaları ve zeminleri tanımlayabiliriz. Ayrıca holografik nesneler için en iyi yerleşimi belirlemek üzere bir kısıtlama kümesine karşı iyileştirme olanağı da sağlar.

Uzamsal anlama kodu

Asobo'nun özgün kodunu alıp bu teknolojiyi kapsüllerken bir kitaplık oluşturduk. Microsoft ve Asobo artık bu kodu açık kaynak olarak hazırlar ve karmarealityToolkit'te kendi projeleriniz için kullanabilirsiniz. Tüm kaynak kodu dahil edilir ve bu kodu ihtiyaçlarınıza göre özelleştirmenize ve geliştirmelerinizi toplulukla paylaşmanıza olanak sağlar. C++ çözücü kodu bir UWP DLL'sine sarmalanmış ve MixedRealityToolkitiçinde bulunan bir açılır liste ile Unity'ye açık.

Unity örneğinde yer alan ve duvarlarda boş alan bulmanıza, nesneleri tavana veya büyük alanlara yer vermene, karakterlerin bulunacak yerleri tanımlamanıza ve sayısız uzamsal anlama sorgusuna olanak sağlayan birçok yararlı sorgu vardır.

HoloLens tarafından sağlanan uzamsal eşleme çözümü, problem alanlarının tamamının ihtiyaçlarını karşılayacak kadar genel olacak şekilde tasarlanmıştır ancak uzamsal anlama modülü iki belirli oyunların ihtiyaçlarını destekleyecek şekilde tasarlanmıştır. Bu nedenle, çözümü belirli bir işlem ve varsayım kümesi çevresinde yapılandırılmıştır:

  • Sabit boyutlu playspace:Kullanıcı, init çağrısında en büyük playspace boyutunu belirtir.
  • Tek kullanımlık taramaişlemi: bu işlem, kullanıcının etrafında dolaşarak playspace'i tanımlayarak bir ayrık tarama aşaması gerektirir. Tarama son hale gelene kadar sorgu işlevleri çalışmaz.
  • Kullanıcı tarafından yönlendiren playspace "tablo": Tarama aşamasında kullanıcı hareket eder ve playspace'i inceler ve dahil edilecek alanları etkili bir şekilde boyamaya başlar. Oluşturulan örgü, bu aşamada kullanıcıya geri bildirim sağlamak için önemlidir.
  • İç mekan veya ofis ayarları:Sorgu işlevleri düz yüzeyler ve duvarlarda doğru açılarda tasarlanmıştır. Bu bir yazılım sınırlamasıdır. Ancak tarama aşamasında birincil eksen analizi tamamlanır ve büyük ve küçük eksenler boyunca örgülerin daha iyi hale getirmesi gerekir.

Oda Tarama Süreci

Uzamsal anlama modülünü yükleyemediniz mi ilk olarak alanınızı tarar, böylece zemin, tavan ve duvar gibi tüm kullanılabilir yüzeyler tanımlanır ve etiketlenebilir. Tarama işlemi sırasında odanıza bakar ve taramaya dahil edilecek alanları "boyar".

Bu aşamada görülen örgü, kullanıcıların odanın hangi bölümlerinin taranıyor olduğunu anlarını sağlayan önemli bir görsel geri bildirimtir. Uzamsal anlama modülünün DLL'si, playspace'i dahili olarak 8cm boyutlu vo cubes kılavuzu olarak depolar. Taramanın ilk bölümünde, oda eksenlerini belirlemek için birincil bileşen analizi tamamlanır. Dahili olarak, bu eksenlere hizalanmış vo eksen boşluklarını depolar. Her saniye yaklaşık olarak bir örgü oluşturulur ve i isosurface, vok hacimden ayıklanır.

Beyaz renkli uzamsal eşleme ağı ve yeşil renkli playspace mesh'i anlama

Beyaz renkli uzamsal eşleme ağı ve yeşil renkli playspace mesh'i anlama

Dahil edilen SpatialUnderstanding.cs dosyası tarama aşaması işlemini yönetir. Aşağıdaki işlevleri çağıran:

  • SpatialUnderstanding_Init:Başında bir kez çağrılır.
  • GeneratePlayspace_InitScan:Tarama aşamasının başlaması gerektiğini gösterir.
  • GeneratePlayspace_UpdateScan_DynamicScan:Tarama işlemini güncelleştirmek için her çerçeve çağrılır. Kamera konumu ve yönü geçirildi ve yukarıda açıklanan playspace tablo işlemi için kullanılır.
  • GeneratePlayspace_RequestFinish:Playspace'i sonleştirmek için çağrılır. Bu, playspace'i tanımlamak ve kilitlemek için tarama aşamasında "boyanmış" alanları kullanır. Uygulama, tarama aşamasında istatistikleri sorgulanın yanı sıra kullanıcı geri bildirimi sağlamak için özel ağı sorgular.
  • Import_UnderstandingMesh:Tarama sırasında modül tarafından sağlanan ve anlama prefab'sine yerleştirilen SpatialUnderstandingCustomMesh davranışı, işlem tarafından oluşturulan özel ağı düzenli aralıklarla sorgular. Buna ek olarak, tarama son hale getirildikten sonra bu bir kez daha yapılır.

SpatialUnderstanding davranışı tarafından yönlendiren tarama akışı InitScan'ıve ardından her kareyi UpdateScan olarak çağırıyor. İstatistik sorgusu makul kapsamı raporlayana kadar kullanıcı, tarama aşamasının sonunu belirtmek için RequestFinish çağrısı yapmak için airtap'i çağırabilirsiniz. UpdateScan, DLL'nin işlemeyi tamamlamış olduğunu gösterene kadar çağrılmaya devam eder.

Sorgular

Tarama tamamlandıktan sonra arabirimde üç farklı sorgu türüne erişebilirsiniz:

  • Topoloji sorguları:Bunlar taranan odanın topolojisi temel alan hızlı sorgulardır.
  • Sorguları şekillendirme:Bunlar, tanımladığınız özel şekillerle iyi bir eşleşme olan yatay yüzeyleri bulmak için topoloji sorgularının sonuçlarını kullanır.
  • Nesne yerleştirme sorguları:Bunlar, nesne için bir dizi kural ve kısıtlamaya göre en uygun konumu bulanan daha karmaşık sorgulardır.

Üç birincil sorguya ek olarak etiketli yüzey türlerini almak için kullanılmaktadır ve özel bir watertight oda ağı kopyalanır.

Topoloji sorguları

DLL içinde, topoloji yöneticisi ortamın etiketlemektedir. Yukarıda da belirtildiği gibi verilerin büyük bir miktarı, bir voksel birimi içinde yer alan yüzeylerin içinde depolanır. Buna ek olarak PlaySpaceInfos yapısı, dünya hizalaması (aşağıda daha fazla ayrıntı), zemin ve tavan yüksekliği dahil olmak üzere playspace hakkında bilgileri depolamak için kullanılır.

Zemin, tavan ve duvarları belirlemek için kullanılmaktadır. Örneğin, 1 m2'den büyük yüzey alanına sahip en büyük ve en düşük yatay yüzey zemin olarak kabul edilir. Tarama işlemi sırasında kamera yolunun da bu işlemde kullan olduğunu unutmayın.

Topoloji yöneticisi tarafından ortaya atlanan sorguların bir alt kümesi DLL aracılığıyla açığa çıkarılır. Ortaya çıkarıla topoloji sorguları aşağıdaki gibidir:

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

Sorguların her biri, sorgu türüne özgü bir parametre kümesine sahip. Aşağıdaki örnekte kullanıcı, istenen birimin en düşük yükseklik genişliğini, zeminin üzerindeki en düşük yerleştirme yüksekliğini ve birimin önündeki minimum boşluk & miktarını belirtir. Tüm ölçümler ölçümler içindedir.

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)

Bu sorguların her biri topolojiResult yapılarının önceden ayrılmış bir dizisini alır. locationCount parametresi geçirilen dizinin uzunluğunu belirtir. Dönüş değeri, döndürülen konum sayısını raporlar. Bu sayı hiçbir zaman geçirilen locationCount parametresinden büyük değil.

TopologyResult döndürülen birimin orta konumunu, yönü (normal) ve bulunan boşluğun boyutlarını içerir.

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

Unity örneğinde bu sorguların her biri, sanal kullanıcı arabirimi panelindeki bir düğmeye bağlıdır. Örnek, bu sorguların her biri için parametreleri makul değerlere sabit kodlar. Daha fazla örnek için örnek kodda SpaceVisualizer.cs'ye bakın.

Sorguları şekillendirme

DLL'nin içinde şekil çözümleyicisi (ShapeAnalyzer_W), kullanıcı tarafından tanımlanan özel şekillerle eşleşmek için topoloji çözümleyicisi kullanır. Unity örneğinde, şekil sekmesindeki sorgu menüsünde gösterilen önceden tanımlanmış bir şekil kümesi vardır.

Şekil analizinin yalnızca yatay yüzeylerde çalıştığını unutmayın. Örneğin bir yer, düz yer yüzeyi ve arka kısmında yer alan düz üst ile tanımlanır. Şekil sorgusu, belirli bir boyutta, yüksekliğe ve en boy aralığına sahip iki yüzeyin hizalı ve bağlı olduğu iki yüzeyin aramalarını sağlar. API'ler terminolojisi kullanılarak, couch seat ve back of the back of the couch şekil bileşenleridir ve hizalama gereksinimleri şekil bileşeni kısıtlamalarıdır.

"Sittable" nesneleri için Unity örneğinde tanımlanan örnek sorgu (ShapeDefinition.cs), aşağıdaki gibidir:

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

Her şekil sorgusu, her biri bir dizi bileşen kısıtlaması ve bileşenler arasındaki bağımlılıkları listeleye bir dizi şekil kısıtlaması ile bir dizi şekil bileşeni tarafından tanımlanır. Bu örnek, tek bir bileşen tanımında üç kısıtlama içerir ve bileşenler arasında şekil kısıtlaması yoktur (yalnızca bir bileşen olduğu için).

Buna karşılık, yer şekli iki şekil bileşenine ve dört şekil kısıtlamasına sahiptir. Bileşenlerin, kullanıcının bileşen listesinde (Bu örnekte 0 ve 1) dizin tarafından tanımlandığını unutmayın.

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

Sarmalayıcı işlevleri, özel şekil tanımlarının kolay oluşturulması için Unity modülünde sağlanır. Bileşen ve şekil kısıtlamalarının tam listesi, Shapecomponentconstraint ve Shapeconstraint yapıları Içindeki Spatialunderstandingdll. cs dosyasında bulunabilir.

Mavi dikdörtgen, sandalye şekil sorgusunun sonuçlarını vurgular.

Mavi dikdörtgen, sandalye şekil sorgusunun sonuçlarını vurgular.

Nesne yerleştirme çözücü

Nesne yerleştirme sorguları, nesnelerinizi yerleştirmek için fiziksel odadaki ideal konumları belirlemek için kullanılabilir. Çözücü, nesne kuralları ve kısıtlamaları verilen en uygun konumu bulur. Ayrıca nesne sorguları, nesne Solver_RemoveObject veya Solver_RemoveAllObjects çağrılarıyla kaldırılana kadar kalıcı hale gelene kadar, kısıtlanmış çok nesneli yerleştirme sağlar.

Nesne yerleştirme sorguları üç bölümden oluşur: parametrelere sahip yerleştirme türü, kuralların listesi ve kısıtlamaların listesi. Bir sorgu çalıştırmak için aşağıdaki API 'yi kullanın:

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)

Bu işlev bir nesne adı, yerleştirme tanımı ve kural ve kısıtlamaların bir listesini alır. C# sarmalayıcıları kural ve kısıtlama oluşturmayı kolay hale getirmek için oluşturma Yardımcısı işlevlerini sağlar. Yerleştirme tanımı sorgu türünü içerir — diğer bir deyişle, aşağıdakilerden biridir:

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

Yerleştirme türlerinin her biri, türü için benzersiz bir parametre kümesine sahiptir. Objectplacementdefinition yapısı, bu tanımları oluşturmak için bir statik yardımcı işlevler kümesi içerir. Örneğin, bir nesneyi kata yerleştirmek için bir yer bulmak için aşağıdaki işlevi kullanabilirsiniz:

public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims)

Yerleştirme türüne ek olarak, bir dizi kural ve kısıtlama sağlayabilirsiniz. Kurallar ihlal edilemez. Tür ve kuralları karşılayan olası yerleştirme konumları, en uygun yerleştirme konumunu seçmek için kısıtlamalar kümesine göre iyileştirilir. Kuralların ve kısıtlamaların her biri, belirtilen statik oluşturma işlevleri tarafından oluşturulabilir. Örnek bir kural ve kısıtlama oluşturma işlevi aşağıda verilmiştir.

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

Aşağıdaki nesne yerleştirme sorgusu, bir yarı ölçüm küpünü bir yüzey kenarına, daha önceki yerleştir nesnelerden uzağa ve odanın ortasına yakın bir yere yerleştirmenizi sağlar.

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

Başarılı olursa yerleştirme konumunu, boyutları ve yönlendirmeyi içeren bir Objectplacementresult yapısı döndürülür. Ayrıca, yerleştirme DLL 'nin yerleştirilmiş nesnelerin iç listesine eklenir. Sonraki yerleştirme sorguları, bu nesneyi hesaba götürür. Unity örneğindeki Levelçözücü. cs dosyası daha fazla örnek sorgu içerir.

Mavi kutular,

Mavi kutular, "kamera konumundan uzakta" kurallarından oluşan taban sorgularda yer alan üç yerden elde edilen sonucu gösterir.

İpuçları:

  • Bir düzey veya uygulama senaryosu için gereken birden çok nesnenin yerleştirme konumunu çözerken, bir alanın bulunabileceği olasılığını en üst düzeye çıkarmak için önce olmazdır ve büyük nesneleri çözün.
  • Yerleştirme sırası önemlidir. Nesne yerleşimi bulunamazsa, daha az kısıtlanmış yapılandırma deneyin. Bir dizi geri dönüş yapılandırması, birçok oda yapılandırmasında işlevselliği desteklemek için kritik öneme sahiptir.

Ray atama

Üç birincil sorguya ek olarak, etiketli yüzey türlerini almak için bir Ray atama arabirimi kullanılabilir ve oda tarandıktan ve sonlandırıldıktan sonra, Etiketler dahili, tavan ve duvarlar gibi yüzeyler için dahili olarak oluşturulur. Playspaceraycast işlevi bir Ray alır ve Ray bilinen bir yüzey ile çakışıyorsa ve bu durumda, bir rayyon sonucuolarak bu yüzey hakkında bilgi verir.

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

İç olarak, raycast, Playspace 'in hesaplanan 8cm tarafından yürütülen Voxel gösterimine göre hesaplanır. Her Voxel, işlenen topoloji verileriyle (surksel olarak da bilinir) bir yüzey öğeleri kümesi içerir. Kesişen Voxel hücresinde bulunan surflikler karşılaştırılır ve topoloji bilgilerini aramak için en iyi eşleşme kullanılır. Bu topoloji verileri, Surfacetype numaralandırması biçiminde döndürülen etiketlemenin yanı sıra kesişen yüzeyinin yüzey alanını içerir.

Unity örneğinde, imleç her karede bir ışın yayınlar. İlk olarak, Unity 'nin çakışmasındaki çarpışlara göre İkincisi, modülün dünya gösterimine göre; ve son olarak, Kullanıcı Arabirimi öğelerine karşı. Bu uygulamada, Kullanıcı arabirimi öncelik alır, daha sonra anlama sonucu ve son olarak Unity 'nin çakışmasına sahip olur. Surfacetype , imlecin yanında metin olarak bildirilir.

Raycast sonuç raporlaması taban ile kesişme.

Raycast sonuç raporlaması taban ile kesişme.

Kodu alma

Açık kaynak kodu Mixedrealitytoolkitiçinde kullanılabilir. kodu bir projede kullanıyorsanız, HoloLens geliştirici forumlarında bize bilgi verin. İle neler yapabileceğinizi görmek için bekleyemiyorum!

Yazar hakkında

Jeff, Microsoft 'ta Yazılım Mühendisliği lideri Jeff dratt , önceki günlerde bu yana HoloLens üzerinde çalışan bir yazılım mühendisliği lideridir ve bu tarihten itibaren geliştirme deneyimi sağlar. HoloLens önce, Xbox Kinect ve oyun sektöründe çok çeşitli platformlar ve oyunlar üzerinde çalıştık. Jeff, daha sonra bip ile başlayan ve parlak ışıkları ile birlikte Robotics, grafikler ve şeyler hakkında Pastır. Yeni şeyleri öğrenirken yazılım, donanım ve özellikle iki kesişmede yer alan alanda çalışmayı öğreniyor.

Ayrıca bkz.