从点创建OOBB
Creating OOBB from points
如何为给定点创建最小OOBB?创建AABB或球体非常容易,但我在创建最小OOBB时遇到了问题。
[编辑]
第一个答案并没有给我带来好结果。我没有太多的分数。我的分数很少。我正在生成碰撞几何体。例如,立方体有36个点(6条边,每个边2个三角形,每个三角形3个点)。第一篇文章中的算法给立方体带来了糟糕的结果。立方体的示例点:http://nopaste.dk/download/3382(应返回标识轴)
PCA/协方差/特征向量方法本质上是找到近似对象顶点的椭球轴。它应该适用于随机对象,但对于像立方体这样的对称对象会产生糟糕的结果。这是因为立方体的近似椭球体是球体,而球体没有定义好的轴。所以你没有得到你期望的标准轴。
例如,如果你事先知道对象是一个立方体,你可以使用一种专门的方法,并对其他一切使用PCA。
另一方面,如果你想计算真正的OBB,你可以使用现有的实现,例如。http://www.geometrictools.com/LibMathematics/Containment/Containment.html(存档于https://web.archive.org/web/20110817024344/geometrictools.com/LibMathematics/Containment/Containment.html和https://github.com/timprepscius/GeometricTools/blob/master/WildMagic5/LibMathematics/Containment/Wm5ContMinBox3.cpp)。我相信这实现了你的问题评论中提到的算法。
引用自该页面:
ContMinBox3文件实现用于计算包含点。此方法计算点的凸包多面体。最小音量框其中一个面与凸多面体的面或具有由三个给出的轴方向相互垂直的边缘凸多面体。凸多面体由将多面体投影到平面面部,计算包含投影,并计算包含投影到脸。最小面积矩形和最小长度间隔组合为形成候选框。然后所有的三元组的边是已处理。如果任何三元组相互垂直边,最小的长方体轴在计算边缘。在所有这些盒子中,体积最小的是包含原始点集。
如果如您所说,对象没有大量顶点,则运行时间应该是可以接受的。
在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,11)/sqrt(3)和该轴的范围sqrt(3)/2。它还有两个垂直于第一个轴的附加轴,但范围为0。这个盒子的体积是0。如果给线段一点厚度,MVB会稍微变大,但体积仍然比AABB小得多。
您选择的框类型应取决于您自己的应用程序的数据。
所有这些的实现都在我的www.geometrictools.com网站上。我对边界体积树使用了中值分割启发式。MVB结构需要一个2D的凸包探测器,一个3D的凸包发射器,以及一种计算包含一组平面点的最小面积框的方法——我使用旋转卡尺方法。
首先,您必须在pseudcode 中计算点的质心
mu = sum(0..N, x[i]) / N
那么你必须计算协方差矩阵
C = sum(0..N, mult(x[i]-mu, transpose(x[i]-mu)));
注意,mult执行(3x1)矩阵乘以(1x3)矩阵乘法,结果是3x3矩阵。
C矩阵的特征向量定义了OBB的三个轴。
C++在线中有一个新的库ApproxMVBB
,它计算最小体积边界框的近似值。它是根据MPL2.0许可证发布的,由我撰写。
如果您有时间,请查看:http://gabyx.github.io/ApproxMVBB/
该库与C++11兼容,只需要Eigenhttp://eigen.tuxfamily.org.测试表明,根据您的近似设置,可以在合理的时间内(大约5-7秒)计算出1.4亿个3D点的近似值。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 使用std::multimap迭代器创建std::list
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 使用CMake创建QML插件
- 如何在c++中为模板函数实例创建快捷方式
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- OpenCV EqualizeHist()从彩色图像创建黑白图像
- 试图在visual studio上用C++创建一个桌面应用程序
- std::threads可以从Windows DLL中的全局变量创建/销毁吗?
- 如何在C++20中创建模板别名的推导指南
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 如何创建一个空的全局类并在启动时实例化它
- 无法创建抽象类的实例
- 链接到自行创建的dll失败
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++类内存结构中创建"spacer"?
- 终端不会为C++文件创建.exe文件吗
- 从点创建OOBB