Volume Mass calculator

Hi

does anybody know of a script that can calculate the volume or mass of a closed mesh object?

Hi,

based on http://stackoverflow.com/questions/1406029/how-to-calculate-the-volume-of-a-3d-mesh-object-the-surface-of-which-is-made-up, I created the following script:

import bpy

def SignedTriangleVolume(v1, v2, v3):
    return v1.dot(v2.cross(v3)) / 6.0

def TriangleMeshVolume():
    polygons = bpy.context.active_object.data.polygons
    vertices = bpy.context.active_object.data.vertices
    
    volume = 0
    for polygon in polygons:
        volume += SignedTriangleVolume(vertices[polygon.vertices[0]].co, vertices[polygon.vertices[1]].co, vertices[polygon.vertices[2]].co)
        
    return abs(volume)


if __name__ == "__main__":
    print(TriangleMeshVolume())

It’s very rough and has several restrictions:

  • it only works on triangle meshes (no quads or anything) and the currently selected object
  • it does not respect the scaling of the object (in Object Mode, so apply the scale before you evaluate the volume)
  • it outputs the result in the system console and has no UI

these restrictions could easily be overcome, but with a little more time (which I am lacking at the moment)

best regards
blackno666

I copy the text into the note editor and run the script while having the object selected?

Here you go, works on tessfaces (so no matter if tris, quads or ngons), takes object scale into account and prints to info area. Paste code in text editor, run, then hit Spacebar over 3d view and type “Mesh Volume”

import bpy

class MeshVolume(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.mesh_volume"
    bl_label = "Mesh Volume"


    @classmethod
    def poll(cls, context):
        return (context.active_object is not None and
                context.active_object.type == 'MESH')


    def execute(self, context):
        volume = 0
        ob = context.active_object
        ob_mat = ob.matrix_world
        me = ob.data
        me.calc_tessface()
        for tf in me.tessfaces:
            tfv = tf.vertices
            if len(tf.vertices) == 3:
                tf_tris = (me.vertices[tfv[0]], me.vertices[tfv[1]], me.vertices[tfv[2]]),
            else:
                tf_tris = (me.vertices[tfv[0]], me.vertices[tfv[1]], me.vertices[tfv[2]]),\
                          (me.vertices[tfv[2]], me.vertices[tfv[3]], me.vertices[tfv[0]])
                          
            for tf_iter in tf_tris:
                v1 = ob_mat * tf_iter[0].co
                v2 = ob_mat * tf_iter[1].co
                v3 = ob_mat * tf_iter[2].co
                
                volume += v1.dot(v2.cross(v3)) / 6.0
        self.report({'INFO'}, "Volume: %2.f" % volume)
        return {'FINISHED'}




def register():
    bpy.utils.register_class(MeshVolume)




def unregister():
    bpy.utils.unregister_class(MeshVolume)




if __name__ == "__main__":
    register()



This isn’t optimized in any way and did not change the way of calculation

Oddly it only says that the volume is “0” ???

the Volume has been output with no significant digits: so change the line:

self.report({'INFO'}, "Volume: %2.f" % volume)

to

self.report({'INFO'}, "Volume: %.2f" % volume)

(the %.2f) means to print two significant digits (change to your liking, e.g. %.4f for a more precise output)

There’s a Volume option in the Measure Panel addon. Other than not accepting ngons, it seems to be in working order.

ENCN

the script works well. Really too bad that I googled for a measure tool but nothing came up in Google besides scripts from 2005.

COD and Blackno

thanks for the effort as well. The script works, just needed to adjust the decimale steps after the dot because I measure a small object.

Nice script !
Thanks

Included 3d print toolbox addon has volume calculation.

Thanks, It works well