如何将3D空间坐标转换为2D空间坐标?

14

我正在使用一个Lua API。 我试图将3D空间坐标转换为2D空间坐标。 我已经问过谷歌,但除了使用OpenGL函数的片段之外,我找不到任何东西。 我不需要源代码或其他任何东西,只需要简单的方法来完成它? 如果有帮助的话,我可以获取相机的透视图,要转换的原始位置、窗口大小和宽高比。 感谢您提前提供的任何建议:)


2
在哪个空间中转换为2D坐标? - Bart
抱歉,我想输入的是屏幕坐标。 - Conros
2个回答

18

如果你要将世界空间(x,y,z)坐标转换为屏幕空间(u,v)坐标,则基本方法是:

u = x / z;
v = y / z;

如果相机不在原点,则需要在投影矩阵之前使用视图矩阵转换(x,y,z)。您可能还想调整相机的透视,纵横比等,这种情况下我会参考这篇维基百科文章

如果您正在寻找Lua API特定的内容,很抱歉我不熟悉。


重要的是要注意,这不是真正的透视投影,而是所谓的“弱透视投影”,是正交投影和透视投影的混合。 - adrian
1
这对我来说毫无意义。随着z趋近于0,x和y趋近于无穷大。因此,在世界空间中为(1,1,0)的向量,在屏幕空间中应该为(1,1),在适当的相机设置下最终会变成(无穷大,无穷大)。 - David Coombes
2
@DavidCoombes为什么不合理呢?如果相机位于原点,面向z方向,它永远无法看到在相机上方或右侧的物体,因此x和y应该趋近于无穷大。我想象时经常使用这个例子:https://www.youtube.com/watch?v=_P00jYB81ZQ 当旗帜靠近您(当z趋近于零),x和y变得更大,旗帜飞出屏幕。 - Peter Bruins

1

使用这个数学公式:—

New2dpos = ((zpos÷fovl)*oldpos)

在此处,pos 表示位置。

在此处,fovl 表示从相机到屏幕的距离。(如果图像拉伸了,可以调整此值)

oldpos= 3d 的 "x" 或 "y" 坐标。这个公式适用于 x 和 y 的 3d 坐标。

New2dpos 表示投影坐标,您可以将其用于在您的 2d 平面上进行投影。

请参见以下图片以获得更好的解释:

perspective projection image

// 'double[] a' indicates your 3d coordinates.eg: a=[x,y,z];

// int b indicates whether you wanted to return your 2d x coordinate or y coordinate. 0 will return x and 1 will return y.

// if your image stretches then you can adjust the fovl(field of view line)(distance from camera to screen) .

public static double PERSPECTIVE_PROJECTION(double[] a,int b){
int fovl=200;
double oldpos=a[b];
double z=a[2];
double newpos=(double)(fovl/(fovl+z))*oldpos;
return newpos;
}

这段Java代码定义了一个名为PERSPECTIVE_PROJECTION的静态方法,它接收一个包含3D坐标的double数组a和一个整数b作为参数,用于指示返回投影的2D x坐标还是2D y坐标。

变量fovl的默认值设置为200,该值表示在投影空间中从摄像机到屏幕的距离。

然后代码检索指定的3D坐标“a [b]”的旧位置和相同坐标的z坐标“a [2]”。

使用公式(fovl /(fovl + z)* oldpos)计算透视畸变因子,基于相机和3D坐标之间的距离。然后将(fovl /(fovl + z))乘以旧位置oldpos,以获取指定3D坐标在2D空间中的新位置,并将结果作为double返回。

总体而言,这段代码实现了将3D坐标简单透视投影到2D平面上的功能,给定摄像机位置和视野距离。它是更复杂的透视投影公式的简化版本,但仍可以为某些应用程序产生有用的结果。

我看到许多解决此问题的三角解决方案,我认为可以更有效地解决这个问题,所以我找到了这个公式(fovl / (fovl + z)) * oldpos)。

通过一些基本的轴旋转(使用java swing制作)获得的结果: result2

result1


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