简体   繁体   中英

How to check for convexity of a 3d mesh?

Is there a fast way to do this? Searching online shows convexity of functions or single polygons. But I need the ability to check this for the whole model. An object can have convex faces but can be concave as a whole like a torus.

Kneejerk: if you build a leafy BSP tree and end up with all your geometry at one node, the object is convex.

Slightly smarter way to approach the same solution: for each polygon, get the hyperplane. Make sure every vertex in the model is behind that hyperplane.

Equivalently: check the line segment between every pair of vertices; if it doesn't intersect any faces then the object is convex.

I guess you could also get the convex hull, via quickhull or whatever, and compare it to the original object. Or, similarly, get the convex hull and check that every vertex of the original object lies on a face of the hull.

For every face, compute the equation of the plane of support and check that all vertices* yield the same sign when plugged in the plane equation.

Will take time O(FV) , for F faces and V vertices.

*For safety, disregard the vertices of the face being processed.

Alternatively, compute the 3D convex hull, in time O(V.Log(V)) . If at any stage in the algorithm a vertex gets discarded, then the polyhedron was not convex.

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;
}

trimesh is a Python library that can load a 3D mesh and evaluates if mesh is convex or not.

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

Code is given here .

It can be run from a command line with the following instructions:

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

You can accelerate the plane-vertex tests by adding all vertices to a tree structure first, so you can reject whole leaves if their bounds don't intersect the plane. The BSP idea should actually be identical to testing all triangle planes, as no BSP leaf will be able to subdivide the set of vertices for a convex object.

You probably want to include an epsilon for your plane tests, as both floating point precision and modelling precision for manually created meshes can result in vertices slightly above a plane.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM