我在屏幕空间中有4个2D点,​​我需要将它们反向投影回3D空间。 我知道4个点中的每一个都是3D旋转刚性矩形的一个角,我知道矩形的大小。 如何从中获取3D坐标?

我没有使用任何特定的API,我没有现有的投影矩阵。 我只是在寻找基本的数学来做到这一点。 当然没有足够的数据将单个2D点转换为3D而没有其他参考,但我想如果你有4个点,你知道它们在同一个平面上都是直角相交的,而且你知道它们之间的距离,你应该能够从中找出它。 不幸的是,我无法解释如何。

这可能属于摄影测量的范畴,但谷歌搜索它并没有让我获得任何有用的信息。

===============>>#1 票数:67

好吧,我来到这里寻找答案并没有找到简单明了的东西,所以我继续前进并做了一个愚蠢但有效(而且相对简单)的事情:蒙特卡洛优化。

非常简单地说,算法如下:随机扰动您的投影矩阵,直到它将您已知的3D坐标投影到您已知的2D坐标。

这是Thomas the Tank Engine的静态照片:

托马斯坦克引擎

假设我们使用GIMP来找到地平面上我们认为是正方形的二维坐标(它是否真的是一个正方形取决于您对深度的判断):

带有正方形的轮廓

我在2D图像中得到四个点: (318, 247)(326, 312)(418, 241)(452, 303)

按照惯例,我们说这些点应该对应于3D点: (0, 0, 0)(0, 0, 1)(1, 0, 0)(1, 0, 1) 换句话说,y = 0平面中的单位平方。

将这些3D坐标中的每一个投影到2D中是通过将4D矢量[x, y, z, 1]与4×4投影矩阵相乘,然后将x和y分量除以z以实际获得透视校正来完成的。 这或多或少是gluProject()所做的,除了gluProject()也考虑当前视口并考虑单独的模型视图矩阵(我们可以假设模型视图矩阵是单位矩阵)。 查看gluProject()文档非常方便,因为我实际上想要一个适用于OpenGL的解决方案,但要注意文档在公式中缺少z的除法。

请记住,算法是从一些投影矩阵开始并随机扰动它直到它给出我们想要的投影。 所以我们要做的是投影四个3D点中的每一个,看看我们到达我们想要的2D点的距离。 如果我们的随机扰动导致投影的2D点更接近我们上面标记的那些,那么我们将该矩阵保持为对我们的初始(或先前)猜测的改进。

让我们来定义我们的观点:

# Known 2D coordinates of our rectangle
i0 = Point2(318, 247)
i1 = Point2(326, 312)
i2 = Point2(418, 241)
i3 = Point2(452, 303)

# 3D coordinates corresponding to i0, i1, i2, i3
r0 = Point3(0, 0, 0)
r1 = Point3(0, 0, 1)
r2 = Point3(1, 0, 0)
r3 = Point3(1, 0, 1)

我们需要从一些矩阵开始,身份矩阵似乎是一个自然的选择:

mat = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]

我们需要实际实现投影(基本上是矩阵乘法):

def project(p, mat):
    x = mat[0][0] * p.x + mat[0][1] * p.y + mat[0][2] * p.z + mat[0][3] * 1
    y = mat[1][0] * p.x + mat[1][1] * p.y + mat[1][2] * p.z + mat[1][3] * 1
    w = mat[3][0] * p.x + mat[3][1] * p.y + mat[3][2] * p.z + mat[3][3] * 1
    return Point(720 * (x / w + 1) / 2., 576 - 576 * (y / w + 1) / 2.)

这基本上是gluProject()所做的,720和576分别是图像的宽度和高度(即视口),我们从576中减去以计算我们从顶部开始计算y坐标而OpenGL通常计数的事实他们从底部。 您会注意到我们没有计算z,因为我们在这里并不需要它(尽管它可以很方便地确保它落在OpenGL用于深度缓冲区的范围内)。

现在我们需要一个函数来评估我们与正确解决方案的接近程度。 此函数返回的值是我们将用于检查一个矩阵是否优于另一个矩阵的值。 我选择了平方距离的总和,即:

# The squared distance between two points a and b
def norm2(a, b):
    dx = b.x - a.x
    dy = b.y - a.y
    return dx * dx + dy * dy

def evaluate(mat): 
    c0 = project(r0, mat)
    c1 = project(r1, mat)
    c2 = project(r2, mat)
    c3 = project(r3, mat)
    return norm2(i0, c0) + norm2(i1, c1) + norm2(i2, c2) + norm2(i3, c3)

为了扰乱矩阵,我们只需在某个范围内选择一个随机量扰动的元素:

def perturb(amount):
    from copy import deepcopy
    from random import randrange, uniform
    mat2 = deepcopy(mat)
    mat2[randrange(4)][randrange(4)] += uniform(-amount, amount)

(值得注意的是我们的project()函数实际上根本没有使用mat[2] ,因为我们不计算z,并且因为我们所有的y坐标都是0,所以mat[*][1]值无关紧要好吧。我们可以使用这个事实并且永远不会试图扰乱这些值,这会带来一个小的加速,但这是一个练习...)

为方便起见,让我们通过在目前为止找到的最佳矩阵上反复调用perturb()来添加一个能够完成大部分近似的函数:

def approximate(mat, amount, n=100000):
    est = evaluate(mat)

    for i in xrange(n):
        mat2 = perturb(mat, amount)
        est2 = evaluate(mat2)
        if est2 < est:
            mat = mat2
            est = est2

    return mat, est

现在剩下要做的就是运行它......:

for i in xrange(100):
    mat = approximate(mat, 1)
    mat = approximate(mat, .1)

我发现这已经给出了一个非常准确的答案。 运行一段时间后,我发现的矩阵是:

[
    [1.0836000765696232,  0,  0.16272110011060575, -0.44811064935115597],
    [0.09339193527789781, 1, -0.7990570384334473,   0.539087345090207  ],
    [0,                   0,  1,                    0                  ],
    [0.06700844759602216, 0, -0.8333379578853196,   3.875290562060915  ],
]

误差约为2.6e-5 (请注意我们所说的元素在计算中没有使用的元素实际上并没有从我们的初始矩阵中改变;这是因为更改这些条目不会改变评估的结果,因此改变永远不会被带走。)

我们可以使用glLoadMatrix()将矩阵传递给OpenGL(但是请记住首先将其转置,并记住使用单位矩阵加载模型视图矩阵):

def transpose(m):
    return [
        [m[0][0], m[1][0], m[2][0], m[3][0]],
        [m[0][1], m[1][1], m[2][1], m[3][1]],
        [m[0][2], m[1][2], m[2][2], m[3][2]],
        [m[0][3], m[1][3], m[2][3], m[3][3]],
    ]

glLoadMatrixf(transpose(mat))

现在我们可以例如沿z轴平移以沿轨道获得不同的位置:

glTranslate(0, 0, frame)
frame = frame + 1

glBegin(GL_QUADS)
glVertex3f(0, 0, 0)
glVertex3f(0, 0, 1)
glVertex3f(1, 0, 1)
glVertex3f(1, 0, 0)
glEnd()

随着3D翻译

从数学的角度来看,这不是很优雅; 你没有得到一个封闭形式的等式,你只需将你的数字插入并得到一个直接(和准确)的答案。 但是,它确实允许您添加其他约束,而不必担心使方程复杂化; 例如,如果我们想要合并高度,我们可以使用房子的那个角,并说(在我们的评估函数中)从地面到屋顶的距离应该是某某,并再次运行算法。 所以,是的,这是一种蛮力,但有效,并且运作良好。

Choo choo!

===============>>#2 票数:7

这是基于标记的增强现实的经典问题。

您有一个方形标记(2D条形码),并且在找到标记的四个边缘后,您想要找到它的Pose(相对于相机的平移和旋转)。 综述图片

我不知道该领域的最新贡献,但至少有一点(2009)RPP应该胜过上面提到的POSIT(并且确实是一种经典的方法)请看链接,他们也提供来源。

(PS - 我知道这有点老话题,但无论如何,帖子可能对某人有帮助)

===============>>#3 票数:5

D. DeMenthon设计了一种算法,用于在了解对象模型时从2D图像中的要素点计算对象的姿势 (其在空间中的位置和方向) - 这是您的确切问题

我们描述了一种从单个图像中找到对象姿势的方法。 我们假设我们可以在图像中检测并匹配对象的四个或更多非共面特征点,并且我们知道它们在对象上的相对几何形状。

该算法被称为Posit,并在其经典文章“25行代码中基于模型的对象姿势”(可在其网站上获得 ,第4节)中描述。

直接链接到文章: http//www.cfar.umd.edu/~daniel/daniel_papersfordownload/Pose25Lines.pdf OpenCV实现: http//opencv.willowgarage.com/wiki/Posit

该想法是通过缩放的正交投影重复近似透视投影,直到收敛到精确的姿势。

===============>>#4 票数:4

从2-D空间可以建造2个有效的矩形。 在不知道原始矩阵投影的情况下,您将不知道哪一个是正确的。 它与“盒子”问题相同:你看到两个正方形,一个在另一个里面,4个内部顶点连接到4个相应的外部顶点。 你是从上到下还是从下往上看盒子?

话虽这么说,你正在寻找一个矩阵变换T ...

{{x1,y1,z1},{x2,y2,z2},{x3,y3,z3},{x4,y4,z4}} x T = {{x1,y1},{x2,y2},{ x3,y3},{x4,y4}}

(4 x 3)x T =(4 x 2)

因此T必须是(3 x 2)矩阵。 所以我们有6个未知数。

现在构建一个T约束系统并用Simplex求解。 要构建约束,您知道通过前两个点的直线必须与传递到后两个点的直线平行。 你知道通过点1和3的直线必须与通过点2和4的直线平行。你知道通过1和2的直线必须与通过点2和3的直线正交。你知道长度1和2中的行必须等于3和4行的长度。您知道从1和3开始的行的长度必须等于2和4行的长度。

为了使这更容易,你知道矩形,所以你知道所有边的长度。

这应该给你很多限制来解决这个问题。

当然,要回来,你可以找到T-inverse。

@Rob:是的,有无数个投影,但不是无数个项目,其中点必须满足矩形的要求。

@nlucaroni:是的,如果投影中有四个点,这只能解决。 如果矩形投影到仅2个点(即矩形的平面与投影表面正交),则无法解决此问题。

嗯......我应该回家写这个小宝石。 这听起来很有趣。

更新:

  1. 除非您修复其中一个点,否则会有无数个投影。 如果你固定原始矩形的点,那么有两个可能的原始矩形。

===============>>#5 票数:4

对于我的OpenGL引擎,以下片段将鼠标/屏幕坐标转换为3D世界坐标。 阅读提交内容,了解实际情况。

/*   FUNCTION:        YCamera :: CalculateWorldCoordinates
     ARGUMENTS:       x         mouse x coordinate
                      y         mouse y coordinate
                      vec       where to store coordinates
     RETURN:          n/a
     DESCRIPTION:     Convert mouse coordinates into world coordinates
*/

void YCamera :: CalculateWorldCoordinates(float x, float y, YVector3 *vec) { // START GLint viewport[4]; GLdouble mvmatrix[16], projmatrix[16];

 GLint real_y; GLdouble mx, my, mz; glGetIntegerv(GL_VIEWPORT, viewport); glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix); glGetDoublev(GL_PROJECTION_MATRIX, projmatrix); real_y = viewport[3] - (GLint) y - 1; // viewport[3] is height of window in pixels gluUnProject((GLdouble) x, (GLdouble) real_y, 1.0, mvmatrix, projmatrix, viewport, &mx, &my, &mz); /* 'mouse' is the point where mouse projection reaches FAR_PLANE. World coordinates is intersection of line(camera->mouse) with plane(z=0) (see LaMothe 306) Equation of line in 3D: (x-x0)/a = (y-y0)/b = (z-z0)/c Intersection of line with plane: z = 0 x-x0 = a(z-z0)/c <=> x = x0+a(0-z0)/c <=> x = x0 -a*z0/c y = y0 - b*z0/c */ double lx = fPosition.x - mx; double ly = fPosition.y - my; double lz = fPosition.z - mz; double sum = lx*lx + ly*ly + lz*lz; double normal = sqrt(sum); double z0_c = fPosition.z / (lz/normal); vec->x = (float) (fPosition.x - (lx/normal)*z0_c); vec->y = (float) (fPosition.y - (ly/normal)*z0_c); vec->z = 0.0f; 

}

===============>>#6 票数:2

假设这些点确实是矩形的一部分,我给出了一个通用的想法:

找到具有最大间距的两个点:这些最可能定义一个对角线(例外:矩形几乎与YZ平面并列的特殊情况,留给学生)。 称它们为A,C。计算BAD,BCD角度。 与直角相比,这些可以让您在3d空间中进行定位。 要了解z距离,您需要将投影边与已知边相关联,然后,基于3D投影方法(是1 / z?),您可以在正确的轨道上了解距离。

===============>>#7 票数:2

要跟进Rons方法:如果您知道如何旋转矩形,则可以找到z值。

诀窍是找到进行投影的投影矩阵。 幸运的是,这是可能的,甚至便宜。 相关的数学可以在Paul Heckbert撰写的“图像变形的投影映射”一文中找到。

http://pages.cs.wisc.edu/~dyer/cs766/readings/heckbert-proj.pdf

这样,您可以恢复投影期间丢失的每个顶点的同质部分。

现在你还剩下四条线而不是点(正如罗恩解释的那样)。 既然您知道原始矩形的大小,那么什么都不会丢失。 您现在可以将Ron的方法和2D方法中的数据插入线性方程求解器并求解z。 您可以通过这种方式获得每个顶点的精确z值。

注意:这只适用于:

  1. 原始形状是一个矩形
  2. 您知道3D空间中矩形的确切大小。

这真是一个特例。

希望它有所帮助,尼尔斯

===============>>#8 票数:1

感谢@Vegard给出了一个很好的答案。 我稍微清理了一下代码:

import pandas as pd
import numpy as np

class Point2:
    def __init__(self,x,y):
        self.x = x
        self.y = y

class Point3:
    def __init__(self,x,y,z):
        self.x = x
        self.y = y
        self.z = z

# Known 2D coordinates of our rectangle
i0 = Point2(318, 247)
i1 = Point2(326, 312)
i2 = Point2(418, 241)
i3 = Point2(452, 303)

# 3D coordinates corresponding to i0, i1, i2, i3
r0 = Point3(0, 0, 0)
r1 = Point3(0, 0, 1)
r2 = Point3(1, 0, 0)
r3 = Point3(1, 0, 1)

mat = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
]

def project(p, mat):
    #print mat
    x = mat[0][0] * p.x + mat[0][1] * p.y + mat[0][2] * p.z + mat[0][3] * 1
    y = mat[1][0] * p.x + mat[1][1] * p.y + mat[1][2] * p.z + mat[1][3] * 1
    w = mat[3][0] * p.x + mat[3][1] * p.y + mat[3][2] * p.z + mat[3][3] * 1
    return Point2(720 * (x / w + 1) / 2., 576 - 576 * (y / w + 1) / 2.)

# The squared distance between two points a and b
def norm2(a, b):
    dx = b.x - a.x
    dy = b.y - a.y
    return dx * dx + dy * dy

def evaluate(mat): 
    c0 = project(r0, mat)
    c1 = project(r1, mat)
    c2 = project(r2, mat)
    c3 = project(r3, mat)
    return norm2(i0, c0) + norm2(i1, c1) + norm2(i2, c2) + norm2(i3, c3)    

def perturb(mat, amount):
    from copy import deepcopy
    from random import randrange, uniform
    mat2 = deepcopy(mat)
    mat2[randrange(4)][randrange(4)] += uniform(-amount, amount)
    return mat2

def approximate(mat, amount, n=1000):
    est = evaluate(mat)
    for i in xrange(n):
        mat2 = perturb(mat, amount)
        est2 = evaluate(mat2)
        if est2 < est:
            mat = mat2
            est = est2

    return mat, est

for i in xrange(1000):
    mat,est = approximate(mat, 1)
    print mat
    print est

用.1的近似调用对我来说不起作用,所以我把它拿出来了。 我跑了一会儿,最后我检查了它

[[0.7576315397559887, 0, 0.11439449272592839, -0.314856490473439], 
[0.06440497208710227, 1, -0.5607502645413118, 0.38338196981556827], 
[0, 0, 1, 0], 
[0.05421620936883742, 0, -0.5673977598434641, 2.693116299312736]]

误差大约为0.02。

===============>>#9 票数:1

是的,蒙特卡罗工作,但我找到了更好的解决方案。 此代码完美运行(并使用OpenCV):

Cv2.CalibrateCamera(new List<List<Point3f>>() { points3d }, new List<List<Point2f>>() { points2d }, new Size(height, width), cameraMatrix, distCoefs, out rvecs, out tvecs, CalibrationFlags.ZeroTangentDist | CalibrationFlags.FixK1 | CalibrationFlags.FixK2 | CalibrationFlags.FixK3);

此函数采用已知的3d和2d点,屏幕大小并返回旋转(rvecs [0]),平移(tvecs [0])和相机的内在值矩阵。 这就是你需要的一切。

===============>>#10 票数:1

如果没有人回答,我回家时会拿出线性代数书。 但@ DG,并非所有矩阵都是可逆的。 奇异矩阵不可逆 (当行列式= 0时)。 这实际上会一直发生,因为投影矩阵必须具有0和1的特征值,并且是正方形(因为它是幂等的,所以p ^ 2 = p)。

一个简单的例子是[[0 1] [0 1]],因为行列式= 0,这是x = y线上的投影!

===============>>#11 票数:1

您在2D表面上的投影具有无限多的3D矩形,这些矩形将投射到相同的2D形状。

这样考虑一下:你有四个构成3D矩形的3D点。 称它们为(x0,y0,z0),(x1,y1,z1),(x2,y2,z2)和(x3,y3,z3)。 将这些点投影到xy平面上时,会删除z坐标:(x0,y0),(x1,y1),(x2,y2),(x3,y3)。

现在,您想要投射回3D空间,您需要对z0,..,z3进行逆向工程。 但是任何一组z坐标a)在点之间保持相同的xy距离,并且b)保持形状为矩形将起作用。 所以,这个(无限)集的任何成员都会这样做:{(z0 + i,z1 + i,z2 + i,z3 + i)| 我< - R}。

编辑@Jarrett:想象一下,你解决了这个问题,并在3D空间中得到了一个矩形。 现在,想象一下在z轴上上下滑动该矩形。 那些无限量的翻译矩形都具有相同的xy投影。 你怎么知道你找到了“正确的”?

编辑#2:好的,这是我对这个问题的评论 - 一个更直观的推理方法。

想象一下,在你桌子上方拿一张纸。 假装纸张的每个角落都有一个无重力的激光指示器,它指向桌面。 纸张是3D物体,桌面上的激光指示点是2D投影。

现在,你怎么能通过只看激光指针点来判断纸张的高度?

你不能。 将纸张垂直向上和向下移动。 无论纸张的高度如何,激光指示器仍会照在桌面上的相同位置。

在反投影中找到z坐标就像试图根据桌面上的激光指针点找到纸张的高度。

===============>>#12 票数:1

当您从3D投影到2D时,您将丢失信息。

在单点的简单情况下,反投影将为您提供通过3d空间的无限光线。

立体重建通常从两个2d图像开始并且都投射回​​3D。 然后寻找产生的两条3D射线的交叉点。

投影可以采取不同的形式。 正交或透视。 我猜你正在假设正交投影?

在你的情况下假设你有原始矩阵,你将在3D空间中有4条射线。 然后,您可以通过3d矩形尺寸约束问题并尝试解决。

该解决方案将不是唯一的,因为围绕与2d投影平面平行的任一轴的旋转在方向上将是模糊的。 换句话说,如果2d图像垂直于z轴,则围绕x轴顺时针或逆时针旋转3d矩形将产生相同的图像。 同样适用于y轴。

在矩形平面与z轴平行的情况下,您可以获得更多解决方案。

由于您没有原始投影矩阵,因此任何投影中存在的任意比例因子都会引入更多的模糊性。 您无法区分投影中的缩放和z轴方向上的平移。 如果您只关心3d空间中4个点的相对位置(彼此相关而不是2d投影的平面),则这不是问题。

在透视投影中事情变得更难......

===============>>#13 票数:1

如果您知道形状是平面中的矩形,则可以进一步限制问题。 您当然无法弄清楚“哪个”平面,因此您可以选择它位于z = 0且其中一个角位于x = y = 0的平面上,并且边缘平行于x / y轴。

因此,3d中的点是{0,0,0},{w,0,0},{w,h,0}和{0,h,0}。 我很确定无法找到绝对大小,所以只有w / h的比例是不重要的,所以这是一个未知数。

相对于这个平面,相机必须在空间中的某个点cx,cy,cz,必须指向nx,ny,nz方向(长度为1的向量,因此其中一个是冗余的),并且具有focal_length / image_width因子w。 这些数字变成3x3投影矩阵。

这总共给出了7个未知数:w / h,cx,cy,cz,nx,ny和w。

你总共有8个知识:4 x + y对。

所以这可以解决。

下一步是使用Matlab或Mathmatica。

  ask by Joshua Carmody translate from so

未解决问题?本站智能推荐:

2回复

将2D点反转投影到3D

假设我们有一个带有平面的3d空间,其中有一个任意方程:ax + by + cz + d = 0现在假设我们在该平面上选择3个随机点:(x0,y0,z0)(x1,y1,z1 )(x1,y1,z1) 现在我对这架飞机有不同的观点(相机)。 我的意思是我有一个不同的相机,从不同的角度来看这个飞
1回复

从2D图像平面计算3D坐标以解决透视问题,而无需直接访问视图/投影矩阵

第一次在堆栈交换上提问,希望这是正确的地方。 我似乎无法针对我的情况开发足够接近的近似算法,因为就3D数学而言,我并不是最出色的算法。 我有一个3d环境,可以在其中访问任何对象(包括相机)的位置和旋转,还可以从任意两个点运行跟踪线以获取一个点和一个碰撞点之间的距离。 我也有相机的视
2回复

将3D点投影到2D平面[关闭]

设A是我有3D坐标x,y,z的点,我想将它们转换为2D坐标:x,y。 投影应在由给定法线定义的平面上正交。 平凡的情况,其中法线实际上是其中一个轴,它很容易解决,只是简单地消除了一个坐标,但其他情况如何更容易发生?
3回复

投影几何:如何将3D中的矩形投影转换为2D视图

所以问题是我有一个要转换为2D的矩形的3D投影。 那就是我有一张放在一张桌子上的纸的照片,我想将其转换为该纸的2D视图。 因此,我需要通过恢复所有3D /投影转换并从顶部获得图纸的普通视图来获得不失真的2D图像。 我碰巧找到了关于该主题的一些指导,但是他们没有建议立即就如何实现这一目标进行
4回复

3d到2d投影矩阵

我在3D空间中有3个点我知道确切的位置。 假设它们是: (x0,y0,z0) , (x1,y1,z1)和(x2,y2,z2) 。 此外,我有一个相机正在查看这3个点,我知道这三个点在相机视图平面上的2D位置。 因此,例如(x0,y0,z0)将是(x0',y0') ,并且(x1,y1,z
1回复

将3D点转换为2D点坐标系,反之亦然

我正在尝试将point(x,y,z)转换为point(u,v)。 我在Wiki中使用过方程式: http://en.wikipedia.org/wiki/N-vector#Converting_latitude.2Flongitude_to_n-vector 将点(3,2)转换为3
1回复

如何从2D坐标计算3D点?

最近,我遇到了涉及DirectX11和3D坐标计算的困境。 我希望将鼠标坐标转换为该3D坐标。 在将多边形模型(默认立方体等)或网格对象插入空白区域时,我希望它的行为类似于Maya或Unity。 我需要什么步骤和数学运算来计算此坐标?
1回复

Three.js-3D空间中的2D对象(通过顶点)

我有个问题: 我有一系列3D点。 如何在3D空间中绘制顶点提供的2D平面对象? 我想画从Points [0]到Points [1],从Points [1]到Points [2]等的线…现在我有以下解决方案: faceToTriangles(): 我是在前一段时间写的,在
2回复

是否有必要针对2D和3D几何以及机械问题分离数据结构和算法?

我已经开发了一个可以解决3D几何问题和特定3D机械问题的库。 现在,我受邀设计一个类似的库来解决2D问题。 我是否需要再次为2D情况重新定义类似的数据结构和算法? 有人可以给我一些建议吗? 如果我应该为2D库重新定义它们,您能告诉我一些分开2D和3D库的必要吗?
2回复

从3D网格生成2D横截面多边形

我正在编写一个游戏,该游戏使用3D模型绘制场景(自上而下的正投影),但使用2D物理引擎来计算对碰撞的反应等。我希望获得一些3D资源通过将3D网格与XY平面“切片”并从生成的边创建多边形,自动生成匹配盒。 Google在这方面让我失望(也没有关于SO的有用材料)。 有什么建议吗? 我