Announcements

The Autodesk Community Forums has a new look. Read more about what's changed on the Community Announcements board.

Repetitive remeshing using mm-api automation

gf645ZCFV
Participant

Repetitive remeshing using mm-api automation

gf645ZCFV
Participant
Participant

Hey there!

 

I am looking to use python in connection with Meshmixer on Windows 10 to remesh multiple meshes automatically. I have a folder of .ply meshes and am looking to remesh them one-by-one and export them into a new folder.

 

Based on previous forum posts, I have figured some things out on my own. So far I have:

1) Downloaded the mm-api from gitHub 

2) Downloaded the windows 10 version for Python 2.X from @hfcandrew's Google Drive

[actually I downloaded both the Python 3.X version and the 2.X version, but ended up working with 2.X as that is what many of the other solutions I saw were using so started there]

3) Tested cutting the bunny with test.py - was successful!

4) Combined bits and pieces of the looping mechanism from this forum post with @MagWeb's remeshing function code from this forum post and customized it a bit to meet my needs based on some of the function settings (found in distrib/python/StoredCommands.h).

5) Ran the following code on a test folder with a bunny.ply and sphere.ply - was successful!

6) Ran the following code on a test folder with a bunny.ply, sphere.ply, and a larger .ply from my 3D models that I need remeshed - not quite successful...

 

When I ran the code on just the bunny and sphere, both appeared in the Remeshed folder as bunnyR.ply and sphereR.ply and in my IDLE shell it was clear the command finished executing as the >>> appeared. However, when I ran the code on a folder with the bunny and my model, only the bunny appeared in the Remeshed folder and the shell did not pop up the >>>. I figured maybe something was taking some time so I waited for a bit but nothing happened and I force quit the code. Upon force quitting, I checked the MM window that was still up and and was able to undo the delete object step in MM manually and saw that the actual remeshing of my model was successful. Then to see if it was getting stuck on saving the larger model (though I noted that saving the remeshed model manually took <5 seconds), I ran the code on a folder with the bunny, my model, and the sphere. This time, the bunnyR.ply and sphereR.ply appeared and the shell did not pop up the >>>, again indicating that the code did not finish. However, due to naming, my model was processed in between the bunny and the sphere, so it's clear that the code moved on and processed the sphere after not saving my model...very bizarre

 

This is all to say that it seems that the issue is with saving...maybe? However, it works with the bunny and sphere, so I'm not entirely sure where the issue is going wrong...It very well could be a silly mistake with my code. I am brand new to Python so I'm super proud of getting this far, but I am not sure where to go from here.

 

I have attached the code, a screenshot of my shell output, and an obj version of my model (as the ply files are not allowed for uploading)

 

Any help is greatly appreciated! 🙂

 

Code:

import os
import datetime

from Tkinter import *
from tkFileDialog import askdirectory
import Tkinter as tk

import mmapi
from mmRemote import *
import mm

remote = mmRemote()
remote.connect()

# Remesh settings
rmode = 2 # remesh mode: Target Edge Length
edgeL = 0.8 # edge length in mm
fse = True # preserve sharp edges = T
bmode = 2 # boundary mode: refined fixed boundary
it = 5 # iterations

def Load_File():
    #print("Load_File method start")
    input_dir = askdirectory(parent = root)
    #print(str(input_dir))
    if input_dir is "":
        return
    #print("supported extensions")
    supported_extensions = ['ply'] # can I import ply?
    file_List = [fn for fn in os.listdir(input_dir)if any(fn.endswith(ext) for ext in supported_extensions)]
    #print("file_List: " + str(len(file_List)))
    for i in file_List:
        #print("in the loop: " + str(input_dir+'/'+i))
        ct = datetime.datetime.now()
        print("**Starting new model " + i + " at " + str(ct))
        mm.append_objects_from_file(remote,str(input_dir+'/'+i))
        #print("appended")
        Remesh()
        ct = datetime.datetime.now()
        print("*****Model " + i + " completed at " + str(ct))
        Save_File(i, input_dir)

def Remesh():
    #print("Remesh method start")
    mm.select_all(remote)
    mm.begin_tool(remote, "remesh")
    mm.set_toolparam(remote, "goalType", rmode)
    mm.set_toolparam(remote, "edgeLengthWorld", edgeL)
    mm.set_toolparam(remote, "findSharpEdges", fse)
    mm.set_toolparam(remote, "boundaryMode", bmode)
    mm.set_toolparam(remote, "iterations", it)
    # regularity - default
    # sharp threshold - default
    mm.accept_tool(remote)
    
def Save_File(i, input_dir):
    out_dir = input_dir + '/Remeshed/'
    try:
        os.mkdir(input_dir + '/Remeshed')
    except:
        None
    ext = i.split('.')
    save_path = out_dir + ext[0] +'R.' + ext[1]
    mm.export_mesh(remote,str(save_path))
    cmd = mmapi.StoredCommands()
    cmd.AppendSceneCommand_DeleteSelectedObjects();
    remote.runCommand(cmd)

# Setup a tiny GUI window:    
root = Tk()
root.title("Remesh")
w = 240 
h = 30 
ws = root.winfo_screenwidth() 
x = ws - w
y = 0
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root.attributes("-topmost", True)

button_Remesh = tk.Button(root, text="Remesh All", command = Load_File) 
button_Remesh.pack()

def on_closing():
    remote.shutdown()
    root.destroy()    

root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()


 

0 Likes
Reply
Accepted solutions (1)
822 Views
3 Replies
Replies (3)

hfcandrew
Advisor
Advisor

Ya I'm not sure, I'll have to leave this one up to @MagWeb 

0 Likes

MagWeb
Advisor
Advisor
Accepted solution

The problem is the input's filename "CB.1.a_2021S_outer.ply". It's a basic convention to use fullstops as separator of name and suffix. So do not use fullstops within a filename!

 

This affects your code:

def Save_File

you split the file's total string at its fullstops to elements and use the first element as the output's name and the second as its suffix:

    ext = i.split('.')
    save_path = out_dir + ext[0] +'R.' + ext[1]

Splitting "CB.1.a_2021S_outer.ply" at the fullstops gives four elements ext = [CB, 1, a_2021S_outer, ply].

and combining ext[0] +'R.' + ext[1] gives "CBR.1".

.1 isn't a format MM is able to export. That's why there's nothing written to disk.

 

If you really want to keep the fullstops you might try something like this:

    ext = i.split('.')# splits string to elements at fullstops
    suffix = ext[-1] #extracts last element as suffix
    del ext[-1] #removes last element
    name =".".join(str(x) for x in ext) #joins remaining elements to a string inserting fullstops
    save_path = out_dir + name +'R.' + suffix

 



Gunter Weber
Triangle Artisan

gf645ZCFV
Participant
Participant
I knew it must've been a silly error. Thank you for educating me, explaining what was going on, and how to fix it! Alas, off to fix my file naming...
0 Likes