As part of my quest to improve the FBX export of Cinema 4D I've been asked to do some automatic cleanup of meshes before the export.
I'm using several calls of SendModelingCommand()
to perform these clean up operations. The requested commands are:
c4d.MCOMMAND_OPTIMIZE
c4d.MCOMMAND_ALIGNNORMALS
c4d.MCOMMAND_REVERSENORMALS
Optimize and Align Normals are run on every polygonal object as checked with IsInstanceOf(c4d.Opolygon)
. Reverse Normals is run selectively only on meshes with no boundary edges (i.e. closed meshes) whose normals are pointing inward. I can get all of these to work properly in simple test documents, but when I test it with a full fledged production scene the c4d.MCOMMAND_ALIGNNORMALS
and c4d.MCOMMAND_REVERSENORMALS
calls fail and SendModelingCommand()
returns False
. Is there anyway to get more information about why SendModelingCommand()
is failing?
Here's the applicable part of my code:
if self.align:
poly_objs = [o for o in self._GetAllObjects(self.doc.GetFirstObject()) if o.IsInstanceOf(c4d.Opolygon)]
c4d.StopAllThreads() #Not sure if this is necessary
res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_ALIGNNORMALS, poly_objs, doc=self.doc) #Align normals for all polygon objects
if res:
print("Successfully aligned normals.") #Works in simple scenes
else:
print("Could not align normals.") #Doesn't work in production scenes
if self.reverse:
closed_objs = [o for o in poly_objs if self._IsClosedMesh(o)]
reversed_objs = [o for o in closed_objs if self._IsReversed(o)]
c4d.StopAllThreads()
res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_REVERSENORMALS, reversed_objs, doc=self.doc) #Reverse the normals of all closed polygon objects whose normals are currently reversed
if res:
print("Successfully fixed reversed normals.") #Works in simple scenes
else:
print("Could not fix reversed normals.") #Doesn't work in production scenes
if self.optimize:
poly_objs = [o for o in self._GetAllObjects(self.doc.GetFirstObject()) if o.IsInstanceOf(c4d.Opolygon)]
tool_bc = c4d.BaseContainer()
tool_bc[c4d.MDATA_OPTIMIZE_UNUSEDPOINTS] = True
c4d.StopAllThreads()
res = c4d.utils.SendModelingCommand(c4d.MCOMMAND_OPTIMIZE, poly_objs, bc=tool_bc, doc=self.doc) #Optimize unused points for all polygon objects
if res:
print("Successfully removed unused points.") #This one works in production scenes too! For some reason?
else:
print("Could not remove unused points.")
Edit: there are 1200 or so polygonal objects in the production scene, only 3 of them are closed meshes with reversed normals. I doubt it's an issue of list length. Many of the polygonal objects are children of generators (Symmetry, Cloner, Subdivision Surface) but I can't imagine that should make a difference.