如何为给定的点创建最小的OOBB?创建AABB或球体很容易,但我在创建最小OOBB时遇到了问题。
[编辑]
第一个答案没有给出好的结果。我没有大量的点,只有少量的点。 我正在进行碰撞几何生成。例如,立方体有36个点(6个面,每个面2个三角形,每个三角形3个点)。 第一个帖子的算法在立方体上给出了错误的结果。 立方体的示例点:http://nopaste.dk/download/3382 (应返回标识轴)。
如何为给定的点创建最小的OOBB?创建AABB或球体很容易,但我在创建最小OOBB时遇到了问题。
[编辑]
第一个答案没有给出好的结果。我没有大量的点,只有少量的点。 我正在进行碰撞几何生成。例如,立方体有36个点(6个面,每个面2个三角形,每个三角形3个点)。 第一个帖子的算法在立方体上给出了错误的结果。 立方体的示例点:http://nopaste.dk/download/3382 (应返回标识轴)。
如您所述,对象没有大量顶点时,运行时间应该是可以接受的。
在http://www.gamedev.net/topic/320675-how-to-create-oriented-bounding-box/上的讨论中,上述库的作者对该主题进行了更详细的说明:
Gottschalk构建OBB的方法是为点集计算协方差矩阵。该矩阵的特征向量是OBB轴。点的平均值是OBB中心。OBB不能保证具有所有包含盒子中最小的体积。通过递归分裂顶点为点集的三角网格来构建OBB树。提到了一些启发式方法用于分裂。
包含点集的最小体积框(MVB)是包含点凸壳的最小体积框。外壳是一个凸多面体。基于Joe O'Rourke的结果,MVB由多面体面支撑或多面体的三条互相垂直的边支撑。"被一个面支持"意味着MVB具有与多面体面重合的面。"由三条垂直的边支撑"意味着MVB的三条垂直边与多面体的边重合。
正如jyk所指出的,这些算法的实施都不是轻松的。不过,永远不要因此而放弃尝试 :) AABB可能是一个好选择,但它也可能非常不匹配。考虑一个“细”圆柱体,端点为(0,0,0)和(1,1,1)[想象圆柱体是连接这些点的线段]。AABB是0 <= x <= 1, 0 <= y <= 1和 0 <= z <= 1,体积为1。MVB的中心为(1,1,1)/2,轴为(1,1,1)/sqrt(3),沿该轴的延伸长度为sqrt(3)/2。它还具有两个垂直于第一轴的额外轴,但其延伸距离为0。该盒子的体积为0。如果给线段留一点厚度,那么MVB会变得稍微大一些,但仍然比AABB的体积小得多。
你选择哪种类型的盒子应该取决于你自己的应用程序数据。
所有这些的实现都在我的www.geometrictools.com网站上。我使用中位数分割启发式来构建边界体树。MVB构造需要在2D中找到凸包查找器,在3D中找到凸包查找器以及计算包含一组平面点的最小区域框的方法——我使用旋转卡尺法来实现。
首先你需要计算点的质心,伪代码如下:
mu = sum(0..N, x[i]) / N
那么你需要计算协方差矩阵
C = sum(0..N, mult(x[i]-mu, transpose(x[i]-mu)));
注意,mult是通过(1x3)矩阵乘法和(3x1)矩阵乘法进行计算的,结果是一个3x3的矩阵。
C矩阵的特征向量定义了OBB的三个轴。
有一个名为ApproxMVBB
的新C++库在线上发布,它可以计算出最小体积边界框的近似值。它是根据MPL 2.0许可证发布的,且由我编写。
如果您有时间,请访问:http://gabyx.github.io/ApproxMVBB/
该库与C++11兼容,仅需要Eigenhttp://eigen.tuxfamily.org即可。测试表明,在合理的时间内(约5-7秒,取决于您对近似值的设置),可以计算出3D中1.4亿个点的近似值。
find_package(ApproxMVBB,...
很容易将其用于你的项目中。如果与其他库集成困难,请考虑在GitHub上添加一个问题。 - Gabriel