# Subdivision/decimation is not working as expected

I am trying to subdivide the following mesh which is split in 3 objects and each object is structured from quads:

I tried both the following two functions:

def subdivide_objects():
obs = [o for o in bpy.data.objects
if o.type == 'MESH' and (o.name == "Wall" or o.name == "Ceiling" or o.name == "Floor")]

for obj in obs:
me = obj.data
# New bmesh
bm = bmesh.new()
bm.from_mesh(me)

bmesh.ops.subdivide_edges(bm, edges=bm.edges, cuts=12, use_grid_fill=True)

# Write back to the mesh
bm.to_mesh(me)
me.update()

def post_process_objects():
bpy.ops.object.select_all(action='DESELECT') # Deselect all objects

for o in ("Wall", "Ceiling", "Floor"):
obj = bpy.context.scene.objects.get(o)
bpy.context.view_layer.objects.active = obj
if obj:
obj.select_set(True)

# Get into edit mode
bpy.ops.object.mode_set(mode="EDIT")

# Subdivide faces
bpy.ops.mesh.subdivide(number_cuts=12)

# Return back to object mode
bpy.ops.object.mode_set(mode="OBJECT")

bpy.ops.object.select_all(action='DESELECT') # Deselect all objects


but for some reason both are not giving the desired result, but as you can see a faulty one:

Any idea what I am missing here (attached the .blend file)?

Update:

After applying @Lucca's solution, for some reason I am still facing the same problem on some specific parts of the plane as you can see in the following images:

It doesn't seem that I have duplicate vertices or something now thus ny idea why still the subdivide operator does not work properly.

Example for @batFINGER 's solution:

Still problematic:

Using same code from Add Cuboid.

Test Run, first linked mesh in question, bisecting (2, 2, 2) 3x be same as running once with (8, 8, 8)

Another take on this is to use the same method as outlined in https://blender.stackexchange.com/a/102239/15543

Since all the edges are aligned in X, Y and Z can select on each and cut.

Note this is not joining the meshes, rather subdividing the axis aligned edges of each.

import bpy
import bmesh

from mathutils import Matrix

def subdivide(mesh, subs=(2, 2, 2)):
bm = bmesh.new()
bm.from_mesh(mesh)

axes = [axis for axis in Matrix().to_3x3()]

for cuts, axis in zip(subs, axes):
def aligned(e):
dir = (e.verts[1].co - e.verts[0].co).normalized()
return abs(dir.dot(axis)) > 0.5
if cuts == 1:
continue
bmesh.ops.subdivide_edges(bm,
edges=[e for e in bm.edges if aligned(e)],
use_grid_fill=True,
cuts=cuts - 1)
bm.to_mesh(mesh)

for ob in bpy.context.selected_objects:
if ob.type == 'MESH':
subdivide(ob.data, (2, 2, 2))


By Edge Length, rather than cuts.

Result on first linked mesh in question using method below

Result on problematic mesh, converted to all quads. Notice thought that the walls are cut to not match ceiling so grids do not line up. They will (as shown above) if the wall edges match the corresponding roof / ceiling edge lengths.

Instead of cutting all edges the same, can instead keep to a minimal edge length, ie the longer the edge the more the cuts.

import bpy
import bmesh
from mathutils import Matrix, Vector
from collections import defaultdict
from math import ceil

def subdivide(mesh, subs=(1, 1, 1)):
bm = bmesh.new()
bm.from_mesh(mesh)

axes = [axis for axis in Matrix().to_3x3()]

for min_length, axis in zip(subs, axes):
def aligned(e):
dir = (e.verts[1].co - e.verts[0].co).normalized()
return abs(dir.dot(axis)) > 0.5
edges=[e for e in bm.edges if aligned(e)]
pool_edges = defaultdict(list)
for e in edges:
l = e.calc_length()
cuts = ceil(l / min_length)
pool_edges[cuts].append(e)
for cuts, edges in pool_edges.items():
if cuts == 1:
continue
bmesh.ops.subdivide_edges(bm,
edges=edges,
use_grid_fill=True,
cuts=cuts - 1)
bm.to_mesh(mesh)

for ob in bpy.context.selected_objects:
if ob.type == 'MESH':
subdivide(ob.data, (0.5, 0.5, 0.5))


EDIT.

Re problematic mesh in question

The face from ceiling not subdividing is a 7 edge ngon.

Having followed the progression of this there is an expectation that there are no doubles, and no ngons in the mesh. The "problematic" roof mesh shown in question has both. The floor has similar issues.

could clean by removing doubles, and removing inline verts, however this should be done prior when generating the initial floor-plan.

    bmesh.ops.remove_doubles(
bm,
verts=bm.verts,
dist=1e-4,
)
bmesh.ops.dissolve_verts(
bm,
verts=[
v for v in bm.verts
]
)

• thanks for the response. As usual a nice answer, however testing your code sometimes I am still getting not a correct subdivision. Check on the updated example I've added based on your solution in my initial post. Feb 9 at 13:01
• Edited re it being a problematic mesh. Feb 9 at 14:12
• Thanks a lot :-). Feb 9 at 14:16
• @ttsesm cheers. Have added re sub'd longer edges more than shorter. Feb 9 at 15:31
• That's neat, many thanks for your time. Feb 10 at 21:28

It's not a problem with your code, but rather with your base objects. You have several overlapping vertices and edges in there. Take a look at this screenshot:

See how there is no orange line indicating connected edges to the left? If I pull the vertex point to the right, this happens:

This kind of 'malformed' model will play havoc with expected outputs.

There are quite a few vertices like that in your model. Fixing them by hand can be tedious, so it's a good idea to start with using Blender's 'Merge vertices by distance' functionality. In newer versions of Blender (I'm using 2.91, don't have a 2.8 install to check right now), this can be accessed by selecting two ore more vertices (using A to select all will do in your case), then pressing M -> By Distance:

Just repeat this for each object, then run your script again:

I assume that looks like what you expected.

I've attached a .blend file with the fix I did:

• Thanks a lot, indeed the issue was the duplicate vertices. For completeness, in python if someone wants to achieve the same result he can use bpy.ops.mesh.remove_doubles(threshold = 0.05) in edit mode. Jan 18 at 10:57
• The problem with the subdivision is still chasing me finally. Check on my update in the initial post. It doesn't seem that I have any duplicate vertices or something now but for some reason parts of the plane are not subdivided. Feb 9 at 10:42