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.
-
2It is enough to check angles between neighbouring faces? If there are two neigbouring polygons (probably triangles) with angle between them larger than pi (180) than mesh is concave. – Ante Feb 08 '14 at 08:20
-
yep I agree but be careful if your mesh has not strict winding rule then is very hard to identify which side of face is which. btw thorus has concave faces on the inside of the ring ... if mesh contains at least one concave face pair then it is concave !!! for speed is enough to check all adjacent normals to each other – Spektre Feb 09 '14 at 11:20
-
Just for clarification: Are you trying to determine, if the surface defined by the mesh is convex, or are you trying to determine if the set of points delimited by the mesh (as a boundary) is convex? – datenwolf Oct 15 '16 at 07:42
5 Answers
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.

- 99,986
- 12
- 185
- 204
-
Thanks but comparing the object to the convex hull wouldn't work because the topology will be different. – Joan Venge Feb 08 '14 at 01:56
-
That depends how you compare: if you do it topologically then you'll probably see a difference. If you do it by other means then you won't. – Tommy Feb 08 '14 at 02:57
-
You are right. I assumed volume comparison wouldn't be accurate. Not sure how else I can compare but I need a fast way to do this and unfortunately the built-in convex hull generator is very slow. – Joan Venge Feb 08 '14 at 04:59
-
You gave us a few really good ideas, but if I had to choose I'd vote for the 2nd one :) . – kolenda Feb 13 '14 at 19:35
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(F.V)
, 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;
}

- 33
- 5

- 31
- 1
-
1Thank you for your answer. It would be nice if you could add details how your algorithm works. Code only answers are discouraged, because they may work or not, but it is unclear why and harder to spot if they contain mistakes. – allo Nov 12 '18 at 09:47
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)"

- 11,217
- 6
- 43
- 49
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.

- 187
- 10