Как перевести OpenGLES modelView в CATransform3D?

Моя цель состоит в том, чтобы наложить стандартное представление UIKit (на данный момент я просто создаю UILabel, но в конечном итоге получаю пользовательский контент) по обнаруженной форме, используя отслеживание изображений и Vuforia AR SDK. У меня есть что-то, что работает, но с термином "fudge", который я не могу объяснить. Я хотел бы понять, где моя ошибка, поэтому я могу либо оправдать существование этой коррекции, либо использовать другой алгоритм, который, как известно, действителен.

Мой проект основан на образце проекта ImageTargets в SDK Vuforia. Где их EAGLView выполняет итерации по результатам для рендеринга чайников OpenGL, я заменил это вызовом на мой класс ObjС++ TrackableObjectController. Для каждого отслеживаемого результата он делает следующее:

- (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 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;
}

Затем есть другой код, вызываемый в основном потоке, который смотрит на мои экземпляры TrackableObject, применяет вычисленный CATransform3D к слою представления наложения и устанавливает вид наложения как подпункт EAGLView.

Моя проблема в том, что комментарий в примере кода был отдан, с этим фактором sizeFudge. Помимо этого фактора, код, который у меня есть, делает то же самое как этот ответ; но это заставляет мое мнение не в том месте.

Эмпирически я считаю, что если я не включаю термин sizeFudge, тогда мой оверлейный вид хорошо отслеживает ориентацию и перевод гусеничного объекта, но смещается вниз и направо на экране iPad - это разница в переводе, поэтому имеет смысл изменить используемый термин. Сначала я подумал, что проблема связана с размером объекта, указанным в Vuforia Target Manager. Это не так; если я создаю цель в десять раз больше размера, тогда представление наложения нарисовано в том же неправильном месте, но в десять раз меньше (поскольку AR предполагает, что объект, отслеживающий его дальше, я полагаю).

Это только перевод позы здесь, который меня достает, где я хочу быть, но это неудовлетворительно, поскольку это не имеет никакого смысла для меня. Может ли кто-нибудь объяснить правильный способ перевода из координат OpenGL, предоставленный Vuforia в CATransform3D, который не полагается на магические числа?

** Дополнительные данные **

Проблема сложнее, чем я думал, когда писал этот вопрос. Расположение метки фактически зависит от расстояния от iPad до отслеживаемого объекта, хотя и не линейно. Там также очевидная систематическая ошибка.

Здесь график, построенный путем перемещения iPad на определенное расстояние от цели (расположенного над черным квадратом) и маркировки пером, где появился центр представления. Пункты выше и слева от квадрата имеют выдумку перевода, как описано выше, точки ниже и справа имеют sizeFudge==0. Надеемся, что отношения между расстоянием и смещением, показанные здесь, подскажут кому-то, кто знает больше о 3D-графике, чем я, в чем проблема с преобразованием.

Chart as described in the previous paragraph.

Ответ 1

Вероятно, это связано с настройкой ваших взглядов. Странное смещение может быть вызвано тем, что ширина и высота неправильны или любые другие возможные неправильные значения, такие как использование коэффициента экрана iPhone на iPad.

Является ли ваше приложение ландшафтом? Если да, то дайте ему пойти в портрет. В прошлом я заметил, что приложения всегда запускаются с размерами экрана портрета (я этого еще не подтвердил), поэтому, если ваша настройка просмотра происходит до того, как экран будет "правильным образом" вокруг, вы получите несоответствие.

Вы также можете попытаться точно определить, насколько это возможно. Вместо того, чтобы умножать size.data как взломать: добавьте другой перевод и настройте цифры до упора. Эти цифры могут дать вам некоторое представление о том, что происходит. * 10, вероятно, просто чистая случайность и ничего не значит.