Моя цель состоит в том, чтобы наложить стандартное представление 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-графике, чем я, в чем проблема с преобразованием.