【发布时间】:2013-02-03 04:28:46
【问题描述】:
我的目标是使用图像跟踪和 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 因素。除了这个因素,我的代码做同样的事情as this answer;但这将我的观点置于错误的位置。
根据经验,我发现如果我不包含 sizeFudge 术语,那么我的叠加视图可以很好地跟踪被跟踪对象的方向和平移,但在 iPad 屏幕上向下和向右偏移 - 这是平移差异,因此更改用于 . 的术语是有道理的。我首先认为问题在于 Vuforia 的目标管理器中指定的对象大小。事实证明并非如此。如果我创建一个十倍大小的目标,那么覆盖视图将绘制在相同的、不正确的位置但小十倍(因为 AR 假设它跟踪的对象更远,我想)。
只是翻译这里的姿势才能让我到达我想去的地方,但这并不令人满意,因为它对我没有任何意义。谁能解释从 Vuforia 提供的 OpenGL 坐标转换为不依赖幻数的 CATransform3D 的正确方法?
** 更多数据 **
问题比我写这个问题时想象的要复杂。标签的位置实际上似乎取决于 iPad 到被跟踪对象的距离,尽管不是线性的。还有一个明显的系统错误。
这是一张图表,通过将 iPad 移动到距离目标一定距离(位于黑色方块上方),并用笔在视图中心出现的位置进行标记。正方形上方和左侧的点具有如上所述的翻译软糖,下方和右侧的点具有sizeFudge==0。希望此处显示的距离和偏移量之间的关系能够让比我更了解 3D 图形的人了解变换的问题所在。
【问题讨论】:
-
他们的 OpenGL ES 视图使用的坐标系是什么?通常,OpenGL ES 场景设置的坐标从 -1 到 1,而不是 UIKit 坐标的 0 到 [width] 或 [height]。我可以看到需要翻译来解释这一点。如果他们使用范围从 -10 到 10 的坐标系,这可能解释了您的翻译捏造因素。
-
感谢@BradLarson 的洞察力。我不确定如何找到这个坐标系;我目前看不到项目在哪里设置了截锥体或其他相机投影。我也觉得这是不相关的,因为 view 的 坐标系在视图平面上是二维的,不是吗?
-
看起来这些人可能会给你答案,或者至少有一些有用的建议:stackoverflow.com/questions/6045502/…
-
@cb88 这是我在这个问题中链接的问题;我正在做同样的事情但没有得到预期结果的那个。
-
跟踪视图的大小是多少?如果你设置
trackingView.center = CGPointZero会发生什么?
标签: ios uikit opengl-es-2.0 augmented-reality vuforia