ios - 我应该如何将 OpenGL 模型 View 转换为 CATransform3D?

标签 ios uikit opengl-es-2.0 augmented-reality vuforia

我的目标是使用图像跟踪和 Vuforia 在检测到的形状上覆盖标准 UIKit View (目前,我只是创建一个 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 应用于覆盖 View 的层并设置覆盖 View 作为 EAGLView 的 subview 。

我的问题是,正如代码示例中的注释所暴露的那样,这个 sizeFudge 因素。除了这个因素,我的代码做同样的事情 as this answer ;但这把我的观点放在了错误的地方。

根据经验,我发现如果不包含 sizeFudge 项,那么我的叠加 View 会很好地跟踪被跟踪对象的方向和平移,但在 iPad 屏幕上会向下和向右偏移 —这是翻译差异,因此更改用于 .我首先认为问题出在 Vuforia 的目标管理器中指定的对象大小。事实并非如此。如果我创建一个十倍大小的目标,那么覆盖 View 将绘制在相同的、不正确的位置,但要小十倍(我想,因为 AR 假设它正在跟踪的对象更远)。

只是转换这里的姿势让我到达我想去的地方,但这并不令人满意,因为它对我来说没有任何意义。任何人都可以解释从 Vuforia 提供的 OpenGL 坐标转换为不依赖魔数(Magic Number)的 CATransform3D 的正确方法吗?

** 更多数据 **

问题比我写这道题时想的要复杂。标签的位置实际上似乎取决于 iPad 到被跟踪对象的距离,尽管不是线性的。还有一个明显的系统错误。

这是通过将 iPad 移动到距目标一定距离(位于黑色方 block 上方)并用笔在 View 中心出现的位置进行标记而构建的图表。正方形上方和左侧的点具有如上所述的翻译软糖,下方和右侧的点具有 sizeFudge==0。希望这里显示的距离和偏移量之间的关系能够让比我更了解 3D 图形的人了解转换的问题所在。

Chart as described in the previous paragraph.

最佳答案

这可能首先与您的 View 设置有关。错误的宽度和高度或任何其他可能的错误值(例如在 iPad 上使用 iPhone 屏幕比例)可能导致奇怪的偏移。

您的应用是横向的吗?如果是这样,那就试试肖像吧。我过去注意到应用程序似乎总是以纵向屏幕尺寸启动(虽然我还没有确认这一点)所以如果你的 View 设置发生在屏幕是“正确的方式”之前你会得到不匹配。

您也可以尝试算出它到底偏离了多少。不要把 size.data 乘以 hack:添加另一个翻译并调整数字直到正确。这些数字可能会让您更好地了解正在发生的事情。 *10 可能只是侥幸,并没有多大意义。

关于ios - 我应该如何将 OpenGL 模型 View 转换为 CATransform3D?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14941435/

相关文章:

ios - Swift iOS9 新联系人框架 - 如何仅检索具有有效电子邮件地址的 CNContact?

ios - 如何显示时间 08 :00:00 to 8 am using swift

ios - UITableView 禁用滑动删除,但在编辑模式下仍然有删除?

swift - 避免在 deinit 期间第一次访问引用 self 的惰性变量时崩溃

c - 在 OpenGL ES 1.1 与 ES 2.0 中使用顶点缓冲区对象进行绘图

iphone - 哪些 AR 库对于开发用于显示某些对象信息的 iOS 应用程序很有用?

ios - 通过从应用程序图标启动,在应用程序完全关闭时处理远程通知

iphone - 更改 UITableView 部分标题的颜色

android - 带有着色器的 HUD (opengl-es 2.0)

java - 在着色器中使用 alpha 测试的 OpenGL ES 2.0 透明度