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