Obtener resultados de ejecución de sesión
Durante la ejecución de la sesión, se modifican los transform de algunos objetos en la escena y se altera la imagen de la cámara, entre otros cambios. En ocasiones, estas modificaciones no satisfacen plenamente las necesidades de la aplicación, y puede ser necesario obtener los resultados de ejecución de la sesión en cada fotograma para procesar estos datos de forma secundaria. Este documento explica cómo obtener y utilizar estos datos de resultados.
Antes de comenzar
- Comprende los conceptos básicos, la composición y el flujo de trabajo de la sesión a través de Introducción a ARSession
- Aprende cómo crear una sesión
- Aprende cómo acceder a los componentes de funcionalidad AR
Obtener actualizaciones de InputFrame
Puedes usar el evento InputFrameUpdate para obtener actualizaciones de InputFrame. Este evento solo se activa cuando InputFrame cambia en los datos de salida de cada fotograma de la sesión.
Nota
InputFrameUpdate solo es válido en sesiones donde la renderización de imágenes la realiza EasyAR. Generalmente, no es válido cuando se usa AR Foundation o dispositivos de visualización montados en la cabeza (head-mounted displays), en cuyo caso se deben usar los métodos proporcionados por esas bibliotecas de terceros para obtener actualizaciones de datos.
Con InputFrame puedes obtener la imagen de la cámara física, parámetros de la cámara, marca de tiempo, transform de la cámara física en relación al sistema de coordenadas mundial y estado de seguimiento, entre otros. Sin embargo, dado que la transform de la cámara ya ha sido aplicada por la sesión a la cámara virtual y otros objetos, generalmente no es necesario obtener la transform de la cámara a través de InputFrame.
Obtener la imagen de la cámara física del fotograma actual
Puedes usar el método InputFrame.image() para obtener los datos de imagen de la cámara física como tipo Image.
Por ejemplo, el siguiente código puede obtener la imagen de la cámara física cuando se actualiza InputFrame:
Session.InputFrameUpdate += (inputFrame) => {
using (var image = inputFrame.image())
{
}
};
Precaución
Al usar datos de tipo Image y otros datos de tipo class obtenidos de él, es necesario asegurarse de que Dispose() se invoque correctamente (la instrucción using en el código anterior garantiza esto), de lo contrario podrían producirse fugas de memoria o incluso problemas como la detención de actualizaciones de imagen.
Si necesitas retener InputFrame o Image para usarlos en el siguiente fotograma, debes incrementar el valor de ARAssembly.ExtraBufferCapacity según la cantidad de datos retenidos, de lo contrario podrías fallar al obtener datos debido a capacidad insuficiente en el búfer.
Si necesitas retener InputFrame, también debes llamar al método Clone() para crear una copia de referencia, y luego invocar Dispose() en la copia cuando ya no la necesites.
Dado que la frecuencia de fotogramas de la cámara física suele ser inferior a la frecuencia de renderizado, no se activará el evento InputFrameUpdate en cada fotograma de renderizado. Sin embargo, del mismo modo, la renderización de imágenes de la cámara física tampoco se actualiza en cada fotograma de renderizado. El contenido visual de todos los fotogramas de renderizado hasta el próximo evento InputFrameUpdate coincidirá con la imagen del InputFrame actual.
Nota
La imagen en InputFrame siempre será consistente con la imagen de fondo de la cámara virtual del fotograma actual, pero durante la renderización del fondo, la imagen puede sufrir escalado y recorte, por lo que es normal que la imagen obtenida tenga un tamaño o proporción diferente al que se muestra en pantalla.
Además, es importante señalar que los datos de imagen devueltos por InputFrame.image() son legibles por la CPU, no son texturas de GPU. Si necesitas usar los datos de imagen en la GPU, debes cargarlos en una textura de GPU o usar la interfaz CameraImageRenderer.RequestTargetTexture(Action<Camera, RenderTexture>) para obtener directamente la textura de GPU.
[Opcional] Interceptar la renderización de imágenes de la cámara física
Puedes usar ARAssembly.CameraImageRenderer para controlar el dibujo de imágenes de la cámara física.
El siguiente código puede detener el dibujo de imágenes de la cámara física:
if (Session.Assembly != null && Session.Assembly.CameraImageRenderer.OnSome)
{
Session.Assembly.CameraImageRenderer.Value.enabled = false;
}
Es importante señalar que primero se debe verificar si existe ARAssembly.CameraImageRenderer.
Nota
Solo en sesiones donde la renderización de imágenes la realiza EasyAR, puedes detener las actualizaciones de imagen mediante el método anterior. Generalmente, no es válido cuando se usa AR Foundation o dispositivos de visualización montados en la cabeza, en cuyo caso se deben usar los métodos proporcionados por esas bibliotecas de terceros para implementar la funcionalidad correspondiente.
Después de detener el dibujo de imágenes de la cámara física, la aplicación puede usar InputFrame para obtener datos de imagen de la cámara física y usarlos para realizar un dibujo personalizado.
Obtener actualizaciones de transform
Puedes obtener datos de transform de objetos en la escena después de cada actualización de fotograma de la sesión a través del evento PostSessionUpdate.
Nota
Para algunas funcionalidades (como Mega), incluso si la imagen no cambia y no se solicita explícitamente una actualización del servicio, el cálculo AR se ejecuta en cada fotograma de renderizado. Por lo tanto, si necesitas obtener todos los cambios de transform, debes obtener los datos de transform en cada fotograma, no solo en algunos fotogramas.
Obtener el transform de la cámara virtual
Puedes obtener el transform de la cámara en la escena a través de ARAssembly.Camera.
Session.PostSessionUpdate += () =>
{
var position = Session.Assembly.Camera.transform.position;
var rotation = Session.Assembly.Camera.transform.rotation;
};
Obtener el transform del target
Puedes obtener el transform del target en la escena a través del objeto target concreto en uso. Por ejemplo, para el seguimiento de imágenes, este target es el objeto donde está ubicado el componente ImageTargetController.
Session.PostSessionUpdate += () =>
{
var position = target.transform.position;
var rotation = target.transform.rotation;
};
[Opcional] Obtener pose
Pose es una estructura de datos que describe la posición y orientación de un objeto, generalmente compuesta por position y rotation. En aplicaciones AR, pose se usa típicamente para describir la posición y orientación de la cámara física o de un objetivo de seguimiento en relación a un sistema de referencia.
Unity no proporciona datos de pose originales, ya que pose generalmente se usa para impulsar el movimiento de objetos en la escena, y este trabajo lo realiza automáticamente la sesión. Para el cálculo y renderizado de contenido, transform es suficiente.
Importante
Antes de leer los métodos a continuación, vuelve a considerar si los datos de transform de objetos en la escena, como la cámara y objetivos de seguimiento, ya satisfacen tus necesidades. Por lo general, los datos de pose adicionales no son necesarios.
Si realmente necesitas datos de pose por alguna razón, puedes calcular el valor de pose requerido a partir de transform en el evento PostSessionUpdate. Generalmente, el transform relativo entre target y camera obtenido en PostSessionUpdate es la pose.
El siguiente código muestra cómo obtener el transform de camera y target, y calcular la pose relativa entre ellos:
Session.PostSessionUpdate += () =>
{
Pose cameraToWorld = new(Session.Assembly.Camera.transform.position, Session.Assembly.Camera.transform.rotation);
Pose targetToWorld = new(target.transform.position, target.transform.rotation);
Pose worldToTarget = new()
{
position = Quaternion.Inverse(targetToWorld.rotation) * (-targetToWorld.position),
rotation = Quaternion.Inverse(targetToWorld.rotation)
};
Pose cameraToTarget = cameraToWorld.GetTransformedBy(worldToTarget);
};
Precaución
Si también estás usando AR Foundation, dispositivos de visualización montados en la cabeza u otras bibliotecas de terceros que se ejecutan simultáneamente, estas bibliotecas también podrían modificar el transform de la cámara en la escena. Debes asegurarte de que la lógica de actualización de estas bibliotecas haya finalizado antes de realizar cálculos de pose relacionados, de lo contrario los resultados podrían ser incorrectos. En este escenario, la pose relativa entre target y origin en PostSessionUpdate sigue siendo precisa.
[Opcional] Interceptar actualizaciones de transform
Durante la ejecución de la funcionalidad AR, los transform de objetos como cámaras y objetivos de seguimiento en Unity generalmente se actualizan automáticamente por la sesión. Estos procesos de actualización garantizan la corrección y consistencia de la renderización AR, por lo que no hay ningún método disponible para interceptar estas actualizaciones.
Sin embargo, si necesitas personalizar la lógica de actualización de transform de objetos, puedes hacerlo escuchando el evento PostSessionUpdate. Esto requiere un método algo engorroso:
- Aunque normalmente los contenidos de renderizado deberían estar montados como nodos hijos o componentes adicionales bajo objetos controlados por la sesión, si necesitas personalizar la actualización de transform de objetos, debes eliminar estos objetos de la jerarquía de objetos controlados por la sesión. Es decir, estos objetos no deberían ser nodos hijos de objetos controlados por la sesión.
- En el evento PostSessionUpdate, registra el transform de los objetos que deseas actualizar de forma personalizada.
- Finalmente, en el evento PostSessionUpdate, usa la lógica personalizada para actualizar el transform de estos objetos basándote en los datos proporcionados por la sesión.
Nota
Usar el evento PostSessionUpdate es necesario, ya que solo después de este momento la sesión dejará de manipular objetos en la escena.
Es importante señalar que este método no puede usarse para modificar la cámara, ya que se requiere una lógica más compleja para manejar actualizaciones personalizadas de la cámara.
Además, este método solo puede usarse para personalizar la actualización de transform de objetos, no para modificar el transform de objetos controlados por la sesión. Si el transform de un objeto controlado por la sesión es modificado externamente, la sesión aún lo sobrescribirá en la próxima actualización de fotograma, lo que podría afectar la corrección de algunos cálculos.
Precaución
Usar este método requiere que garantices la corrección del transform de los objetos, de lo contrario podría causar errores en la renderización AR.
Si también estás usando AR Foundation, dispositivos de visualización montados en la cabeza u otras bibliotecas de terceros, estas podrían modificar también el transform de objetos en la escena. Debes asegurarte de que la lógica de actualización de estas bibliotecas no entre en conflicto con tu lógica personalizada, de lo contrario podrías obtener resultados inesperados.
Temas relacionados
- Modo de centro restringe qué objetos tendrán su transform modificado por la sesión
- Introducción a componentes básicos de AR