Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Met ruimtelijke toewijzing kunt u driehoeksnetten ophalen die de oppervlakken in de wereld rond een HoloLens-apparaat vertegenwoordigen. U kunt surface-gegevens gebruiken voor plaatsing, occlusie en ruimteanalyse om uw Unity-projecten een extra dosis onderdompeling te geven.
Unity biedt volledige ondersteuning voor ruimtelijke toewijzing, die op de volgende manieren beschikbaar is voor ontwikkelaars:
- Onderdelen voor ruimtelijke toewijzing die beschikbaar zijn in de MixedRealityToolkit, die een handig en snel pad bieden om aan de slag te gaan met ruimtelijke toewijzing
- API's voor ruimtelijke toewijzing op lager niveau, die volledige controle bieden en geavanceerdere toepassingsspecifieke aanpassingen mogelijk maken
Als u ruimtelijke toewijzing in uw app wilt gebruiken, moet de mogelijkheid SpatialPerception worden ingesteld in uw AppxManifest.
Apparaatondersteuning
| Functie | HoloLens (eerste generatie) | HoloLens 2 | Meeslepende headsets |
|---|---|---|---|
| Ruimtelijke toewijzing | ✔️ | ✔️ | ❌ |
De mogelijkheid SpatialPerception instellen
Als u wilt dat een app ruimtelijke toewijzingsgegevens gebruikt, moet de mogelijkheid SpatialPerception zijn ingeschakeld.
De functie SpatialPerception inschakelen:
- Open in de Unity-Editor het deelvenster 'Spelerinstellingen' (Projectinstellingen > bewerken > Player)
- Selecteer op het tabblad Windows Store
- Vouw 'Publicatie-instellingen' uit en controleer de mogelijkheid 'SpatialPerception' in de lijst 'Mogelijkheden'
Opmerking
Als u uw Unity-project al hebt geëxporteerd naar een Visual Studio-oplossing, moet u exporteren naar een nieuwe map of deze mogelijkheid handmatig instellen in AppxManifest in Visual Studio.
Voor ruimtelijke toewijzing is ook een MaxVersionTested van ten minste 10.0.10586.0 vereist:
- Klik in Visual Studio met de rechtermuisknop op Package.appxmanifest in de Solution Explorer en selecteer Code weergeven
- Zoek de regel die TargetDeviceFamily specificeert en wijzig MaxVersionTested="10.0.10240.0" in MaxVersionTested="10.0.10586.0"
- Sla package.appxmanifest op.
Toewijzing toevoegen in Unity
Ruimtelijk bewustzijnssysteem
Bekijk in MRTK de handleiding Aan de slag met ruimtelijk bewustzijn voor informatie over het instellen van verschillende ruimtelijke mesh-waarnemers.
Raadpleeg de handleiding Mesh-waarnemers configureren voor apparaten voor informatie over waarnemers op het apparaat.
Raadpleeg de gids Scène begrijpen waarnemers voor informatie over scènes.
Mesh-analyse op hoger niveau: ruimtelijk inzicht
Voorzichtigheid
Spatial Understanding is afgeschaft ten gunste van Scene Understanding.
De MixedRealityToolkit is een verzameling hulpprogrammacode voor holografische ontwikkeling die is gebouwd op de holografische API's van Unity.
Ruimtelijk inzicht
Bij het plaatsen van hologrammen in de fysieke wereld is het vaak wenselijk om verder te gaan dan de mesh- en oppervlaktevlakken van ruimtelijke toewijzingen. Wanneer plaatsing procedureel wordt uitgevoerd, is een hoger niveau van milieu-begrip wenselijk. Dit vereist meestal het nemen van beslissingen over wat vloer, plafond en wanden zijn. U hebt ook de mogelijkheid om te optimaliseren tegen een reeks plaatsingsbeperkingen om de beste fysieke locaties voor holografische objecten te bepalen.
Tijdens de ontwikkeling van Young Conker en Fragments werd Asobo Studios geconfronteerd met dit probleem door een room solver te ontwikkelen. Elk van deze games had spelspecifieke behoeften, maar ze deelden kerntechnologie voor ruimtelijk inzicht. De HoloToolkit.SpatialUnderstanding-bibliotheek omvat deze technologie, zodat u snel lege ruimtes op de wanden kunt vinden, objecten op het plafond kunt plaatsen, kunt identificeren waar het karakter moet zitten en een groot aantal andere query's op het gebied van ruimtelijk inzicht.
Alle broncode is opgenomen, zodat u deze kunt aanpassen aan uw behoeften en uw verbeteringen kunt delen met de community. De code voor de C++-oplosser is verpakt in een UWP-dll en blootgesteld aan Unity met een drop-in-prefab in de MixedRealityToolkit.
Informatie over modules
Er zijn drie primaire interfaces beschikbaar in de module: topologie voor eenvoudige surface- en ruimtelijke query's, shape voor objectdetectie en de oplosser voor objectplaatsing voor het plaatsen van objecten op basis van beperkingen van objectsets. Elk van deze wordt hieronder beschreven. Naast de drie primaire module-interfaces kan een ray casting-interface worden gebruikt om getagde oppervlaktetypen op te halen en kan een aangepast waterdicht speelruimtegaas worden gekopieerd.
Ray Casting
Nadat de ruimtescan is voltooid, worden er intern labels gegenereerd voor oppervlakken zoals de vloer, het plafond en de wanden. De PlayspaceRaycast functie neemt een straal en retourneert als de straal botst met een bekend oppervlak en zo ja, informatie over dat oppervlak in de vorm van een 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 wordt de raycast berekend op basis van de berekende 8-cm kubusvormige voxelweergave van de playspace. Elke voxel bevat een set oppervlakte-elementen met verwerkte topologiegegevens (ook wel surfels genoemd). De surfels in de doorsneden voxelcel worden vergeleken en de beste overeenkomst wordt gebruikt om de topologiegegevens op te zoeken. Deze topologiegegevens bevatten de labeling die wordt geretourneerd in de vorm van de opsomming 'SurfaceTypes', evenals de oppervlakte van het doorsneden oppervlak.
In het Unity-voorbeeld werpt de cursor elk frame een ray. Ten eerste tegen de colliers van Unity. Ten tweede, tegen de wereldweergave van de understanding-module. En ten slotte, nogmaals ui-elementen. In deze toepassing krijgt de gebruikersinterface prioriteit, naast het begrijpende resultaat en ten slotte de colliders van Unity. Het SurfaceType wordt gerapporteerd als tekst naast de cursor.
Surface-type wordt gelabeld naast de cursor
Topologiequery's
In het DLL-bestand verwerkt de topologiebeheerder het labelen van de omgeving. Zoals hierboven vermeld, worden veel van de gegevens opgeslagen in surfels, die zich in een voxel-volume bevinden. Daarnaast wordt de structuur 'PlaySpaceInfos' gebruikt om informatie over de speelruimte op te slaan, waaronder de werelduitlijning (meer informatie hierover hieronder), de vloer en de hoogte van het plafond. Heuristieken worden gebruikt voor het bepalen van de vloer, het plafond en de wanden. Het grootste en laagste horizontale oppervlak met een oppervlakte van meer dan 1 m2 wordt bijvoorbeeld beschouwd als de vloer.
Opmerking
Het camerapad tijdens het scanproces wordt ook gebruikt in dit proces.
Een subset van de query's die door topologiebeheer worden weergegeven, wordt weergegeven via het dll-bestand. De weergegeven topologiequery's zijn als volgt.
QueryTopology_FindPositionsOnWalls
QueryTopology_FindLargePositionsOnWalls
QueryTopology_FindLargestWall
QueryTopology_FindPositionsOnFloor
QueryTopology_FindLargestPositionsOnFloor
QueryTopology_FindPositionsSittable
Elk van de query's heeft een set parameters die specifiek zijn voor het querytype. In het volgende voorbeeld geeft de gebruiker de minimale hoogte & breedte van het gewenste volume, de minimale plaatsingshoogte boven de vloer en de minimale ruimte vóór het volume op. Alle metingen zijn in meters.
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)
Voor elk van deze query's wordt een vooraf toegewezen matrix met 'TopologyResult'-structuren gebruikt. De parameter locationCount geeft de lengte van de doorgegeven matrix op. De retourwaarde geeft het aantal geretourneerde locaties weer. Dit getal is nooit groter dan de parameter locationCount.
De "TopologyResult" bevat de centrale positie van het geretourneerde volume, de richting naar toe (d.w.v. normaal) en de afmetingen van de gevonden ruimte.
struct TopologyResult
{
DirectX::XMFLOAT3 position;
DirectX::XMFLOAT3 normal;
float width;
float length;
};
Opmerking
In het Unity-voorbeeld is elk van deze query's gekoppeld aan een knop in het deelvenster van de virtuele gebruikersinterface. De voorbeeldcode codeert de parameters voor elk van deze query's tot redelijke waarden. Zie SpaceVisualizer.cs in de voorbeeldcode voor meer voorbeelden.
Shapequery's
In de dll gebruikt de shape analyzer ('ShapeAnalyzer_W') de topologieanalyse om te vergelijken met aangepaste shapes die door de gebruiker zijn gedefinieerd. Het Unity-voorbeeld definieert een set shapes en geeft de resultaten weer via het querymenu in de app, op het tabblad Shape. Het is de bedoeling dat de gebruiker zijn eigen objectshapequery's kan definiëren en deze kan gebruiken, indien nodig voor de toepassing.
De vormanalyse werkt alleen op horizontale oppervlakken. Een bank wordt bijvoorbeeld gedefinieerd door het platte zitvlak en de platte bovenkant van de rugleuning van de bank. De shapequery zoekt naar twee oppervlakken met een specifieke grootte, hoogte en hoogtebereik, waarbij de twee oppervlakken zijn uitgelijnd en verbonden. Volgens de TERMINOLOGIE van de API's zijn de bankzitting en de rugleuning onderdelen van de vorm en zijn de uitlijningsvereisten beperkingen van shapeonderdelen.
Een voorbeeldquery die is gedefinieerd in het Unity-voorbeeld (ShapeDefinition.cs), voor 'sittable'-objecten is als volgt.
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);
Elke shapequery wordt gedefinieerd door een set shapeonderdelen, elk met een set onderdeelbeperkingen en een set shapebeperkingen die afhankelijkheden tussen de onderdelen vermelden. Dit voorbeeld bevat drie beperkingen in één onderdeeldefinitie en geen shapebeperkingen tussen onderdelen (omdat er slechts één onderdeel is).
De vorm van de bank heeft daarentegen twee shapeonderdelen en vier vormbeperkingen. Onderdelen worden geïdentificeerd door hun index in de lijst met onderdelen van de gebruiker (0 en 1 in dit voorbeeld).
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),
};
Wrapper-functies zijn beschikbaar in de Unity-module voor het eenvoudig maken van aangepaste vormdefinities. De volledige lijst met beperkingen voor onderdelen en shapes vindt u in 'SpatialUnderstandingDll.cs' in de structuren ShapeComponentConstraint en ShapeConstraint.
Rechthoekshape is te vinden op dit oppervlak
Oplosser voor objectplaatsing
De oplosser voor objectplaatsing kan worden gebruikt om ideale locaties in de fysieke ruimte te identificeren om uw objecten te plaatsen. De oplosser vindt de meest geschikte locatie op basis van de objectregels en beperkingen. Bovendien blijven objectquery's behouden totdat het object wordt verwijderd met aanroepen 'Solver_RemoveObject' of 'Solver_RemoveAllObjects', waardoor beperkte plaatsing van meerdere objecten mogelijk is. Plaatsingsquery's voor objecten bestaan uit drie onderdelen: plaatsingstype met parameters, een lijst met regels en een lijst met beperkingen. Gebruik de volgende API om een query uit te voeren.
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)
Deze functie gebruikt een objectnaam, een plaatsingsdefinitie en een lijst met regels en beperkingen. De C#-wrappers bieden bouwhulpfuncties om het bouwen van regels en beperkingen eenvoudig te maken. De plaatsingsdefinitie bevat het querytype, een van de volgende.
public enum PlacementType
{
Place_OnFloor,
Place_OnWall,
Place_OnCeiling,
Place_OnShape,
Place_OnEdge,
Place_OnFloorAndCeiling,
Place_RandomInAir,
Place_InMidAir,
Place_UnderFurnitureEdge,
};
Elk van de plaatsingstypen heeft een set parameters die uniek zijn voor het type. De structuur ObjectPlacementDefinition bevat een set statische helperfuncties voor het maken van deze definities. Als u bijvoorbeeld een plaats wilt zoeken om een object op de vloer te plaatsen, kunt u de volgende functie gebruiken. public static ObjectPlacementDefinition Create_OnFloor(Vector3 halfDims) Naast het plaatsingstype kunt u een set regels en beperkingen opgeven. Regels kunnen niet worden overtreden. Mogelijke plaatsingslocaties die voldoen aan het type en de regels, worden vervolgens geoptimaliseerd op basis van de set beperkingen om de optimale plaatsingslocatie te selecteren. Elk van de regels en beperkingen kan worden gemaakt door de opgegeven functies voor statisch maken. Hieronder vindt u een voorbeeld van de constructiefunctie voor regels en beperkingen.
public static ObjectPlacementRule Create_AwayFromPosition(
Vector3 position, float minDistance)
public static ObjectPlacementConstraint Create_NearPoint(
Vector3 position, float minDistance = 0.0f, float maxDistance = 0.0f)
De onderstaande objectplaatsingsquery is op zoek naar een plek om een kubus van een halve meter op de rand van een oppervlak te plaatsen, weg van andere eerder geplaatste objecten en in de buurt van het midden van de ruimte.
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());
Als dit lukt, wordt een 'ObjectPlacementResult'-structuur geretourneerd die de plaatsingspositie, afmetingen en afdrukstand bevat. Bovendien wordt de plaatsing toegevoegd aan de interne lijst met geplaatste objecten van de dll. Volgende plaatsingsquery's houden rekening met dit object. Het bestand 'LevelSolver.cs' in het Unity-voorbeeld bevat meer voorbeeldquery's.
Afbeelding 3: De blauwe vakken hoe het resultaat van drie plaatsen op vloerquery's met afstand van camerapositieregels
Bij het oplossen van de plaatsingslocatie van meerdere objecten die vereist zijn voor een niveau of toepassingsscenario, lost u eerst noodzakelijke en grote objecten op om de kans te maximaliseren dat een ruimte kan worden gevonden. Plaatsingsvolgorde is belangrijk. Als objectplaatsingen niet kunnen worden gevonden, probeert u minder beperkte configuraties. Het hebben van een set terugvalconfiguraties is essentieel voor het ondersteunen van de functionaliteit in veel ruimteconfiguraties.
Ruimtescanproces
Hoewel de oplossing voor ruimtelijke toewijzing van de HoloLens zo is ontworpen dat deze algemeen genoeg is om te voldoen aan de behoeften van het hele scala aan probleemruimten, is de module ruimtelijk inzicht gebouwd om de behoeften van twee specifieke games te ondersteunen. De oplossing is gestructureerd rond een specifiek proces en een set veronderstellingen, die hieronder worden samengevat.
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.
Door de gebruiker gestuurde speelruimte "schilderen" - Tijdens de scanfase beweegt de gebruiker en kijkt rond het speeltempo, waardoor de gebieden effectief worden geschilderd, die moeten worden opgenomen. De gegenereerde mesh is belangrijk om gebruikersfeedback te geven tijdens deze fase. Thuis of op kantoor instellen: de queryfuncties zijn ontworpen rond platte oppervlakken en wanden in rechte hoeken. Dit is een zachte beperking. Tijdens de scanfase wordt echter een analyse van de primaire as voltooid om de netssseling langs de primaire en secundaire as te optimaliseren. Het inbegrepen SpatialUnderstanding.cs-bestand beheert het scanfaseproces. De volgende functies worden aangeroepen.
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.
De scanstroom, die wordt aangestuurd door het gedrag 'SpatialUnderstanding' roept InitScan aan en vervolgens UpdateScan elk frame. Wanneer de statistische query redelijke dekking rapporteert, mag de gebruiker airtap om RequestFinish aan te roepen om het einde van de scanfase aan te geven. UpdateScan blijft aangeroepen totdat de retourwaarde aangeeft dat de dll-verwerking is voltooid.
Inzicht in Mesh
De begrijpende dll slaat de playspace intern op als een raster van voxel-kubussen van 8 cm. Tijdens het eerste deel van het scannen wordt een analyse van het primaire onderdeel voltooid om de assen van de ruimte te bepalen. Intern slaat het de voxel-ruimte op die is uitgelijnd op deze assen. Ongeveer elke seconde wordt een mesh gegenereerd door het isosurface uit het voxel-volume te extraheren.
Gegenereerde mesh geproduceerd op het voxel-volume
Problemen oplossen
- Zorg ervoor dat u de mogelijkheid SpatialPerception hebt ingesteld
- Wanneer het bijhouden verloren gaat, worden met de volgende OnSurfaceChanged-gebeurtenis alle meshes verwijderd.
Ruimtelijke toewijzing in Mixed Reality Toolkit
Zie de sectie ruimtelijk bewustzijn van de MRTK-documenten voor meer informatie over het gebruik van ruimtelijke toewijzing met Mixed Reality Toolkit.
Volgend controlepunt voor ontwikkeling
Als u het Unity-ontwikkelingstraject volgt dat we hebben uitgetekend, bent u bezig met het verkennen van de basisbouwstenen van MRTK. Vanaf hier kunt u doorgaan naar de volgende bouwsteen:
Of ga naar Mixed Reality platformmogelijkheden en API's:
U kunt altijd op elk gewenst moment teruggaan naar de unity-ontwikkelingscontrolepunten .