def serialize(self, file): file.write('<mesh>\n') # write shared vertex buffer if available. sharedVertexCount = self.mSharedVertexBuffer.vertexCount() if (sharedVertexCount > 0): file.write('\t<sharedgeometry vertexcount="%d">\n' % sharedVertexCount) self.mSharedVertexBuffer.serialize(file, '\t\t') file.write('\t</sharedgeometry>\n') subMeshNames = list() # write submeshes. file.write('\t<submeshes>\n') for subMesh in self.mSubMeshDict.values(): name = subMesh.mName if (name): if (not name in subMeshNames): subMeshNames.append(name) else: LogManager.logMessage("Mulitple submesh with same name defined: %s" % name, Message.LVL_WARNING) subMesh.serialize(file) file.write('\t</submeshes>\n') # write submesh names if (len(subMeshNames)): file.write('\t<submeshnames>\n') for index, name in enumerate(subMeshNames): file.write('\t\t<submeshname name="%s" index="%d" />\n' % (name, index)) file.write('\t</submeshnames>\n') file.write('</mesh>\n')
def insertPolygon(self, blendMesh, polygon, blendVertexGroups = None, ogreSkeleton = None, fixUpAxisToY = True): polygonVertices = polygon.vertices polygonVertexCount = polygon.loop_total # extract uv information. # Here we convert blender uv data into our own # uv information that lists uvs by vertices. blendUVLoopLayers = blendMesh.uv_layers # construct empty polygon vertex uv list. polygonVertUVs = list() for i in range(polygonVertexCount): polygonVertUVs.append(list()) for uvLoopLayer in blendUVLoopLayers: for i, loopIndex in enumerate(polygon.loop_indices): polygonVertUVs[i].append(uvLoopLayer.data[loopIndex].uv) # extract color information. # Here we convert blender color data into our own # color information that lists colors by vertices. blendColorLoopLayers = blendMesh.vertex_colors # construct empty polygon vertex color list. polygonVertColors = list() for i in range(polygonVertexCount): polygonVertColors.append(list()) for colorLoopLayer in blendColorLoopLayers: for i, loopIndex in enumerate(polygon.loop_indices): polygonVertColors[i].append(colorLoopLayer.data[loopIndex].color) # loop through the vertices and add to this submesh. localIndices = list() useSmooth = polygon.use_smooth for index, uvs, colors in zip(polygonVertices, polygonVertUVs, polygonVertColors): vertex = blendMesh.vertices[index] norm = vertex.normal if (useSmooth) else polygon.normal # grab bone weights. boneWeights = list() if (ogreSkeleton is not None): for groupElement in vertex.groups: groupName = blendVertexGroups[groupElement.group].name boneIndex = ogreSkeleton.getBoneIndex(groupName) if (boneIndex == -1 or abs(groupElement.weight) < 0.000001): continue boneWeight = groupElement.weight boneWeights.append(BoneWeight(boneIndex, boneWeight)) # trim bone weight count if too many defined. if (len(boneWeights) > 4): LogManager.logMessage("More than 4 bone weights are defined for a vertex! Best 4 will be used.", Message.LVL_WARNING) boneWeights.sort(key=attrgetter('mBoneWeight'), reverse=True) while (len(boneWeights) > 4): del boneWeights[-1] localIndices.append(self.mVertexBuffer.addVertex(index, vertex.co, norm, uvs, colors, boneWeights, fixUpAxisToY)) # construct triangle index data. if (polygonVertexCount is 3): self.mFaceData.append(localIndices) else: # split quad into triangles. self.mFaceData.append(localIndices[:3]) self.mFaceData.append([localIndices[0], localIndices[2], localIndices[3]])
def executeOgreXMLConverter(converterpath, filepath, settings=MeshXMLConverterSettings()): global gDevNull try: if os.path.exists(converterpath): filepath = os.path.normpath(filepath) converterpath = os.path.normpath(converterpath) # converter path command = [converterpath] # options if settings.extremityPoints > 0: command.extend(['-x', str(settings.extremityPoints)]) if not settings.edgeLists: command.append('-e') if settings.tangent: command.append('-t') if settings.tangentSemantic == 'uvw': command.extend(['-td', 'uvw']) if settings.tangentSize == '4': command.extend(['-ts', '4']) if settings.splitMirrored: command.append('-tm') if settings.splitRotated: command.append('-tr') if settings.reorganiseVertBuff: command.append('-r') if not settings.optimiseAnimation: command.append('-o') # additional arguments globalSettings = bpy.context.scene.ogre_mesh_exporter additional = shlex.split( globalSettings.ogreXMLConverterAdditionalArg) if len(additional): command.extend(additional) command.extend(['-log', '%s.log' % filepath]) # file path command.append(filepath) LogManager.logMessage("Executing OgrXMLConverter: " + " ".join(command)) p = subprocess.Popen(command, stdout=gDevNull, stderr=gDevNull) return p else: LogManager.logMessage("No converter found at %s" % converterpath, Message.LVL_ERROR) except: traceback.print_exc() return False
def __init__(self, blendMesh = None, blendVertexGroups = None, ogreSkeleton = None, exportSettings = MeshExportSettings()): # shared vertex buffer. self.mSharedVertexBuffer = VertexBuffer() # Blender mesh -> shared vertex index link. self.mSharedMeshVertexIndexLink = dict() # collection of submeshes. self.mSubMeshDict = dict() # skip blend mesh conversion if no blend mesh passed in. if (blendMesh is None): return self.mOgreSkeleton = ogreSkeleton hasBoneWeights = ogreSkeleton is not None # Lets do some pre checking to show warnings if needed. uvLayerCount = len(blendMesh.uv_layers) colorLayerCount = len(blendMesh.vertex_colors) if (uvLayerCount > 8): LogManager.logMessage("More than 8 UV layers in this mesh. Only 8 will be exported.", Message.LVL_WARNING) if (colorLayerCount > 2): LogManager.logMessage("More than 2 color layers in this mesh. Only 2 will be exported.", Message.LVL_WARNING) # setup shared vertex buffer. self.mSharedVertexBuffer.reset(uvLayerCount, colorLayerCount, hasBoneWeights) # split up the mesh into submeshes by materials. # we first get sub mesh shared vertices option. materialList = blendMesh.materials materialCount = len(materialList) subMeshProperties = blendMesh.ogre_mesh_exporter.subMeshProperties while (len(subMeshProperties) < materialCount): subMeshProperties.add() # add more items if needed. while (len(subMeshProperties) > materialCount): subMeshProperties.remove(0) # remove items if needed. LogManager.logMessage("Material Count: %d" % len(materialList), Message.LVL_INFO) for polygon in blendMesh.polygons: # get or create submesh. if (polygon.material_index in self.mSubMeshDict): subMesh = self.mSubMeshDict[polygon.material_index] else: # instantiate submesh base on wether sharing vertices or not. subMeshProperty = subMeshProperties[polygon.material_index] if (subMeshProperty.useSharedVertices): subMesh = SubMesh(self.mSharedVertexBuffer, self.mSharedMeshVertexIndexLink, subMeshProperty.name) else: subMesh = SubMesh(VertexBuffer(uvLayerCount, colorLayerCount, hasBoneWeights), name = subMeshProperty.name) subMesh.mMaterial = None if (len(materialList) == 0) else materialList[polygon.material_index] if (exportSettings.requireMaterials and subMesh.mMaterial == None): LogManager.logMessage("Some faces are not assigned with a material!", Message.LVL_WARNING) LogManager.logMessage("To hide this warning, please uncheck the 'Require Materials' option.", Message.LVL_WARNING) self.mSubMeshDict[polygon.material_index] = subMesh # insert polygon. subMesh.insertPolygon(blendMesh, polygon, blendVertexGroups, ogreSkeleton, exportSettings.fixUpAxisToY)
def serializeBoneAssignments(self, file, indent = ''): file.write('%s\t<boneassignments>\n' % indent) vertexWithNoBoneAssignements = 0; for i, vertex in enumerate(self.mVertexData): if (len(vertex.mBoneWeights) == 0): vertexWithNoBoneAssignements += 1 for boneWeight in vertex.mBoneWeights: file.write('%s\t\t<vertexboneassignment vertexindex="%d" boneindex="%d" weight="%.6f" />\n' % (indent, i, boneWeight.mBoneIndex, boneWeight.mBoneWeight)) if (vertexWithNoBoneAssignements > 0): LogManager.logMessage("There are %d vertices with no bone assignements!" % vertexWithNoBoneAssignements, Message.LVL_WARNING) file.write('%s\t</boneassignments>\n' % indent)
def executeOgreXMLConverter(converterpath, filepath, settings = MeshXMLConverterSettings()): global gDevNull try: if os.path.exists(converterpath): filepath = os.path.normpath(filepath) converterpath = os.path.normpath(converterpath) # converter path command = [converterpath] # options if settings.extremityPoints > 0: command.extend(['-x', str(settings.extremityPoints)]) if not settings.edgeLists: command.append('-e') if settings.tangent: command.append('-t') if settings.tangentSemantic == 'uvw': command.extend(['-td', 'uvw']) if settings.tangentSize == '4': command.extend(['-ts', '4']) if settings.splitMirrored: command.append('-tm') if settings.splitRotated: command.append('-tr') if settings.reorganiseVertBuff: command.append('-r') if not settings.optimiseAnimation: command.append('-o') # additional arguments globalSettings = bpy.context.scene.ogre_mesh_exporter additional = shlex.split(globalSettings.ogreXMLConverterAdditionalArg) if len(additional): command.extend(additional) command.extend(['-log', '%s.log' % filepath]) # file path command.append(filepath) LogManager.logMessage("Executing OgrXMLConverter: " + " ".join(command)) p = subprocess.Popen(command, stdout = gDevNull, stderr = gDevNull) return p else: LogManager.logMessage("No converter found at %s" % converterpath, Message.LVL_ERROR) except: traceback.print_exc() return False
def serialize(self, file): file.write('<mesh>\n') # write shared vertex buffer if available. sharedVertexCount = self.mSharedVertexBuffer.vertexCount() if (sharedVertexCount > 0): file.write('\t<sharedgeometry vertexcount="%d">\n' % sharedVertexCount) self.mSharedVertexBuffer.serialize(file, '\t\t') file.write('\t</sharedgeometry>\n') # write bone assignments if (self.mSharedVertexBuffer.mHasBoneWeights): self.mSharedVertexBuffer.serializeBoneAssignments(file, '\t\t') subMeshNames = list() # write submeshes. file.write('\t<submeshes>\n') for subMesh in self.mSubMeshDict.values(): name = subMesh.mName if (name): if (not name in subMeshNames): subMeshNames.append(name) else: LogManager.logMessage( "Mulitple submesh with same name defined: %s" % name, Message.LVL_WARNING) subMesh.serialize(file) file.write('\t</submeshes>\n') # write submesh names if (len(subMeshNames)): file.write('\t<submeshnames>\n') for index, name in enumerate(subMeshNames): file.write('\t\t<submeshname name="%s" index="%d" />\n' % (name, index)) file.write('\t</submeshnames>\n') # write skeleton link if (self.mOgreSkeleton is not None): file.write('\t<skeletonlink name="%s.skeleton" />\n' % self.mOgreSkeleton.mName) file.write('</mesh>\n')
def serializeBoneAssignments(self, file, indent=''): file.write('%s\t<boneassignments>\n' % indent) vertexWithNoBoneAssignements = 0 for i, vertex in enumerate(self.mVertexData): if (len(vertex.mBoneWeights) == 0): vertexWithNoBoneAssignements += 1 for boneWeight in vertex.mBoneWeights: file.write( '%s\t\t<vertexboneassignment vertexindex="%d" boneindex="%d" weight="%.6f" />\n' % (indent, i, boneWeight.mBoneIndex, boneWeight.mBoneWeight)) if (vertexWithNoBoneAssignements > 0): LogManager.logMessage( "There are %d vertices with no bone assignements!" % vertexWithNoBoneAssignements, Message.LVL_WARNING) file.write('%s\t</boneassignments>\n' % indent)
def exportMesh(meshObject, filepath): result = list() try: LogManager.logMessage("Output: %s.mesh.xml" % filepath, Message.LVL_INFO) # get combined mesh override & global settings. meshExportSettings = MeshExportSettings.fromRNA(meshObject) if (meshExportSettings.runOgreXMLConverter): meshXMLConverterSettings = MeshXMLConverterSettings.fromRNA(meshObject) # get linked armature armatureObject = None ogreSkeleton = None parentObject = meshObject.parent if (parentObject and meshObject.parent_type == 'ARMATURE'): armatureObject = parentObject else: # check modifier stack, use first valid armature modifier. for modifier in meshObject.modifiers: if (modifier.type == 'ARMATURE' and (modifier.use_vertex_groups or modifier.use_bone_envelopes)): armatureObject = modifier.object # Do skeleton export first if armature exist. if (armatureObject): # get skeleton file path and name. if (meshExportSettings.skeletonNameFollowMesh): skeletonFilePath = filepath + '.skeleton.xml'; skeletonName = os.path.basename(filepath) else: dirname = os.path.dirname(filepath) skeletonFilePath = dirname + armatureObject.data.name + '.skeleton.xml'; skeletonName = armatureObject.data.name LogManager.logMessage("Skeleton: " + skeletonName, Message.LVL_INFO); # prepare skeleton. meshInverseMatrix = meshObject.matrix_world.inverted() ogreSkeleton = Skeleton(skeletonName, armatureObject, meshInverseMatrix, meshExportSettings.fixUpAxisToY) LogManager.logMessage("Bones: %d" % len(ogreSkeleton.mBones), Message.LVL_INFO); # write skeleton. file = open(skeletonFilePath, "w", encoding="utf8", newline="\n") ogreSkeleton.serialize(file) file.close() LogManager.logMessage("Done exporting skeleton XML.") # Run XML Converter if needed. if (meshExportSettings.runOgreXMLConverter): globalSettings = bpy.context.scene.ogre_mesh_exporter LogManager.logMessage("Converting skeleton to Ogre binary format...") result.append(executeOgreXMLConverter(globalSettings.ogreXMLConverterPath, skeletonFilePath, meshXMLConverterSettings)) # If modifiers need to be applied, we will need to create a new mesh with flattened modifiers. LogManager.logMessage("Apply Modifier: %s" % meshExportSettings.applyModifiers, Message.LVL_INFO) if (meshExportSettings.applyModifiers): mesh = meshObject.to_mesh(bpy.context.scene, True, 'PREVIEW') cleanUpMesh = True else: mesh = meshObject.data cleanUpMesh = False # prepare mesh. ogreMesh = Mesh(mesh, meshObject.vertex_groups, ogreSkeleton, meshExportSettings) LogManager.logMessage("Shared Vertices: %d" % len(ogreMesh.mSharedVertexBuffer.mVertexData), Message.LVL_INFO); LogManager.logMessage("Submeshes: %d" % len(ogreMesh.mSubMeshDict), Message.LVL_INFO); for index, submesh in enumerate(ogreMesh.mSubMeshDict.values()): if (submesh.mShareVertexBuffer): continue LogManager.logMessage(" [%d]%s: vertices: %d" % (index, submesh.mName if (submesh.mName) else '' , len(submesh.mVertexBuffer.mVertexData)), Message.LVL_INFO); # write mesh. meshFilePath = filepath + ".mesh.xml" file = open(meshFilePath, "w", encoding="utf8", newline="\n") ogreMesh.serialize(file) file.close() # remove mesh if we created a new one that has modifiers applied. if (cleanUpMesh): bpy.data.meshes.remove(mesh) ogreMesh = None LogManager.logMessage("Done exporting mesh XML.") # Run XML Converter if needed. if (meshExportSettings.runOgreXMLConverter): globalSettings = bpy.context.scene.ogre_mesh_exporter LogManager.logMessage("Converting mesh to Ogre binary format...") result.append(executeOgreXMLConverter(globalSettings.ogreXMLConverterPath, meshFilePath, meshXMLConverterSettings)) else: LogManager.logMessage("Success!") except IOError as err: LogManager.logMessage("I/O error(%d): %s" % (err.errno, err.strerror), Message.LVL_ERROR) result.append(False) #~ except Exception as err: #~ LogManager.logMessage(str(err), Message.LVL_ERROR) #~ result.append(False) #~ except: #~ traceback.print_exc() #~ result.append(False) return result
def __init__(self, blendMesh=None, blendVertexGroups=None, ogreSkeleton=None, exportSettings=MeshExportSettings()): # shared vertex buffer. self.mSharedVertexBuffer = VertexBuffer() # Blender mesh -> shared vertex index link. self.mSharedMeshVertexIndexLink = dict() # collection of submeshes. self.mSubMeshDict = dict() # skip blend mesh conversion if no blend mesh passed in. if (blendMesh is None): return self.mOgreSkeleton = ogreSkeleton hasBoneWeights = ogreSkeleton is not None # Lets do some pre checking to show warnings if needed. uvLayerCount = len(blendMesh.uv_layers) colorLayerCount = len(blendMesh.vertex_colors) if (uvLayerCount > 8): LogManager.logMessage( "More than 8 UV layers in this mesh. Only 8 will be exported.", Message.LVL_WARNING) if (colorLayerCount > 2): LogManager.logMessage( "More than 2 color layers in this mesh. Only 2 will be exported.", Message.LVL_WARNING) # setup shared vertex buffer. self.mSharedVertexBuffer.reset(uvLayerCount, colorLayerCount, hasBoneWeights) # split up the mesh into submeshes by materials. # we first get sub mesh shared vertices option. materialList = blendMesh.materials materialCount = len(materialList) subMeshProperties = blendMesh.ogre_mesh_exporter.subMeshProperties while (len(subMeshProperties) < materialCount): subMeshProperties.add() # add more items if needed. while (len(subMeshProperties) > materialCount): subMeshProperties.remove(0) # remove items if needed. LogManager.logMessage("Material Count: %d" % len(materialList), Message.LVL_INFO) for polygon in blendMesh.polygons: # get or create submesh. if (polygon.material_index in self.mSubMeshDict): subMesh = self.mSubMeshDict[polygon.material_index] else: # instantiate submesh base on wether sharing vertices or not. subMeshProperty = subMeshProperties[polygon.material_index] if (subMeshProperty.useSharedVertices): subMesh = SubMesh(self.mSharedVertexBuffer, self.mSharedMeshVertexIndexLink, subMeshProperty.name) else: subMesh = SubMesh(VertexBuffer(uvLayerCount, colorLayerCount, hasBoneWeights), name=subMeshProperty.name) subMesh.mMaterial = None if ( len(materialList) == 0) else materialList[polygon.material_index] if (exportSettings.requireMaterials and subMesh.mMaterial == None): LogManager.logMessage( "Some faces are not assigned with a material!", Message.LVL_WARNING) LogManager.logMessage( "To hide this warning, please uncheck the 'Require Materials' option.", Message.LVL_WARNING) self.mSubMeshDict[polygon.material_index] = subMesh # insert polygon. subMesh.insertPolygon(blendMesh, polygon, blendVertexGroups, ogreSkeleton, exportSettings.fixUpAxisToY)
def insertPolygon(self, blendMesh, polygon, blendVertexGroups=None, ogreSkeleton=None, fixUpAxisToY=True): polygonVertices = polygon.vertices polygonVertexCount = polygon.loop_total # extract uv information. # Here we convert blender uv data into our own # uv information that lists uvs by vertices. blendUVLoopLayers = blendMesh.uv_layers # construct empty polygon vertex uv list. polygonVertUVs = list() for i in range(polygonVertexCount): polygonVertUVs.append(list()) for uvLoopLayer in blendUVLoopLayers: for i, loopIndex in enumerate(polygon.loop_indices): polygonVertUVs[i].append(uvLoopLayer.data[loopIndex].uv) # extract color information. # Here we convert blender color data into our own # color information that lists colors by vertices. blendColorLoopLayers = blendMesh.vertex_colors # construct empty polygon vertex color list. polygonVertColors = list() for i in range(polygonVertexCount): polygonVertColors.append(list()) for colorLoopLayer in blendColorLoopLayers: for i, loopIndex in enumerate(polygon.loop_indices): polygonVertColors[i].append( colorLoopLayer.data[loopIndex].color) # loop through the vertices and add to this submesh. localIndices = list() useSmooth = polygon.use_smooth for index, uvs, colors in zip(polygonVertices, polygonVertUVs, polygonVertColors): vertex = blendMesh.vertices[index] norm = vertex.normal if (useSmooth) else polygon.normal # grab bone weights. boneWeights = list() if (ogreSkeleton is not None): for groupElement in vertex.groups: groupName = blendVertexGroups[groupElement.group].name boneIndex = ogreSkeleton.getBoneIndex(groupName) if (boneIndex == -1 or abs(groupElement.weight) < 0.000001): continue boneWeight = groupElement.weight boneWeights.append(BoneWeight(boneIndex, boneWeight)) # trim bone weight count if too many defined. if (len(boneWeights) > 4): LogManager.logMessage( "More than 4 bone weights are defined for a vertex! Best 4 will be used.", Message.LVL_WARNING) boneWeights.sort(key=attrgetter('mBoneWeight'), reverse=True) while (len(boneWeights) > 4): del boneWeights[-1] localIndices.append( self.mVertexBuffer.addVertex(index, vertex.co, norm, uvs, colors, boneWeights, fixUpAxisToY)) # construct triangle index data. if (polygonVertexCount is 3): self.mFaceData.append(localIndices) else: # split quad into triangles. self.mFaceData.append(localIndices[:3]) self.mFaceData.append( [localIndices[0], localIndices[2], localIndices[3]])
def exportMesh(meshObject, filepath): result = list() try: LogManager.logMessage("Output: %s.mesh.xml" % filepath, Message.LVL_INFO) # get combined mesh override & global settings. meshExportSettings = MeshExportSettings.fromRNA(meshObject) if (meshExportSettings.runOgreXMLConverter): meshXMLConverterSettings = MeshXMLConverterSettings.fromRNA(meshObject) # get linked armature parentObject = meshObject.parent if (parentObject and meshObject.parent_type == 'ARMATURE'): armatureObject = parentObject else: # check modifier stack, use first valid armature modifier. for modifier in meshObject.modifiers: if (modifier.type == 'ARMATURE' and (modifier.use_vertex_groups or modifier.use_bone_envelopes)): armatureObject = modifier.object # Do skeleton export first if armature exist. if (armatureObject): # get skeleton file path and name. if (meshExportSettings.skeletonNameFollowMesh): skeletonFilePath = filepath + '.skeleton.xml'; skeletonName = os.path.basename(filepath) else: dirname = os.path.dirname(filepath) skeletonFilePath = dirname + armatureObject.data.name + '.skeleton.xml'; skeletonName = armatureObject.data.name LogManager.logMessage("Skeleton: " + skeletonName, Message.LVL_INFO); # prepare skeleton. meshInverseMatrix = meshObject.matrix_world.inverted() ogreSkeleton = Skeleton(skeletonName, armatureObject, meshInverseMatrix, meshExportSettings.fixUpAxisToY) LogManager.logMessage("Bones: %d" % len(ogreSkeleton.mBones), Message.LVL_INFO); # write skeleton. file = open(skeletonFilePath, "w", encoding="utf8", newline="\n") ogreSkeleton.serialize(file) file.close() LogManager.logMessage("Done exporting skeleton XML.") # Run XML Converter if needed. if (meshExportSettings.runOgreXMLConverter): globalSettings = bpy.context.scene.ogre_mesh_exporter LogManager.logMessage("Converting skeleton to Ogre binary format...") result.append(executeOgreXMLConverter(globalSettings.ogreXMLConverterPath, skeletonFilePath, meshXMLConverterSettings)) # If modifiers need to be applied, we will need to create a new mesh with flattened modifiers. LogManager.logMessage("Apply Modifier: %s" % meshExportSettings.applyModifiers, Message.LVL_INFO) if (meshExportSettings.applyModifiers): mesh = meshObject.to_mesh(bpy.context.scene, True, 'PREVIEW') cleanUpMesh = True else: mesh = meshObject.data cleanUpMesh = False # prepare mesh. ogreMesh = Mesh(mesh, meshObject.vertex_groups, ogreSkeleton, meshExportSettings) LogManager.logMessage("Shared Vertices: %d" % len(ogreMesh.mSharedVertexBuffer.mVertexData), Message.LVL_INFO); LogManager.logMessage("Submeshes: %d" % len(ogreMesh.mSubMeshDict), Message.LVL_INFO); for index, submesh in enumerate(ogreMesh.mSubMeshDict.values()): if (submesh.mShareVertexBuffer): continue LogManager.logMessage(" [%d]%s: vertices: %d" % (index, submesh.mName if (submesh.mName) else '' , len(submesh.mVertexBuffer.mVertexData)), Message.LVL_INFO); # write mesh. meshFilePath = filepath + ".mesh.xml" file = open(meshFilePath, "w", encoding="utf8", newline="\n") ogreMesh.serialize(file) file.close() # remove mesh if we created a new one that has modifiers applied. if (cleanUpMesh): bpy.data.meshes.remove(mesh) ogreMesh = None LogManager.logMessage("Done exporting mesh XML.") # Run XML Converter if needed. if (meshExportSettings.runOgreXMLConverter): globalSettings = bpy.context.scene.ogre_mesh_exporter LogManager.logMessage("Converting mesh to Ogre binary format...") result.append(executeOgreXMLConverter(globalSettings.ogreXMLConverterPath, meshFilePath, meshXMLConverterSettings)) else: LogManager.logMessage("Success!") except IOError as err: LogManager.logMessage("I/O error(%d): %s" % (err.errno, err.strerror), Message.LVL_ERROR) result.append(False) #~ except Exception as err: #~ LogManager.logMessage(str(err), Message.LVL_ERROR) #~ result.append(False) #~ except: #~ traceback.print_exc() #~ result.append(False) return result
def exportMesh(meshObject, filepath): result = (False, None) try: LogManager.logMessage("Output: %s" % filepath, Message.LVL_INFO) # get combined mesh override & global settings. meshExportSettings = MeshExportSettings.fromRNA(meshObject) # If modifiers need to be applied, we will need to create a new mesh with flattened modifiers. LogManager.logMessage("Apply Modifier: %s" % meshExportSettings.applyModifiers, Message.LVL_INFO) if (meshExportSettings.applyModifiers): mesh = meshObject.to_mesh(bpy.context.scene, True, 'PREVIEW') cleanUpMesh = True else: mesh = meshObject.data cleanUpMesh = False # prepare mesh. ogreMesh = Mesh(mesh, meshExportSettings) LogManager.logMessage("Shared Vertices: %d" % len(ogreMesh.mSharedVertexBuffer.mVertexData), Message.LVL_INFO); LogManager.logMessage("Submeshes: %d" % len(ogreMesh.mSubMeshDict), Message.LVL_INFO); for index, submesh in enumerate(ogreMesh.mSubMeshDict.values()): if (submesh.mShareVertexBuffer): continue LogManager.logMessage(" [%d]%s: vertices: %d" % (index, submesh.mName if (submesh.mName) else '' , len(submesh.mVertexBuffer.mVertexData)), Message.LVL_INFO); # write mesh. file = open(filepath, "w", encoding="utf8", newline="\n") ogreMesh.serialize(file) file.close() # remove mesh if we created a new one that has modifiers applied. if (cleanUpMesh): bpy.data.meshes.remove(mesh) ogreMesh = None LogManager.logMessage("Done exporting XML.") # check if we need to convert to ogre mesh. if (meshExportSettings.runOgreXMLConverter): globalSettings = bpy.context.scene.ogre_mesh_exporter LogManager.logMessage("Converting mesh to Ogre binary format...") result = convertToOgreMesh(globalSettings.ogreXMLConverterPath, filepath, MeshXMLConverterSettings.fromRNA(meshObject)) else: LogManager.logMessage("Success!") result[0] = True except IOError as err: LogManager.logMessage("I/O error(%d): %s" % (err.errno, err.strerror), Message.LVL_ERROR) except Exception as err: LogManager.logMessage(str(err), Message.LVL_ERROR) except: traceback.print_exc() return result