Table of Contents

Ottenere il risultato di esecuzione di session

Durante l’esecuzione di session vengono modificati il transform di alcuni oggetti della scena e l’immagine della camera. A volte queste modifiche non sono ancora sufficienti per l’applicazione, e può essere necessario ottenere il risultato di esecuzione di session a ogni frame ed elaborare di nuovo questi dati. Questo articolo spiega come ottenere e usare tali dati.

Prima di iniziare

Ottenere gli aggiornamenti di InputFrame

Puoi usare l’evento InputFrameUpdate per ottenere gli aggiornamenti di InputFrame. Questo evento viene attivato solo quando InputFrame cambia nei dati di output di ogni frame di session.

Nota

InputFrameUpdate è valido solo nelle session in cui l’immagine viene disegnata da EasyAR. In generale non è valido quando si usa AR Foundation o un visore, e in quel caso bisogna usare i metodi forniti da quelle librerie di terze parti per ottenere gli aggiornamenti dei dati.

Con InputFrame puoi ottenere l’immagine della camera fisica, i parametri della camera, il timestamp, il transform della camera fisica rispetto al sistema di coordinate del mondo e lo stato di tracking, e così via. Tuttavia, poiché il transform della camera è già applicato da session alla camera virtuale e agli altri oggetti, in genere non è necessario ottenere il transform della camera tramite InputFrame.

Ottenere l’immagine della camera fisica del frame corrente

Puoi usare il metodo InputFrame.image() per ottenere i dati immagine della camera fisica di tipo Image.

Per esempio, il codice seguente ottiene l’immagine della camera fisica quando InputFrame viene aggiornato:

Session.InputFrameUpdate += (inputFrame) => {
    using (var image = inputFrame.image())
    {
    }
};
Attenzione

Quando usi dati di tipo Image e altri dati di tipo class ottenuti da esso, devi assicurarti che Dispose() venga chiamato correttamente (l’istruzione using nel codice sopra lo garantisce); altrimenti possono verificarsi perdite di memoria e persino l’interruzione dell’aggiornamento dell’immagine.

Se devi conservare InputFrame o Image per usarli nel frame successivo, aumenta il valore di ARAssembly.ExtraBufferCapacity in base alla quantità di dati conservata; altrimenti l’acquisizione dei dati potrebbe fallire per mancanza di buffer.

Se devi conservare InputFrame, devi anche chiamare Clone() per creare una copia con riferimento, e poi chiamare Dispose() sulla copia quando non serve più.

Poiché il frame rate della camera fisica è di solito inferiore al frame rate di rendering, non tutti i frame di rendering ricevono l’evento InputFrameUpdate, ma allo stesso modo l’immagine della camera fisica non viene aggiornata a ogni frame di rendering. Tutti i frame di rendering prima del successivo trigger di InputFrameUpdate hanno lo stesso contenuto immagine dell’InputFrame corrente.

Nota

L’immagine in InputFrame è sempre coerente con l’immagine di sfondo della camera virtuale del frame corrente, ma durante il rendering dello sfondo possono esserci scaling e ritaglio, quindi è normale che le dimensioni o il rapporto dell’immagine ottenuta non coincidano con quanto mostrato sullo schermo.

Inoltre, va notato che i dati immagine restituiti da InputFrame.image() sono leggibili dalla CPU e non sono una texture GPU. Se devi usare i dati immagine sulla GPU, devi caricarli in una texture GPU, oppure ottenere direttamente la texture GPU tramite l’interfaccia CameraImageRenderer.RequestTargetTexture(Action<Camera, RenderTexture>).

[Opzionale] Intercettare il rendering dell’immagine della camera fisica

Puoi usare ARAssembly.CameraImageRenderer per controllare il rendering dell’immagine della camera fisica.

Il codice seguente può arrestare il rendering dell’immagine della camera fisica:

if (Session.Assembly != null && Session.Assembly.CameraImageRenderer.OnSome)
{
    Session.Assembly.CameraImageRenderer.Value.enabled = false;
}

Tieni presente che qui bisogna prima verificare se ARAssembly.CameraImageRenderer esiste.

Nota

Solo nelle session in cui l’immagine viene disegnata da EasyAR è possibile interrompere l’aggiornamento dell’immagine con il metodo sopra. In generale non è valido quando si usa AR Foundation o un visore, e in quel caso bisogna usare i metodi forniti da quelle librerie di terze parti per ottenere la funzione corrispondente.

Dopo aver arrestato il rendering dell’immagine della camera fisica, l’applicazione può ottenere i dati immagine della camera fisica tramite InputFrame e usarli per un rendering personalizzato.

Ottenere gli aggiornamenti di transform

Puoi ottenere i dati di transform degli oggetti nella scena dopo ogni aggiornamento di session tramite l’evento PostSessionUpdate.

Nota

Per alcune funzioni (ad esempio Mega), anche se l’immagine non cambia e non c’è una richiesta visibile di aggiornamento del servizio, il calcolo AR viene eseguito a ogni frame di rendering. Quindi, se devi ottenere tutte le variazioni di transform, devi recuperare i dati di transform a ogni frame e non solo su alcuni frame.

Ottenere il transform della camera virtuale

Puoi ottenere il transform della camera nella scena tramite ARAssembly.Camera.

Session.PostSessionUpdate += () =>
{
    var position = Session.Assembly.Camera.transform.position;
    var rotation = Session.Assembly.Camera.transform.rotation;
};

Ottenere il transform del target

Puoi ottenere il transform del target nella scena attraverso l’oggetto target specifico che stai usando. Ad esempio, per image tracking, quel target è l’oggetto che contiene il componente ImageTargetController.

Session.PostSessionUpdate += () =>
{
    var position = target.transform.position;
    var rotation = target.transform.rotation;
};

[Opzionale] Ottenere la pose

La pose è una struttura dati che descrive la posizione e l’orientamento di un oggetto, e di solito è composta da position e rotation. Nelle applicazioni AR, la pose viene spesso usata per descrivere la posizione e l’orientamento della camera fisica o del target di tracking rispetto a un sistema di riferimento.

Unity non fornisce dati pose grezzi, perché la pose viene in genere usata per guidare il movimento degli oggetti nella scena, e questo è esattamente il lavoro che session fa in automatico. Per il calcolo e il rendering del contenuto, basta il transform.

Importante

Prima di leggere il metodo seguente, chiediti di nuovo se i dati transform della camera, del target di tracking e degli altri oggetti soddisfano già le tue esigenze. In genere, i dati pose aggiuntivi non sono necessari.

Se per qualche motivo hai davvero bisogno dei dati pose, puoi calcolarli dal transform nell’evento PostSessionUpdate. In generale, il transform relativo tra target e camera ottenuto in PostSessionUpdate è già la pose.

Il codice seguente mostra come ottenere i transform di camera e target e calcolare la pose relativa tra i due:

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

Se stai usando contemporaneamente AR Foundation, un visore o altre librerie di terze parti in esecuzione, anche queste librerie potrebbero modificare il transform della camera nella scena. Devi assicurarti che il calcolo della pose avvenga dopo che le loro logiche di aggiornamento sono terminate; altrimenti il risultato potrebbe non essere corretto. In uno scenario del genere, la pose relativa tra target e origin in PostSessionUpdate rimane accurata.

[Opzionale] Intercettare gli aggiornamenti di transform

Quando le funzioni AR sono in esecuzione, il transform della camera, del target di tracking e di altri oggetti in Unity viene di solito aggiornato automaticamente da session. Questi aggiornamenti garantiscono la correttezza e la coerenza del rendering AR, quindi non esiste un modo per intercettarli direttamente.

Ma se hai bisogno di una logica personalizzata per aggiornare il transform degli oggetti, puoi farlo ascoltando l’evento PostSessionUpdate. Qui è necessario usare un metodo un po’ laborioso:

  1. Anche se normalmente il contenuto renderizzato dovrebbe essere montato come nodi figlio o componenti aggiuntivi sotto gli oggetti controllati da session, se devi personalizzare l’aggiornamento del transform di quegli oggetti, devi rimuoverli dalla gerarchia controllata da session. In altre parole, questi oggetti non devono essere figli degli oggetti controllati da session.
  2. Nell’evento PostSessionUpdate, registra il transform degli oggetti che vuoi aggiornare in modo personalizzato.
  3. Infine, nell’evento PostSessionUpdate, usa la logica personalizzata per aggiornare questi oggetti in base ai dati forniti da session.
Nota

L’uso dell’evento PostSessionUpdate è necessario, perché solo dopo quel momento session non agisce più sugli oggetti della scena.

Tieni presente che questo metodo non può essere usato per modificare la camera; per la personalizzazione dell’aggiornamento della camera serve una logica più complessa.

Inoltre, questo metodo serve solo per aggiornare in modo personalizzato il transform degli oggetti, non per modificare il transform degli oggetti controllati da session. Se il transform di un oggetto controllato da session viene modificato dall’esterno, session sovrascriverà comunque quelle modifiche al successivo aggiornamento del frame, e ciò può influire sulla correttezza di alcuni calcoli.

Attenzione

Usare questo metodo richiede di garantire la correttezza del transform degli oggetti; altrimenti può causare errori di rendering AR.

Se stai usando anche AR Foundation, un visore o altre librerie di terze parti, queste librerie possono modificare il transform degli oggetti della scena. Devi assicurarti che la logica di aggiornamento di queste librerie non entri in conflitto con la tua logica personalizzata; altrimenti possono verificarsi risultati imprevedibili.

Argomenti correlati