Hola !
HoloToolkit posee 2 herramientas que nos permiten realizar un un scaneo de nuestros alrededores cuando usamos Hololens.
- Spatial Mapping
- Spatial Understanding
Spatial Mapping es el asset que usamos por defecto y es el que nos permite tener un control básico del proceso de scan que realiza Hololens. Por ejemplo, una vez que agregamos este elemento y habilitamos el dibujo del Mesh, podemos ver en tiempo real el scan que hace Hololens del entorno donde la estamos utilizando.
Spatial Understanding nos permite ir un paso más allá y realizar algunas tareas más complejas. Por ejemplo:
- Definir el momento de inicio y fin para el proceso de scan. Esto es realmente útil cuando por ejemplo, necesitamos realizar un scan inicial y luego sabemos que el contexto de trabajo no cambiará. Si deshabilitamos el scan en tiempo real, le damos más recursos a Hololens para utilizar en otras cosas
- Realizar consultas simples sobre diferentes elementos en nuestro punto de vista. Por ejemplo, para buscar superficies planas en una pared o en el piso para posicionar hologramas.
- Realizar consultas más complejas, para buscar elementos como una silla, una guitarra, etc. A esta opción no la he utilizado pero la tengo en reserva para cuando la necesite.
Importante: siempre que utilizamos Spatial Understanding, debemos tener agregado el prefab de Spatial Mapping, en caso contrario veremos unos errores muy divertidos.
Personalmente creo que las 2 mejores formas de conocer como funciona Spatial Understanding son las siguientes
- Leer el artículo de Jeff Evertt Case study – Expanding the spatial mapping capabilities of HoloLens, donde comenta como han creado este asset para escenarios específicos que no se contemplaban en HoloToolkit.
- Revisar la Scene de ejemplo ubicada en “HoloToolkit-Unity/Assets/HoloToolkit-Examples/SpatialUnderstanding/SpatialUnderstanding-FeatureOverview/Scenes/“.
La misma utiliza Spatial Understanding para realizar un scan inicial del ambiente y luego presentar algunas opciones de consultas simples.
Si además lo quieres utilizar en un proyecto propio, el siguiente pequeño paso a paso puede ayudarte. El resultado final es una app que muestra en tiempo real un HUD con el estado del scan y al finalizar deshabilita la visualización del Mesh.
Estos son los pasos a seguir.
- Create a 3D project in Unity3D
- Import HoloToolkit package
- Configure project to
- Support HoloLens projects (UWP, VR, etc)
- enable Spatial Mapping feature
- Clean Scene elements
- Add
- Hololens Camera
- Cursor With Feedback
- Input Manager
- Spatial Mapping
- Spatial Understanding
- FPS Display
- Add Empty element
- Rename to CodeManagers
- Add new C# Script named “GameStartScanner.cs”
El proyecto debe quedar similar al siguiente
El código completo del ejemplo se puede descargar desde aquí (link).
Y el script para la nueva clase está debajo, y lo mejor es revisar un par de apuntes interesantes sobre la misma
- Las propiedades MinAreaForComplete , MinHorizAreaForComplete, MinWallAreaForComplete definen el mínimo de área a escanear para dar el proceso cómo válido
- En el Start() se inicia el proceso de Scan con la operación SpatialUnderstanding.Instance.RequestBeginScanning(); y además nos suscribimos a los cambios de estado
- La propiedad DoesScanMeetMinBarForCompletion es la que se encarga de validar si se ha terminado el proceso de scan
- En el Update se realizan 2 operaciones imporantes
- Se muestra en un FPS Text el estado del proceso de scan
- Si el se ha encontrado el minimo de elementos, finalizamos el proceso de scan, y deshabilitamos el proceso visual de scan
Código de ejemplo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using HoloToolkit.Unity; | |
using HoloToolkit.Unity.SpatialMapping; | |
using UnityEngine; | |
using UnityEngine.UI; | |
public class GameStartScanner : MonoBehaviour | |
{ | |
public float MinAreaForComplete = 30.0f; | |
public float MinHorizAreaForComplete = 20.0f; | |
public float MinWallAreaForComplete = 5.0f; | |
private bool _scanComplete = false; | |
public TextMesh DebugDisplay; | |
void Start() | |
{ | |
SpatialUnderstanding.Instance.ScanStateChanged += Instance_ScanStateChanged; | |
SpatialUnderstanding.Instance.RequestBeginScanning(); | |
} | |
private void Instance_ScanStateChanged() | |
{ | |
if ((SpatialUnderstanding.Instance.ScanState == SpatialUnderstanding.ScanStates.Done) | |
&& SpatialUnderstanding.Instance.AllowSpatialUnderstanding) | |
{ | |
_scanComplete = true; | |
} | |
} | |
void Update() | |
{ | |
if (DebugDisplay != null) | |
DebugDisplay.text = PrimaryText; | |
if (_scanComplete || !DoesScanMeetMinBarForCompletion) return; | |
SpatialUnderstanding.Instance.RequestFinishScan(); | |
_scanComplete = true; | |
// hide mesh | |
var customMesh = SpatialUnderstanding.Instance.GetComponent<SpatialUnderstandingCustomMesh>(); | |
customMesh.DrawProcessedMesh = false; | |
SpatialMappingManager.Instance.DrawVisualMeshes = false; | |
} | |
public string PrimaryText | |
{ | |
get | |
{ | |
// Scan state | |
if (SpatialUnderstanding.Instance.AllowSpatialUnderstanding) | |
{ | |
switch (SpatialUnderstanding.Instance.ScanState) | |
{ | |
case SpatialUnderstanding.ScanStates.Scanning: | |
// Get the scan stats | |
IntPtr statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr(); | |
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0) | |
{ | |
return "playspace stats query failed"; | |
} | |
// The stats tell us if we could potentially finish | |
if (DoesScanMeetMinBarForCompletion) | |
{ | |
return "When ready, air tap to finalize your playspace"; | |
} | |
return @"Bruno it's time to walk ! | |
Move around and scan in your playspace"; | |
case SpatialUnderstanding.ScanStates.Finishing: | |
return "Finalizing scan (please wait)"; | |
case SpatialUnderstanding.ScanStates.Done: | |
return "Scan complete – Now go back to work!"; | |
default: | |
return @"I'm working, | |
ScanState = " + SpatialUnderstanding.Instance.ScanState.ToString(); | |
} | |
} | |
return ""; | |
} | |
} | |
public bool DoesScanMeetMinBarForCompletion | |
{ | |
get | |
{ | |
// Only allow this when we are actually scanning | |
if ((SpatialUnderstanding.Instance.ScanState != SpatialUnderstanding.ScanStates.Scanning) || | |
(!SpatialUnderstanding.Instance.AllowSpatialUnderstanding)) | |
{ | |
return false; | |
} | |
// Query the current playspace stats | |
var statsPtr = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStatsPtr(); | |
if (SpatialUnderstandingDll.Imports.QueryPlayspaceStats(statsPtr) == 0) | |
{ | |
return false; | |
} | |
var stats = SpatialUnderstanding.Instance.UnderstandingDLL.GetStaticPlayspaceStats(); | |
// Check our preset requirements | |
if ((stats.TotalSurfaceArea > MinAreaForComplete) || | |
(stats.HorizSurfaceArea > MinHorizAreaForComplete) || | |
(stats.WallSurfaceArea > MinWallAreaForComplete)) | |
{ | |
return true; | |
} | |
return false; | |
} | |
} | |
} |
Saludos @ Toronto
El Bruno
References
- GitHub, HoloToolkit
- GitHub, HoloToolkit Unity
- Windows Dev Center, Case study – Expanding the spatial mapping capabilities of HoloLens
- El Bruno, How to Import the HoloToolkit Unity
- El Bruno, How to place a Hologram using AirTap and HoloToolkit
- El Bruno, Creating a menu with options with HoloToolkit
- El Bruno, Using voice commands to display a menu with HoloToolkit
- El Bruno, How to create a 3D text always visible using HoloToolkit
- El Bruno, How to create a HUD (3D text always visible without HoloToolkit)
- El Bruno, How to detect hands using HoloToolkit
- El Bruno, Windows 10, Xbox One Controller, Bluetooth and some lessons learned
- El Bruno, How to use Fire Buttons actions with an XBoxOne Controller
- El Bruno, HoloToolkit compiled packages for Unity3D in GitHub
- El Bruno, How to detect AirTap and Click actions using HoloToolkit
- El Bruno, Detect user hand interactions using #HoloToolkit
- El Bruno, Moving and rotating Holograms using an XBoxOne Controller