如何检查3d网格的凸度?

时间:2014-02-08 01:07:12

标签: graphics 3d game-engine computational-geometry convex-hull

有快速的方法吗?在线搜索显示函数或单个多边形的凸性。但我需要能够检查整个模型。物体可以具有凸面,但可以像圆环一样整体凹陷。

5 个答案:

答案 0 :(得分:7)

Kneejerk:如果您构建一个绿叶的BSP树并以一个节点结束所有几何体,则该对象是凸的。

采用相同解决方案的更智能方法:对于每个多边形,获取超平面。确保模型中的每个顶点都在超平面后面。

等价:检查每对顶点之间的线段;如果它没有与任何面相交,则该对象是凸的。

我猜你也可以通过quickhull或其他任何方式获得凸包,并将其与原始对象进行比较。或者,类似地,获取凸包,并检查原始对象的每个顶点是否位于船体的一个面上。

答案 1 :(得分:2)

bool IsConvex(std::vector<vec3> &points, std::vector<int> &triangles, float threshold = 0.001)
{
    for (unsigned long i = 0; i < triangles.size() / 3; i++)
    {

        vec3 Atmp = points[triangles[i * 3 + 0]];
        vec3 Btmp = points[triangles[i * 3 + 1]];
        vec3 Ctmp = points[triangles[i * 3 + 2]];

        btVector3 A(Atmp.x, Atmp.y, Atmp.z);
        btVector3 B(Btmp.x, Btmp.y, Btmp.z);
        btVector3 C(Ctmp.x, Ctmp.y, Ctmp.z);
        B -= A;
        C -= A;

        btVector3 BCNorm = B.cross(C).normalized();

        float checkPoint = btVector3(points[0].x - A.x(), points[0].y - A.y(), points[0].z - A.z()).dot(BCNorm);
        for (unsigned long j = 0; j < points.size(); j++)
        {

            float dist = btVector3(points[j].x - A.x(), points[j].y - A.y(), points[j].z - A.z()).dot(BCNorm);

            if(std::abs(checkPoint) > threshold & std::abs(dist) > threshold & checkPoint * dist < 0)
            {
                return false;
            }
        }
    }

    return true;
}

答案 2 :(得分:1)

对于每个面,计算支撑平面的方程,并在插入平面方程时检查所有顶点*是否产生相同的符号。

O(F.V)个面和F个顶点需要花费时间V

*为安全起见,请忽略正在处理的面的顶点。

或者,在时间O(V.Log(V))内计算3D凸包。如果算法中的任何阶段都丢弃了一个顶点,那么多面体就不会凸起。

答案 3 :(得分:1)

trimesh是一个Python库,可以加载3D网格并评估网格是否凸起。

import trimesh
mesh = trimesh.load('my_mesh_file')
print(mesh.is_convex)

代码here

可以使用以下说明从命令行运行它:

python -m pip install trimesh
python -c "import trimesh; mesh = trimesh.load('my_mesh_file'); print(mesh.is_convex)"

答案 4 :(得分:0)

您可以通过首先将所有顶点添加到树结构来加速平面顶点测试,因此如果它们的边界不与平面相交,则可以拒绝整个叶子。 BSP的想法应该与测试所有三角形平面完全相同,因为没有BSP叶子能够细分凸对象的顶点集。

您可能希望为平面测试包含一个epsilon,因为手动创建的网格的浮点精度和建模精度都会导致顶点略高于平面。