making a gif file with glc player

making a gif file with glc player

Anonymous
Not applicable
1,294 Views
7 Replies
Message 1 of 8

making a gif file with glc player

Anonymous
Not applicable

First question) How come some obj has .jpg file and .mtl file, but when exported by meshmixer for obj, you only get one file (.obj)??

 

Second question) Does anyone know how to take multiple snapshots of the 3d model? I know glc-player, but it doesn't load .obj with color.

0 Likes
Accepted solutions (1)
1,295 Views
7 Replies
Replies (7)
Message 2 of 8

Anonymous
Not applicable

ad 1):

If there's a textured object loaded to MM the application exports the texture (image +mtl) along with the object.

If you edit the object in some way which creates new faces in MM: MM saves the object with several texture images (the original texture as objectName_material_0 and objectName_GeneratedMat1 for added surfaces). Note that there are third party applications which do not support several texture images for a single object.

If you run EDIT/MakeSolid on a textured object: This tool transfers texture to per vertex color (which is stored in the .obj if you choose the ObjFormatWithPerVertexColor option in the export dialog's format dropdown)

 

ad 2): 

Using mmApi you can grab several screenshots automatically.

This code constructs a MMView application:

Ohne Titel.jpeg

Hitting Turntable (save checked) it saves screenshots (number is a result of Time x Fps) to .documents/meshmixer/turntable (you need to create that directory turntable manually before).

from Tkinter import *
import ttk 
import mmapi
from mmRemote import *
import mm
import time
import os



#create a centered "root" window object
root = Tk()
root.title("MM View")  #name window
w = 302 # width Tk root
h = 300 # height Tk root
# get screen width and height:
ws = root.winfo_screenwidth() # width
hs = root.winfo_screenheight() # height
# calculate startup x and y coordinates for Tk root:
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))  # set root window's size and position
root.attributes("-topmost", True) # keeps root window in front




# initialize connection to MM
remote = mmRemote()
remote.connect()

#############################
# fixed views stuff:
e = mmapi.vec3f()
t = mmapi.vec3f()
u = mmapi.vec3f()

def front():
     cmd2 = mmapi.StoredCommands()
     
     e.x = 0.0
     e.y = 0.0
     e.z = 1.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 1.0
     u.z = 0.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Front")
     

def rear():
     cmd2 = mmapi.StoredCommands()
 
     e.x = 0.0
     e.y = 0.0
     e.z = -1.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 1.0
     u.z = 0.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Rear")

def top():
     cmd2 = mmapi.StoredCommands()
     
     e.x = 0.0
     e.y = 1.0
     e.z = 0.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 0.0
     u.z = -1.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Top")

def below():
     cmd2 = mmapi.StoredCommands()
     
     e.x = 0.0
     e.y = -1.0
     e.z = 0.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 0.0
     u.z = 1.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Below")

def right():
     cmd2 = mmapi.StoredCommands()
     
     e.x = 1.0
     e.y = 0.0
     e.z = 0.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 1.0
     u.z = 0.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Right")

def left():
     cmd2 = mmapi.StoredCommands()
     
     e.x = -1.0
     e.y = 0.0
     e.z = 0.0
     
     t.x = 0.0
     t.y = 0.0
     t.z = 0.0
     
     u.x = 0.0
     u.y = 1.0
     u.z = 0.0
     cmd2.CameraControl_SetSpecificView(e,t,u)
     cmd2.CameraControl_RecenterView()
     remote.runCommand(cmd2)
     help_text.configure(text="Current View: Left")


##########################     
#turntable stuff:
rec_time = DoubleVar()#target length of video
fps = DoubleVar()#video framerate
direction = IntVar()#turn direction
direction.set(-1)
save = IntVar()#save turntable to file
sample = IntVar()#sample selectVisible
stopTurn = IntVar()#to stop turntable
stopTurn.set(0)

def scrs(): #single screeshot saved to file with time stamp
    scs = mmapi.StoredCommands()
    scs.AppendSceneCommand_SaveScreenShot(os.path.expanduser("~/documents/meshmixer/screenshots/shot" + time.strftime("%d:%m:%y_%H:%M:%S") + ".jpg" ))
    remote.runCommand(scs)
    help_text.configure(text="See: Meshmixer/screenshots")


def hideP(): #sorts out and hides/shows pivots
    cur_objects = mm.list_objects(remote)
    i = len(cur_objects)
    if buttonHideP.config('text')[-1] == 'HidePiv': #hide pivots
        while (i > 0):
              mm.select_objects(remote, [cur_objects[0]])
              cmd2 = mmapi.StoredCommands()
              t_key = cmd2.AppendSceneCommand_GetObjectType(cur_objects[0])
              remote.runCommand(cmd2)
              obj_type = mmapi.any_result()
              mtype = cmd2.GetSceneCommandResult_GetObjectType(t_key,obj_type)
              remote.runCommand(cmd2)
              if obj_type.i == 3:
                  cmd2.AppendSceneCommand_SetHidden(cur_objects[0])
                  remote.runCommand(cmd2)
              cur_objects.pop(0)
              i -= 1
              buttonHideP.config(text='ShowPiv')
              help_text.configure(text="Pivots hidden")

    else: #show pivots
        while (i > 0):
              mm.select_objects(remote, [cur_objects[0]])
              cmd2 = mmapi.StoredCommands()
              t_key = cmd2.AppendSceneCommand_GetObjectType(cur_objects[0])
              remote.runCommand(cmd2)
              obj_type = mmapi.any_result()
              mtype = cmd2.GetSceneCommandResult_GetObjectType(t_key,obj_type)
              remote.runCommand(cmd2)
              if obj_type.i == 3:
                  cmd2.AppendSceneCommand_SetVisible(cur_objects[0])
                  remote.runCommand(cmd2)
              cur_objects.pop(0)
              i -= 1
              buttonHideP.config(text='HidePiv')
              help_text.configure(text="Pivots visible")

              

def ortho(): #switches perspective and orthogonal
     if buttonOrth.config('text')[-1] == 'Ortho':
        buttonOrth.config(text='Persp')
        cmd2 = mmapi.StoredCommands()
        cmd2.CameraControl_SetPerspectiveView()
        remote.runCommand(cmd2)        
        help_text.configure(text="Perspective view")

     else:
        buttonOrth.config(text='Ortho')        
        cmd2 = mmapi.StoredCommands()
        cmd2.CameraControl_SetOrthographicView()
        remote.runCommand(cmd2)
        help_text.configure(text="Orthographic view")


def turn(): #turntable
     help_text.configure(text="...Turning...")
     sa = save.get()
     if sa == 1: # prepares record mode: cleaning output directory
          path = os.path.expanduser("~/documents/meshmixer/turntable")
          fileList = os.listdir(path)
          for fileName in fileList:
               os.remove(path+"/"+fileName)
     sv = sample.get()
     if sv == 1: # prepares selectVisible sampling: ensures basic selection
          cmd2 = mmapi.StoredCommands()
          cmd2.CameraControl_SetOrthographicView()
          remote.runCommand(cmd2)
          buttonOrth.config(text='Ortho') 
          cur_groups = mm.list_selected_groups(remote)
          if len(cur_groups) == 0:
              help_text.configure(text="This action needs a Selection")
              raise Exception("Selection missing")
     r = rec_time.get() # calls current values
     f = fps.get()
     d = direction.get()
     totalframes = r * f # calculate number of screenshots
     angleframe = (float(360)/totalframes)*d # calculates angle/screenshot
     i = 0
     while i < (totalframes):
          s  = stopTurn.get()
          if s == 1: # stop turntable
               stopTurn.set(0)
               sample.set(0)
               break
          cmd2 = mmapi.StoredCommands()
          cmd2.CameraControl_TurntableOrbit(angleframe, 0.0);
          if sa == 1: # saves screenshots serie
               cmd2.AppendSceneCommand_SaveScreenShot(os.path.expanduser("~/documents/meshmixer/turntable/image_%d_.png"%i))
          if sv == 1: # samples selectVisible
               cmd2.AppendSelectUtilityCommand( "selectVisible",1)
          remote.runCommand(cmd2)
          i += 1
          root.update()
     help_text.configure(text="Turntable completed")
     if sv == 1: # inverts sampled selection to be deleted or separated by user
          help_text.configure(text="Hidden selected")
          cmd2 = mmapi.StoredCommands()
          cmd2.AppendSelectUtilityCommand( "invert")
          remote.runCommand(cmd2)

               
          
def stop_turn():
     stopTurn.set(1)
     help_text.configure(text="Ready")
         

def toggle(): # switches turn direction
     if toggleDir.config('text')[-1] == '>>>':
        toggleDir.config(text='<<<')
        direction.set(1)
        help_text.configure(text="Direction : clockwise")

     else:
        toggleDir.config(text='>>>')        
        direction.set(-1)
        help_text.configure(text="Direction : anticlockwise")


############################    
#applet's GUI elements

help_text = Label(root,text = "Ready", font = ("Helvetica",14), wraplength = 200,  compound = CENTER)
help_text.grid (row = 0, columnspan = 3, padx = 2, pady = 3)

buttonFront = ttk.Button(root, text="Front", command = front) 
buttonFront.grid (row = 2, column = 1, padx = 2, pady = 3)

buttonRear = ttk.Button(root, text="Rear", command = rear) 
buttonRear.grid (row = 4, column = 1, padx = 2, pady = 3)

buttonTop = ttk.Button(root, text="Top", command = top) 
buttonTop.grid (row = 1, column = 1, padx = 2, pady = 3)

buttonBelow = ttk.Button(root, text="Below", command = below) 
buttonBelow.grid (row = 3, column = 1, padx = 2, pady = 3)

buttonRight = ttk.Button(root, text="Right", command = right) 
buttonRight.grid (row = 2, column = 2, padx = 2, pady = 3)

buttonLeft = ttk.Button(root, text="Left", command = left) 
buttonLeft.grid (row = 2, column = 0, padx = 2, pady = 3)


buttonShot = ttk.Button(root, text="Screensh.", command = scrs) 
buttonShot.grid (row = 5, column = 0, padx = 2, pady = 3)

buttonHideP = ttk.Button(root, text="HidePiv", command = hideP)
buttonHideP.grid (row = 5, column = 1, padx = 2, pady = 3)

buttonOrth = ttk.Button(root, text="Persp", command = ortho) 
buttonOrth.grid (row = 5, column = 2, padx = 2, pady = 3)


buttonTurn = ttk.Button(root, text="Turntable", command = turn) 
buttonTurn.grid (row = 6, column = 0, padx = 2, pady = 3)

buttonStop = ttk.Button(root, text="Stop", command = stop_turn, compound = CENTER ) 
buttonStop.grid (row = 6, column = 1, padx = 2, pady = 3)

saveCheck = Checkbutton(root, text="save", variable=save)
saveCheck.grid (row = 6, column = 2, padx = 2, pady = 3)


slideTime = Scale(root, from_=1, to=60, orient=HORIZONTAL, variable = rec_time, label ="Time" )
slideTime.set(30)
slideTime.grid (row = 7, column=0, padx = 2, pady = 3)

toggleDir = ttk.Button(root, text=">>>", command=toggle)
toggleDir.grid (row = 7, column = 1, padx = 2, pady = 3)

slideFps = Scale(root, from_=2, to=60, orient=HORIZONTAL, variable = fps, label = "Fps" )
slideFps.set(30)
slideFps.grid (row = 7, column = 2, padx = 2, pady = 3)

visibCheck = Checkbutton(root, text="selectV", variable=sample)
visibCheck.grid (row = 8, column = 1, padx = 2, pady = 3)


mainloop()
0 Likes
Message 3 of 8

Anonymous
Not applicable

hi, it is nice to know you can make another app just that for. However, I am not sure how to put the code and in which file(in meshmixer.exe?)

 

I feel like this involves rtext to open meshmixer.exe and find a place to put those codes. Is that true?  Sorry a bit of a newb here.

0 Likes
Message 4 of 8

Anonymous
Not applicable

where do I get mmAPI? how to install it?

 

I am using a windows laptop

0 Likes
Message 5 of 8

Anonymous
Not applicable

No need to modify meshmixer.exe .

 

mmApi allows to send commands to MM and to receive stuff like tool parameters from MM. Think of it as a remote control for a running MM window.

 

You can download mmApi from here . Store it somewhere on your system.

To use python codes you need to install Python 2.7 from here.

Go to the folder where you saved mmApi and browse to .../mm-api/distrib/python.

 

Now test the api: Open .../mm-api/distrib/python/test.py with Python 2.7 and run MM loading the default bunny. In Python 2.7 IDLE run the loaded code via menu>Run/RunModule. >>> In MM the bunny should be cut in half now.

 

If that worked: Go to .../mm-api/python. There you find a mm folder. Copy that folder to clipboard and paste it in .../mm-api/distrib/python/

 

To run the code I posted above: 

In Python 2.7 IDLE create a new file (via menu>File/NewFile). Copy the code above and paste it to that empty window.

Running that file (via menu>Run/RunModule) you will be asked to save the file before executing it.  Save it exactly to .../mm-api/distrib/python/ and name it to something like mmView. Now the window shown above should pop up....

0 Likes
Message 6 of 8

Anonymous
Not applicable

I don't know how to code python.

 

I downloaded mm-api-master from your link, not mm-api, is that ok?

 

I downloaded python 2.7.0(32bit), not 2.7.17, is that ok?

 

I open the python27 command line I entered:

Open C:\Users\Work\Desktop\3d_scans\mm-api-master\distrib\python\test.py

and I get syntax error

 

I entered:

Open \Users\Work\Desktop\3d_scans\mm-api-master\distrib\python\test.py

and I get "SyntaxError: unexpected character after line continuation character"

 

I tried / instead of \

I entered:

Open /Users/Work/Desktop/3d_scans/mm-api-master/distrib/python/test.py

and I get invalid syntax

 

Please let me know what to enter exactly

0 Likes
Message 7 of 8

Anonymous
Not applicable
Accepted solution

Yep, the master branch of  mmApi is right.

Python 2.7.0 is almost 10 years old. I'm currently using 2.7.16 without any issues.

 

You need to use the python interpreter to run a .py file

I'm on macOS where things are a bit different, but this should work (taken from here)

Your script is in "C:\Users\Work\Desktop\3d_scans\mm-api-master\distrib\python\test.py" 


  • Open Command line:   Start menu -> Run  and type cmd
  • Type:   C:\python27\python.exe C:\Users\Work\Desktop\3d_scans\mm-api-master\distrib\python\test.py
  • Or if your system is configured correctly, you can drag and drop your script from Explorer onto the Command Line window and press enter.

Instead of CommandPrompt I'd use the IDLE GUI application to load .py files and execute them from there (as explained above). Should be found here:

  • Start IDLE:   Start menu -> Programming -> Python 2.7 -> IDLE (Python GUI)

 

0 Likes
Message 8 of 8

Anonymous
Not applicable

it works! amazing, thanks!

0 Likes