我正在开发一款增强现实应用程序,但是我遇到了一些问题,无法将对象显示在屏幕上。对于我而言,不能将GPS点转换为Android设备上相应的屏幕点非常令人沮丧。我已经阅读了许多文章和stackoverflow上的其他帖子(我已经问过类似的问题),但我仍然需要你的帮助。
我进行了在维基百科中解释的透视投影。
要如何处理透视投影的结果才能获得相应的屏幕点呢?
我正在开发一款增强现实应用程序,但是我遇到了一些问题,无法将对象显示在屏幕上。对于我而言,不能将GPS点转换为Android设备上相应的屏幕点非常令人沮丧。我已经阅读了许多文章和stackoverflow上的其他帖子(我已经问过类似的问题),但我仍然需要你的帮助。
我进行了在维基百科中解释的透视投影。
要如何处理透视投影的结果才能获得相应的屏幕点呢?
维基百科文章在我之前读它时也让我感到困惑。以下是我的另一种解释:
我们简化一下情况,有:
...我们要:
X屏幕坐标的模式:
在这种配置中,E是我们的“眼睛”的位置,我选择它作为起点以简化问题。
可以通过估算焦距f来得到:
tan(α) = (w/2) / f
(1)从图片中可以看出三角形ECD和EBM是相似的,因此使用分线定理,我们得到:
MB / CD = EM / EC
<=> X / x = f / z
(2)现在,结合两个方程(1)和(2),我们有:
X = (x / z) * ((w / 2) / tan(α))
如果我们回到维基百科文章使用的符号,我们的方程等价于:
b_x = (d_x / d_z) * r_z
你可以注意到,我们缺少了乘以s_x / r_x
。这是因为在我们的情况下,"显示尺寸"和"记录表面"是相同的,所以s_x / r_x = 1
。
注:对于Y,同样的推理。
一些注意事项:
tan(α)= 1
,因此该术语不会出现在许多实现中。如果要保留显示元素的比率,请对X和Y都保持f不变,即不要计算:
X = (x / z) * ((w / 2) / tan(α))
和 Y = (y / z) * ((h / 2) / tan(α))
而是执行:
X = (x / z) * ((min(w,h) / 2) / tan(α))
和 Y = (y / z) * ((min(w,h) / 2) / tan(α))
将正方形表面r转换为可能的矩形表面s。注:当我说"显示尺寸"和"记录表面"是相同的"时,那并不完全正确,这里的min操作用于补偿此近似值,适应最小的尺寸。
注2:Appunta使用screenRatio=(getWidth()+getHeight())/2
而不是min(w,h)/2,如您所注意到的。这两种解决方案都保留了元素比例。焦点和视角将根据屏幕自身的比例略有不同。实际上,您可以使用任何想要定义f的函数。
正如您在上图中看到的那样,屏幕坐标在此处定义为X的[-w/2 ; w/2]和Y的[-h/2 ; h/2],但您可能希望改为 [0 ; w] 和 [0 ; h]。解决方法是X += w/2
和Y += h/2
。
希望这能回答您的问题。如果需要修改,我会随时待命。
再见!
<自我推广警报>我实际上在一段时间前写了一篇关于3D投影和渲染的文章。实现是用Javascript完成的,但很容易翻译。