如何将OpenGLES的modelView翻译为CATransform3D?

17
我的目标是使用图像追踪和Vuforia AR SDK,在检测到的形状上叠加标准的UIKit视图(目前,我只创建了一个UILabel,但最终会有自定义内容)。我已经有一些可以工作的东西,但存在一个“假”的术语,我无法解释它。我想了解我的错误在哪里,这样我就可以证明这个修正的存在,或者使用已知有效的不同算法。
我的项目基于Vuforia SDK中的ImageTargets示例项目。当他们的EAGLView迭代结果以渲染OpenGL茶壶时,我用调用我的ObjC++类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'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;
}

接下来是其他的代码,在主线程上调用,它查看我的TrackableObject实例,将计算出的CATransform3D应用于覆盖视图的层,并将覆盖视图设置为EAGLView的子视图。

我的问题是,正如代码示例中的注释所透露的那样,与这个sizeFudge因素有关。除了这个因素,我所拥有的代码与这个答案相同;但这将我的视图放在了错误的位置。

Empirically,我发现如果不包括sizeFudge项,则我的叠加视图可以很好地跟踪所跟踪对象的方向和平移,但在iPad屏幕上向下和向右偏移——这是一种翻译差异,因此改变用于的术语是有道理的。我最初认为问题在于Vuforia的Target Manager中指定的对象大小。事实证明并非如此;如果我创建一个大小为十倍的目标,则叠加视图将以相同的错误位置绘制,但是十倍较小(因为AR假定它正在跟踪的对象更远,我想)。
只有在这里翻译姿势才能让我到达想要去的地方,但是这是不令人满意的,因为对我来说没有任何意义。请问有人可以解释一下从由Vuforia提供的OpenGL坐标转换为不依赖于魔术数字的CATransform3D的正确方法吗?
**一些更多的数据**
当我写这个问题时,问题比我想象的要复杂得多。标签的位置似乎取决于iPad到被跟踪对象的距离,但不是线性的。还存在明显的系统误差。
这里是一张图表,它是通过将iPad移动到距目标一定距离的位置(位于黑色正方形上方),并用笔标记出视图中心出现的位置而构建的。在正方形上方和左侧的点具有如上所述的平移参数,而在正方形下方和右侧的点具有 sizeFudge==0 。希望这里显示的距离和偏移之间的关系能提示比我更了解3D图形的人探究变换问题。

Chart as described in the previous paragraph.


1
他们的OpenGL ES视图使用什么坐标系?通常,OpenGL ES场景的坐标设置为从-1到1,而不是UIKit坐标的0到[宽度]或[高度]。我可以看到需要进行翻译以解决这个问题。如果他们使用的坐标系范围从-10到10,那可能会解释你的翻译偏移量。 - Brad Larson
谢谢你的见解,@BradLarson。我不确定如何找到这个坐标系;目前我无法看到项目设置了锥截体或其他相机投影的位置。而且我感觉这无关紧要,因为“视图”的坐标系应该是在视图平面内的二维坐标系,对吗? - user23743
1
看起来这些人可能有你需要的答案,或者至少有一些有用的指针:https://dev59.com/G1fUa4cB1Zd3GeqPG1J7 - cb88
@cb88 这就是我在这个问题中链接的那个问题;我正在做同样的事情,但没有得到预期的结果。 - user23743
跟踪视图的尺寸是多少?如果设置 trackingView.center = CGPointZero 会发生什么? - tc.
1个回答

1
这可能与您的视图设置有关。奇怪的偏移可能是由于宽度和高度颠倒或其他可能的不正确值,例如在iPad上使用iPhone屏幕比例。
您的应用程序是否为横向?如果是,则尝试以纵向方式运行。我曾经注意到过,过去的应用程序似乎总是使用纵向屏幕尺寸启动(尽管我没有确认过),因此如果您的视图设置发生在屏幕“正确方向”之前,您将会得到不匹配的结果。
您还可以尝试准确计算偏差量。而不是将size.data作为hack进行乘法运算:添加另一个转换并调整数字直到正确为止。这些数字可能会给您更好的了解发生了什么。*10可能只是纯偶然,没有什么特别的含义。

听起来是一个很有前途的路线,谢谢。我在应用程序中看到了其他与纵向/横向方向相关的问题,所以我会去研究一下。 - user23743
我觉得在不同的方向上肯定存在着不同的偏移错误,这可能是一个线索。但这并不是全部,因为在纵向方向上所有东西看起来也都错位了(只是错位的位置不同)。我发现偏移量随着距离目标的远近而变化,所以看起来这是矩阵变换的一个普遍问题。 - user23743

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接