5

The 3D print toolbox currently only outputs the volume/area of all faces.

How can I get the volume of selected mesh objects, ignoring certain faces?


Asking on behalf of a user who mailed me.

ideasman42
  • 47,387
  • 10
  • 141
  • 223

1 Answers1

7

This can be done using the Python API to get the mesh with modifiers applied, then applying the transform matrix.

The following script applies to all selected objects, showing a popup with the final volume. Not that it does not use units or scene scale.

See is_face_volume for the method of checking if a face should be included in volume calculations.

import bpy
from bpy import context

Quick way to test with/without hidden faces

USE_FILTER_FACES = True

def report_info(title="", message=""): # show in console print(title, message) # show in popup def draw_cb(self, context): self.layout.label(text=message) context.window_manager.popup_menu(draw_func=draw_cb, title=title, icon='INFO')

def is_face_skip(f): """Ignore faces that pass this test!""" return f.hide is False # You may want to filter based on material. # return f.material_index == 0

def bmesh_from_object_final(ob): import bmesh matrix = ob.matrix_world me = ob.to_mesh() me.transform(matrix) bm = bmesh.new() bm.from_mesh(me) if USE_FILTER_FACES: faces_remove = [f for f in bm.faces if not is_face_skip(f)] for f in faces_remove: bm.faces.remove(f) return (bm, matrix.is_negative)

def volume_and_area_from_object(ob): bm, is_negative = bmesh_from_object_final(ob) volume = bm.calc_volume(signed=True) area = sum(f.calc_area() for f in bm.faces) bm.free() if is_negative: volume = -volume return volume, area

def main(): volume = 0.0 area = 0.0 object_count = 0 for ob in context.selected_objects: if ob.type != 'MESH': continue volume_single, area_single = volume_and_area_from_object(ob) volume += volume_single area += area_single object_count += 1 volume = abs(volume)

report_info(
    title="From %d object(s)" % object_count,
    message="Volume: %.4f, Area: %.4f" % (volume, area),
)

if name == "main": main()

ideasman42
  • 47,387
  • 10
  • 141
  • 223
  • The Object.to_mesh method only takes in the preserve_all_data_layers and depsgraph parameters on Blender 2.8 with the 3D Printing Toolkit addon installed. Am I missing something still? – Ziad Sep 30 '19 at 09:14
  • Updated for Blender 2.93 – ideasman42 Mar 09 '21 at 11:09