使用ARCore捕捉地板纹理

时间:2019-03-13 21:13:35

标签: unity3d math graphics arcore

我试图基于ARCore检测到的平面和环境(相机)纹理捕获“地板纹理”。然后在平面网格中重新应用此地板纹理,从而基于现实创建数字地板。 我上传了一张图片来说明这一点:

Illustration

这不是ARCore特有的问题,我认为可以通过数学和图形编程来解决,也许类似于基于相机矩阵对飞机进行投影,但是我不知道该怎么做。

有人可以帮助我吗? 谢谢!

1 个答案:

答案 0 :(得分:0)

从本质上讲,我们在此问题上具有三个重要的坐标系:

Coordinate Systems

我们拥有可以任意定义的常规3D世界坐标系。我们有一个平面的2D坐标系。该坐标系的原点位于平面的中心(请注意,为此,我将术语 plane 用作 rectangle 的同义词),坐标范围为-1至+1 。最后,我们为图像设置了2D坐标。实际上,图像有两个:无符号坐标系(如图所示),其原点位于左下角,坐标范围为0到1,以及一个带符号的坐标系,坐标范围为-1到1。 >

我们知道飞机在世界空间中的四个角以及3x4视图/投影矩阵P,该矩阵使我们可以使用齐次坐标将世界空间中的任何点投影到图像空间:

p_image,signed = P * p_world

如果您的投影矩阵为4x4,则由于我们对图像空间深度不感兴趣,只需删除第三行(最后一个,但末尾为1)即可。

我们并不真正在乎世界空间,因为这有点武断。给定平面空间中的2D点,我们可以使用以下方法将其转换为世界空间:

p_world = 1/4 (p0 + p1 + p2 + p3) + u * 1/2 * (p1 - p0) + v * 1/2 * (p3 - p0)

第一部分是平面的原点,第二和第三项中的点差是坐标轴。我们可以用矩阵形式表示为

/ x \   / p1_x - p0_x   p2_x - p0_x   1/4 (p0_x + p1_x + p2_x + p3_x) \   / u \
| y | = | p1_y - p0_y   p2_x - p0_x   1/4 (p0_y + p1_y + p2_y + p3_y) | * | v |
| z |   | p1_z - p0_z   p2_x - p0_x   1/4 (p0_z + p1_z + p2_z + p3_z) |   \ 1 /
\ 1 /   \      0             0                         1              /

让我们将此矩阵称为M

现在,我们可以使用以下方法直接从平面空间转到图像空间:

p_image,signed = P * M * p_plane

矩阵P * M现在是3x3矩阵。这是您的地平面和像平面之间的单应性。

那么,我们该怎么办?我们可以使用它在平面空间中绘制图像。所以,这就是我们要做的事情:

我们将生成一个渲染目标,将用一个绘制调用将其填充。然后,此渲染目标将包含我们平面的纹理。要绘制此图像,我们:

  1. 将相机图像作为纹理上传到GPU
  2. 绑定渲染目标
  3. 绘制一个全角四边形(-1, -1), (1, -1), (1, 1), (-1, 1)
  4. 在顶点着色器中,从平面空间计算图像空间中的纹理坐标
  5. 在像素着色器中,在插值纹理坐标处采样相机图像

有趣的部分是数字4。我们几乎知道我们需要做什么。我们已经知道如何去签名图像空间。现在,我们只需要进入未签名的图像空间。这是一个简单的转变和规模化:

                   / 1/2  0  1/2 \
p_image,unsigned = |  0  1/2 1/2 | * p_image,signed
                   \  0   0   1  /

如果我们将此矩阵称为S,则可以计算S * P * M以获得单个3x3矩阵T。此矩阵可在顶点着色器中用于根据传入的平面空间点计算纹理坐标:

texCoords = p_image,unsigned = T * p_plane

将整个3D矢量传递到片段着色器并仅在像素着色器中进行透视划分以产生正确的透视是很重要的。