Decimate only “bad” objects in a scene

I'm working for a company and they have to optimize 3d scenes to be rendered in virtual reality. The problem is that the people who are modeling the scenes are really bad at doing that. I've seen scenes where small objects had a really large amount of vertices (imagine a scene where a building has, let's say, 100 k vertices, and only one lamp has 15 k vertices...)

I want to write a script that decimates the geometry only for those objects that have an insane number of vertices but, how do I detect them?

I was thinking about computing the volume for each mesh and compare it with the number of vertices, but this would be really expensive and I'm not sure It's a good way to detect such meshes.

Any suggestions?

• I feel your pain. Had House model for VR, had hidden pipes in the walls that had a huge number of vertices not to mention the Aircon unit on the outside wall had 100k vertices. For the aircon I gave up decimating it and just modelled it from scratch. – rob Oct 19 '18 at 14:00

This script:

import bpy, bmesh

THR = 4  # <-- the only parameter. The smaller, the stricter

for element in bpy.data.objects:
if element.type != "MESH": continue

# reset
for m in element.modifiers:
if m.name == 'ScriptedDecimate':
element.modifiers.remove(m)

# scoring function
vert = len(element.data.vertices)
areabbox = (element.dimensions.x*element.dimensions.y
+ element.dimensions.y*element.dimensions.z
+ element.dimensions.x*element.dimensions.z)*2
indicator = vert/areabbox

# select and decimate!
if (indicator > THR):
element.select=True
decimator = element.modifiers.new("ScriptedDecimate", type = "DECIMATE")
decimator.ratio = (THR/indicator)**(2/3)
bpy.context.scene.update()
else:
element.select=False


can be useful.

It creates a Decimate modifier for each element where the number of vertices, divided by the surface area of the bounding box, is greater than a set threshold THR. It also adds these object to your selection (and removes all the unaffected meshes). It resets its actions every time you run it again (to avoid double modifiers).

The Decimate Ratio depends on "how far" the original vertex count per area was from the threshold (but it doesn't try to decimate it right to the point where it doesn't exceed the threshold!).

↑↑   verts, faces (tris): 6171, 7182 (12218) → 1743, 2601 (3374)