0
$\begingroup$

I have a dataset, called ModelNet, containing *.off-files. I need to read each file, decimate the mesh and store it to another file.

Problem: For some reason the modifier I add to the model has no effect on the mesh.

What I did: On Blender 2.79b I have included an add-on to read off files. It works. Then I have set the object I loaded from the *.off-file to active.

Note that I have added to break keywords, since I tried to make the decimation work for one mesh, until I let it loop through every file.

I have tried the code of this post before. Unfortunately I was not able to get that code work for me.

Now, the output of number of vertices, edges and polygons does not change through decimation.

Question: What am I doing wrong? I would appreciate help!

Code:

numberOfIteration=2
decimateRatio=0.3
modifierName='DecimateMod'

# Cleans all decimate modifiers
def cleanAllDecimateModifiers(obj):
    for m in obj.modifiers:
        if(m.type=="DECIMATE"):
            obj.modifiers.remove(modifier=m)

# remove the mesh cube (the intial one from startup)
if "Cube" in bpy.data.meshes:
    mesh = bpy.data.meshes["Cube"]
    print("removing mesh", mesh)
    bpy.data.meshes.remove(mesh)

datasetPath = '~/ModelNet10_Mesh/raw'
folders = next(os.walk(datasetPath))[1]
print(folders)
for folder in folders:
    files = next(os.walk(datasetPath + '/' + str(folder) + '/test/'))[2]

    for file in files:

        bpy.ops.import_mesh.off(filepath=datasetPath + '/' + str(folder) + '/test/' + str(file), axis_forward='-Z', axis_up='Y', filter_glob="*.off")

        print(file.split('.')[0])
        bpy.data.objects[file.split('.')[0]].select = True  # works until blender 2.79
        # bpy.data.objects[file.split('.')[0]].select_set(True)  # works for blender 2.8+
        bpy.context.scene.objects.active = bpy.data.objects[file.split('.')[0]]

        for i in range(0, numberOfIteration):
            objectList = bpy.data.objects
            for obj in objectList:
                if(obj.type == "MESH"):
                    print("before decimation")
                    print(obj.data.vertices)
                    print(obj.data.edges)
                    print(obj.data.polygons)

                    cleanAllDecimateModifiers(obj)

                    bpy.ops.object.modifier_add(type='DECIMATE')
                    bpy.context.object.modifiers["Decimate"].use_collapse_triangulate = True
                    bpy.context.object.modifiers["Decimate"].ratio = 1-decimateRatio*(i+1)
                    bpy.context.scene.update()

                    print("after decimation")
                    print(obj.data.vertices)
                    print(obj.data.edges)
                    print(obj.data.polygons)
        break
    break

Console output:

Camera
Cube
Lamp
['Scene']
removing mesh <bpy_struct, Mesh("Cube")>
['bathtub', 'toilet', 'desk', 'night_stand', 'bed', 'dresser', 'sofa', 'monitor', 'chair', 'table']
bathtub_0141
before decimation
<bpy_collection[74637], MeshVertices>
<bpy_collection[75181], MeshEdges>
<bpy_collection[25241], MeshPolygons>
after decimation
<bpy_collection[74637], MeshVertices>
<bpy_collection[75181], MeshEdges>
<bpy_collection[25241], MeshPolygons>
before decimation
<bpy_collection[74637], MeshVertices>
<bpy_collection[75181], MeshEdges>
<bpy_collection[25241], MeshPolygons>
after decimation
<bpy_collection[74637], MeshVertices>
<bpy_collection[75181], MeshEdges>
<bpy_collection[25241], MeshPolygons>

scene tree. The modifier seems to be added, but the mesh does not change its properties in code.Loading off files works.

EDIT: According to @batFINGER I have now used the following code:

# remove the mesh cube (the intial one from startup)
if "Cube" in bpy.data.meshes:
    mesh = bpy.data.meshes["Cube"]
    print("removing mesh", mesh)
    bpy.data.meshes.remove(mesh)

context = bpy.context
scene = context.scene

datasetPath = '~/datasets/ModelNet10_Mesh/raw'
folder = 'bed'
file = 'bed_0534.off'
bpy.ops.import_mesh.off(filepath=datasetPath + '/' + str(folder) + '/test/' + str(file), axis_forward='-Z', axis_up='Y', filter_glob="*.off")

mesh_obs = [o for o in scene.objects if o.type == "MESH"]

def delMods(ob, mod_type="ALL"):
    mods = (ob.modifiers[:] if mod_type == "ALL"
            else [m for m in ob.modifiers if m.type == mod_type])
    while(mods):
        ob.modifiers.remove(mods.pop())

for ob in mesh_obs:
    delMods(ob, 'DECIMATE')
    dm = ob.modifiers.new("Xxx", type="DECIMATE")
    dm.use_collapse_triangulate = True
    me = ob.data
    me_mod = ob.to_mesh(scene, True, 'RENDER')
    # print(len(me.vertices), len(me_mod.vertices))
    print("me - vertices, polygons, edges")
    print(me.vertices)
    print(me.polygons)
    print(me.edges)
    print("me_mod - vertices, polygons, edges")
    print(me_mod.vertices)
    print(me_mod.polygons)
    print(me_mod.edges)

which results in the following console output:

removing mesh <bpy_struct, Mesh("Cube")>
me - vertices, polygons, edges
<bpy_collection[54904], MeshVertices>
<bpy_collection[30636], MeshPolygons>
<bpy_collection[73232], MeshEdges>
me_mod - vertices, polygons, edges
<bpy_collection[54904], MeshVertices>
<bpy_collection[30636], MeshPolygons>
<bpy_collection[73232], MeshEdges>

scene structure:

enter image description here

$\endgroup$
  • 1
    $\begingroup$ You don't seem to be applying the modifier in your script, hence the actual geometry of the object isn't changed (modifiers work non-destructively until applied). $\endgroup$ – Robert Gützkow Dec 10 '19 at 22:55
1
$\begingroup$

Object.to_mesh

In 2.79 can use the to mesh method.

>>> me = C.object.to_mesh(
to_mesh()
Object.to_mesh(scene, apply_modifiers, settings, calc_tessface=True, calc_undeformed=False)
Create a Mesh data-block with modifiers applied
>>> me = C.object.to_mesh()

To create a mesh with the modifiers applied, instead of using modifier apply operator. Will apply all modifiers, not just the decimate modifier.

Note for 2.8 this has changed see How do I get a mesh data-block with modifiers and shape keys applied in Blender 2.8?

Test script, creates a modified mesh to export. Prints the vert count of original and mesh returned from Object.to_mesh(...) Looped thru all mesh objects in scene. It is often the case that after an import the objects created are the only ones selected and can be garnished from context.selected_objects as opposed to using the dataset file structure.

import bpy

context = bpy.context
scene = context.scene

mesh_obs = [o for o in scene.objects if o.type=='MESH']
# if after op call the newly imported objects are only ones selected use
#mesh_obs = [o for o in context.selected_objects if o.type=='MESH']    
def delmods(ob, mod_type="ALL"):
    mods = (ob.modifiers[:] if mod_type == "ALL" 
            else [m for m in ob.modifiers if m.type == mod_type])
    while(mods):
        ob.modifiers.remove(mods.pop())

for ob in mesh_obs:
    delmods(ob, 'DECIMATE')
    dm = ob.modifiers.new("Xxx", type='DECIMATE')
    dm.ratio = 0.5 # change to suit
    dm.use_collapse_triangulate = True
    me = ob.data
    me_mod = ob.to_mesh(scene, True, 'RENDER')
    print(len(me.vertices), len(me_mod.vertices))
    #bpy.data.meshes.remove(me_mod) #  clean up

Result of running on default cube.

me - vertices, polygons, edges
<bpy_collection[8], MeshVertices>
<bpy_collection[6], MeshPolygons>
<bpy_collection[12], MeshEdges>
me_mod - vertices, polygons, edges
<bpy_collection[5], MeshVertices>
<bpy_collection[6], MeshPolygons>
<bpy_collection[9], MeshEdges>
$\endgroup$
  • $\begingroup$ Can you explain how the the decimation modifier dm is applied to the modified mesh me_mod and not to me here? I have extended the last print to output edges and polygons, as well. But unfortunately it sees like there happened no decimation to the mesh as well. Please see my edited question. $\endgroup$ – jublikon Dec 11 '19 at 10:54
  • $\begingroup$ Might need to change the settings of the decimate modifier. dm In particular ratio. Only set one property in way of example, similarly for name "Xxx" prob want something different. $\endgroup$ – batFINGER Dec 11 '19 at 11:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.