Il mio obiettivo è sovrapporre una visualizzazione UIKit standard (per il momento sto creando solo uno UILabel
ma alla fine avrò un contenuto personalizzato) su una forma rilevata utilizzando il tracciamento delle immagini e l'SDK Vuforia AR. Ho qualcosa che funziona, ma con un termine "fudge" che non posso giustificare. Mi piacerebbe capire dove è il mio errore, quindi posso giustificare l'esistenza di questa correzione o utilizzare un algoritmo diverso che è noto per essere valido.Come dovrei tradurre un modelView OpenGLES in un CATransform3D?
Il mio progetto si basa sul progetto di esempio ImageTargets nell'SDK di Vuforia. Laddove il loro esegue iterazioni sui risultati per il rendering delle teorie OpenGL, l'ho sostituito con una chiamata alla classe ObjC++ TrackableObjectController
. Per ogni risultato tracciabile, lo fa:
- (void)augmentedRealityView:(EAGLView *)view foundTrackableResult:(const QCAR::TrackableResult *)trackableResult
{
// find out where the target is in Core Animation space
const QCAR::ImageTarget* imageTarget = static_cast<const QCAR::ImageTarget*>(&(trackableResult->getTrackable()));
TrackableObject *trackable = [self trackableForName: TrackableName(imageTarget)];
trackable.tracked = YES;
QCAR::Vec2F size = imageTarget->getSize();
QCAR::Matrix44F modelViewMatrix = QCAR::Tool::convertPose2GLMatrix(trackableResult->getPose());
CGFloat ScreenScale = [[UIScreen mainScreen] scale];
float xscl = qUtils.viewport.sizeX/ScreenScale/2;
float yscl = qUtils.viewport.sizeY/ScreenScale/2;
QCAR::Matrix44F projectedTransform = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
QCAR::Matrix44F qcarTransform = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
/* this sizeFudge constant is here to put the label in the correct place in this demo; I had thought that
* the problem was related to the units used (I defined the length of the target in mm in the Target Manager;
* the fact that I've got to multiply by ten here could be indicative of the app interpreting length in cm).
* That turned out not to be the case, when I changed the reported length of the target it stopped drawing the
* label at the correct size. Currently, therefore, the app and the target database are both using mm, but
* there's the following empirically-divised fudge factor to get the app to position the correctly-sized view
* in the correct position relative to the detected object.
*/
const double sizeFudge = 10.0;
ShaderUtils::translatePoseMatrix(sizeFudge * size.data[0]/2, sizeFudge * size.data[1]/2, 0, projectedTransform.data);
ShaderUtils::scalePoseMatrix(xscl, -yscl, 1.0, projectedTransform.data); // flip along y axis
ShaderUtils::multiplyMatrix(projectedTransform.data, qUtils.projectionMatrix.data, qcarTransform.data);
ShaderUtils::multiplyMatrix(qcarTransform.data, modelViewMatrix.data, qcarTransform.data);
CATransform3D transform = *((CATransform3D*)qcarTransform.data); // both are array[16] of float
transform = CATransform3DScale(transform,1,-1,0); //needs flipping to draw
trackable.transform = transform;
}
V'è poi un altro codice, chiamato sul thread principale, che guarda i miei TrackableObject
casi, vale la calcolata CATransform3D
al livello della vista sovrapposizione e imposta la vista sovrapposizione come una sottoview dello .
Il mio problema è, come il commento nel codice di esempio ha dato via, con questo fattore sizeFudge
. Oltre a questo fattore, il codice che ho fa la stessa cosa as this answer; ma questo sta mettendo la mia opinione nel posto sbagliato.
Empiricamente trovo che se non includere il termine sizeFudge
, allora la mia vista sovrapposizione segue l'orientamento e la conversione dell'oggetto monitorato bene, ma è compensato verso il basso e verso destra sul iPad schermo-si tratta di una differenza di conversione, quindi ha senso cambiare il termine usato per. Per prima cosa ho pensato che il problema fosse la dimensione dell'oggetto come specificato in Target Manager di Vuforia. Questo risulta non essere il caso; se creo un bersaglio dieci volte la dimensione, la vista di sovrapposizione viene disegnata nello stesso posto errato ma dieci volte più piccola (poiché l'AR presuppone che l'oggetto del suo tracciamento sia più lontano, suppongo).
Trasloca qui solo la posa che mi porta dove voglio essere, ma questo non è soddisfacente in quanto non ha alcun senso per me. Qualcuno può spiegare il modo corretto di tradurre le coordinate OpenGL fornite da Vuforia in un CATransform3D che non si basa su numeri magici?
** Alcuni altri dati **
il problema è più complicato di quanto ho pensato quando ho scritto questa domanda. La posizione dell'etichetta sembra effettivamente dipendere dalla distanza dall'iPad all'oggetto tracciato, sebbene non in modo lineare. C'è anche un evidente errore sistematico.
Ecco una tabella costruita spostando l'iPad a una certa distanza dall'obiettivo (situato sopra il quadrato nero) e contrassegnando con una penna dove è apparso il centro della vista. I punti sopra e alla sinistra del quadrato hanno il fudge di traduzione come descritto sopra, i punti in basso e a destra hanno sizeFudge==0
. Speriamo che la relazione tra distanza e offset mostrata qui induca qualcuno con più conoscenza della grafica 3D di me a capire qual è il problema con la trasformazione.
Qual è il sistema di coordinate utilizzato per la loro vista OpenGL ES? Normalmente, le scene OpenGL ES sono impostate con coordinate che vanno da -1 a 1, piuttosto che da 0 a [larghezza] o [altezza] delle coordinate UIKit. Potevo vedere la necessità di una traduzione per renderlo conto. Se stessero usando un sistema di coordinate compreso tra -10 e 10, ciò potrebbe spiegare il fattore fudge della traduzione. –
Grazie per l'intuizione @BradLarson. Non sono sicuro di come troverei questo sistema di coordinate; Al momento non riesco a vedere dove il progetto imposta un trancio o un'altra proiezione della telecamera. Ho anche la sensazione che questo non sia correlato, perché il sistema di coordinate di _view's_ sarebbe bidimensionale nel piano della vista, non è vero? –
Sembra che questi ragazzi potrebbero avere la risposta per te o almeno alcuni suggerimenti utili: http://stackoverflow.com/questions/6045502/how-to-get-catransform3d-from-projection-and-modelview-matricesModelView-matrices – cb88