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:

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()