79

I want to calculate the volume of a 3D mesh object having a surface made up triangles.

user1118321
  • 25,567
  • 4
  • 55
  • 86

4 Answers4

122

Reading this paper, it is actually a pretty simple calculation.

The trick is to calculate the signed volume of a tetrahedron - based on your triangle and topped off at the origin. The sign of the volume comes from whether your triangle is pointing in the direction of the origin. (The normal of the triangle is itself dependent upon the order of your vertices, which is why you don't see it explicitly referenced below.)

This all boils down to the following simple function:

public float SignedVolumeOfTriangle(Vector p1, Vector p2, Vector p3) {
    var v321 = p3.X*p2.Y*p1.Z;
    var v231 = p2.X*p3.Y*p1.Z;
    var v312 = p3.X*p1.Y*p2.Z;
    var v132 = p1.X*p3.Y*p2.Z;
    var v213 = p2.X*p1.Y*p3.Z;
    var v123 = p1.X*p2.Y*p3.Z;
    return (1.0f/6.0f)*(-v321 + v231 + v312 - v132 - v213 + v123);
}

and then a driver to calculate the volume of the mesh:

public float VolumeOfMesh(Mesh mesh) {
    var vols = from t in mesh.Triangles
               select SignedVolumeOfTriangle(t.P1, t.P2, t.P3);
    return Math.Abs(vols.Sum());
}
AugSB
  • 249
  • 1
  • 5
  • 16
Frank Krueger
  • 69,552
  • 46
  • 163
  • 208
  • 3
    Quite an elegant solution. – levis501 Mar 22 '13 at 01:37
  • I’m wondering why this wasn’t discovered before 2001. Or it was, but had no relevance? – Lenar Hoyt Sep 16 '13 at 22:47
  • 2
    Oct 1984, the paper "A symbolic method for calculating the integral properties of arbitrary nonconvex polyhedra" was published and describe this method to compute the volume. It's also a more or less a trivial method, so you need much more than just this information to publish a paper. – R.Falque Sep 24 '13 at 05:53
  • 3
    "topped off at the origin" is not mandatory, you may choose any fixed point. And if the object is quite far from the origin, this will lead to numerical instability. Better choose an arbitrary point from the mesh – galinette Sep 07 '14 at 15:55
  • I calculate volume based on same geometry. First, I get volume from solid mesh. Then I extract surface and calculate the volume based on this algorithm. The result is different. The former is 16.46584046 while the later is 16.46596493 – ytyyutianyun May 07 '18 at 21:20
  • how to understand the derivation of the formula from scratch please? – mrtechmaker May 22 '18 at 15:51
  • a big object with low poly(less triangle) will have less volume compare to the small object with more poly count(greater triangle). Is this correct approach? – Muhammad Faizan Khan Nov 23 '18 at 04:33
  • According to the paper, to use this method, you need to check that the vertices of the triangles are ordered consistently. Which is a good practice and is usually the case. If you want to be thorough, though, you need to check this. Once. – geriwald Aug 06 '20 at 16:04
  • this is incredible, thanks! I thought this would end being really complicated.. – treeseal7 Nov 16 '21 at 18:26
  • it's not obvious to me how this would work for non-convex shapes. – Quantum Guy 123 Dec 17 '21 at 19:18
  • @QuantumGuy123 the paper referenced here says "To start with our algorithm, let us make the assumption that the polygon is close. If it is not, a contour close process can be performed first [9]. " – Bugbeeb Jul 07 '22 at 03:07
  • 1
    @KaranAhuja In 2D, this is a simple computer application of Green's theorem (see e.g. planimeters): you can calculate the area enclosed by a curve by a line integral over the curve. In 3D it's an application of the divergence theorem (Gauss' theorem): you can calculate the volume enclosed by a boundary surface by a flux integral over that boundary (for a vector field whose divergence is 1). The boundaries do not need to be convex, but they need to be closed. – armando.sano Sep 29 '22 at 06:13
38

Yip Frank Kruegers answer works well +1 for that. If you have vector functions available to you you could use this too:

    public static float SignedVolumeOfTriangle(Vector p1, Vector p2, Vector p3)
    {
        return p1.Dot(p2.Cross(p3)) / 6.0f;
    }

edit .. added impl. for Dot() and Cross() if you are unsure. Most Math libs will have these. If you are using WPF they are implemented as static methods of the Vector3D class.

    public class Vector
    {
        ... 

        public float Dot(Vector a)
        {
            return this.X * a.X + this.Y * a.Y + this.Z * a.Z;
        }

        public Vector Cross(Vector a)
        {
            return new Vector(
              this.Y * a.Z - this.Z * a.Y,
              this.Z * a.X - this.X * a.Z,
              this.X * a.Y - this.Y * a.X
            );
        }
        ...
    }
Ross Oliver
  • 1,075
  • 1
  • 11
  • 15
  • perhaps post code for Dot() AND Cross()? (both trivial to implement, but for completeness). BTW, @Frank Kruegers answer is what you get if you simplify p1.Dot(p2.Cross(p3)) / 6.0f – Mitch Wheat Jan 03 '13 at 23:18
4

The GNU Triangulated Surface Library can do this for you. Keep in mind that the surface must be closed. That is not going to be the case for quite a few 3D models.

If you want to implement it yourself, you could start by taking a look at their code.

Jay Kominek
  • 8,674
  • 1
  • 34
  • 51
  • 8
    If you do reimplement this, please be careful - the GTS library is LGPL, so any derivative work must be LGPL or GPL. – Cascabel Sep 10 '09 at 16:00
0

The method above is correct for "simple" objects (no intersecting/overlapping triangles) like spheres tetrahedras and so on. For more complex shapes, a good idea could be to segment the mesh (close it) and calculate the volume of each segment separately. Hope this helps.

Anoroah
  • 1,987
  • 2
  • 20
  • 31
  • 4
    if volume is signed you do not need the center to be inside – makc Oct 15 '15 at 13:59
  • 2
    Wrong answer. The method described is correct for arbitrarily complex closed objects with no intersecting/overlapping triangles, and there is no requirement on position of the center point. That's because the tetrahedron "volumes" are signed and add algebraically. – galinette Mar 10 '16 at 22:02
  • @galinette Yes you are right. By "simple" objects i meant objects with no intersecting/overlapping triangles. Also the center of the mesh can be outside. – Anoroah Jul 22 '16 at 15:26
  • cut it with 3d boolean operations – Aquarius Power May 18 '17 at 10:51