Ejemplo n.º 1
0
	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')
Ejemplo n.º 2
0
	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]])
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
	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)
Ejemplo n.º 5
0
	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)
Ejemplo n.º 6
0
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
Ejemplo n.º 7
0
    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')
Ejemplo n.º 8
0
	def invoke(self, context, event):
		# change our view to log panel.
		MainExporterPanel.sViewState = MainExporterPanel.VS_LOG

		self.globalSettings = bpy.context.scene.ogre_mesh_exporter
		self.collection = self.globalSettings.selectedObjectList.collection
		self.collectionCount = len(self.collection)
		self.pendingProcesses = dict()
		self.completedCount = 0
		self.canceling = False
		self.itemIndex = 0

		# clear log.
		LogManager.reset()

		# run modal operator mode.
		context.window_manager.modal_handler_add(self)
		self.timer = context.window_manager.event_timer_add(0.1, context.window)
		return {'RUNNING_MODAL'}
Ejemplo n.º 9
0
	def invoke(self, context, event):
		# change our view to log panel.
		MainExporterPanel.sViewState = MainExporterPanel.VS_LOG

		self.globalSettings = bpy.context.scene.ogre_mesh_exporter
		self.collection = self.globalSettings.selectedObjectList.collection
		self.collectionCount = len(self.collection)
		self.pendingProcesses = dict()
		self.completedCount = 0
		self.canceling = False
		self.itemIndex = 0

		# clear log.
		LogManager.reset()

		# run modal operator mode.
		context.window_manager.modal_handler_add(self)
		self.timer = context.window_manager.event_timer_add(0.1, context.window)
		return {'RUNNING_MODAL'}
Ejemplo n.º 10
0
    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)
Ejemplo n.º 11
0
    def draw(self, context):
        layout = self.layout
        globalSettings = bpy.context.scene.ogre_mesh_exporter

        # ####################################################
        # display preference view.
        # ####################################################
        if (MainExporterPanel.sViewState == MainExporterPanel.VS_PREFERENCE):
            col = layout.column(True)
            col.label("Global Static Config (shared across blend files):")
            staticConfigBox = col.box()
            col = staticConfigBox.column()
            col.prop(globalSettings, "ogreXMLConverterPath")
            col.prop(globalSettings, "ogreXMLConverterAdditionalArg")
            row = col.row()
            row.split()
            row.operator("ogre3d.preferences_apply_static_config",
                         icon='LIBRARY_DATA_DIRECT')

            xmlConverterOptionsBox = layout.column(True)
            xmlConverterOptionsBox.label("Global XML Converter Options:")

            disableConverterOptions = not globalSettings.useXMLConverterOptions
            row = xmlConverterOptionsBox.row(True)
            row.prop(globalSettings,
                     "useXMLConverterOptions",
                     "",
                     'MODIFIER',
                     toggle=True)
            row = row.row(True)
            if (disableConverterOptions): row.enabled = False
            row.prop(globalSettings, "extremityPoints")
            row.prop(globalSettings, "edgeLists", toggle=True)
            row.prop(globalSettings, "tangent", toggle=True)
            row = xmlConverterOptionsBox.row(True)
            if (disableConverterOptions): row.enabled = False
            row.prop(globalSettings, "tangentSemantic", "")
            row.prop(globalSettings, "tangentSize", "")
            row.prop(globalSettings, "splitMirrored", toggle=True)
            row.prop(globalSettings, "splitRotated", toggle=True)
            row = xmlConverterOptionsBox.row(True)
            if (disableConverterOptions): row.enabled = False
            row.prop(globalSettings, "reorganiseVertBuff", toggle=True)
            row.prop(globalSettings, "optimiseAnimation", toggle=True)

            row = layout.row()
            row.scale_y = 1.5
            row.operator("ogre3d.preferences_back", icon='BACK')
            return

        # ####################################################
        # display log view.
        # ####################################################
        elif (MainExporterPanel.sViewState == MainExporterPanel.VS_LOG):
            LogManager.drawLog(layout)
            return

        # ####################################################
        # display main view.
        # ####################################################

        # display selection list.
        col = layout.column()
        col.label("Selected:")
        selectedObjectList = globalSettings.selectedObjectList
        col.template_list(selectedObjectList, "collection", selectedObjectList,
                          "collectionIndex")

        # ####################################################
        # Material settings
        disableMaterialSettings = not globalSettings.exportMaterials
        materialExportBox = layout.column(True)
        materialExportBox.label("Material Settings:")
        row = materialExportBox.row(True)
        row.prop(globalSettings,
                 "exportMaterials",
                 "",
                 'MATERIAL',
                 toggle=True)
        row = row.row(True)
        if (disableMaterialSettings): row.enabled = False
        row.prop(globalSettings, "materialFile", "")
        row.prop(globalSettings, "copyTextures", "", 'TEXTURE', toggle=True)
        row = materialExportBox.row(True)
        if (disableMaterialSettings): row.enabled = False
        row.prop_enum(globalSettings, "materialExportMode", 'rend')
        row.prop_enum(globalSettings, "materialExportMode", 'game')
        row.prop_enum(globalSettings, "materialExportMode", 'custom')
        row = materialExportBox.row(True)
        if (disableMaterialSettings
                or globalSettings.materialExportMode != 'custom'):
            row.enabled = False
        row.prop(globalSettings, "templatePath", "")

        # ####################################################
        # Mesh settings
        disableMeshSettings = not globalSettings.exportMeshes
        meshExportBox = layout.column(True)
        meshExportBox.label("Mesh Settings:")
        row = meshExportBox.row(True)
        row.prop(globalSettings,
                 "exportMeshes",
                 "",
                 'MESH_MONKEY',
                 toggle=True)
        row = row.row(True)
        if (disableMeshSettings): row.enabled = False
        row.prop(globalSettings, "fixUpAxisToY", icon='NONE', toggle=True)
        row.prop(globalSettings, "requireMaterials", icon='NONE', toggle=True)
        row.prop(globalSettings, "applyModifiers", icon='NONE', toggle=True)
        row = meshExportBox.row(True)
        if (disableMeshSettings): row.enabled = False
        row.prop(globalSettings,
                 "skeletonNameFollowMesh",
                 icon='NONE',
                 toggle=True)
        row.prop(globalSettings,
                 "runOgreXMLConverter",
                 icon='NONE',
                 toggle=True)

        exportPathValid = os.path.isdir(globalSettings.exportPath)

        exportPathBox = layout.column(True)
        exportPathBox.label("Export Path:")
        exportPathBox.prop(globalSettings,
                           "exportPath",
                           "",
                           icon=('NONE' if (exportPathValid) else 'ERROR'))

        row = layout.row(True)
        subrow = row.row()
        subrow.scale_y = 1.5
        exportRow = subrow.row(True)
        exportRow.scale_y = 1.5
        if (not exportPathValid or len(selectedObjectList.collection) == 0 or \
         (not globalSettings.exportMeshes and not globalSettings.exportMaterials)):
            exportRow.enabled = False
        exportRow.operator("ogre3d.export", icon='SCRIPTWIN')
        subrow.operator("ogre3d.preferences", icon='SETTINGS')
        subrow.operator("ogre3d.help", icon='HELP')
        row = row.row()
        row.scale_y = 1.5
        row.alignment = 'RIGHT'
        row.operator("ogre3d.log", "", icon='CONSOLE')
Ejemplo n.º 12
0
    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)
Ejemplo n.º 13
0
    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]])
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
	def draw(self, context):
		layout = self.layout
		globalSettings = bpy.context.scene.ogre_mesh_exporter

		# ####################################################
		# display preference view.
		# ####################################################
		if (MainExporterPanel.sViewState == MainExporterPanel.VS_PREFERENCE):
			col = layout.column(True)
			col.label("Global Static Config (shared across blend files):")
			staticConfigBox = col.box()
			col = staticConfigBox.column()
			col.prop(globalSettings, "ogreXMLConverterPath")
			col.prop(globalSettings, "ogreXMLConverterAdditionalArg")
			row = col.row()
			row.split()
			row.operator("ogre3d.preferences_apply_static_config", icon = 'LIBRARY_DATA_DIRECT')

			xmlConverterOptionsBox = layout.column(True)
			xmlConverterOptionsBox.label("Global XML Converter Options:")

			disableConverterOptions = not globalSettings.useXMLConverterOptions
			row = xmlConverterOptionsBox.row(True)
			row.prop(globalSettings, "useXMLConverterOptions", "", 'MODIFIER', toggle = True)
			row = row.row(True)
			if (disableConverterOptions): row.enabled = False
			row.prop(globalSettings, "extremityPoints")
			row.prop(globalSettings, "edgeLists", toggle = True)
			row.prop(globalSettings, "tangent", toggle = True)
			row = xmlConverterOptionsBox.row(True)
			if (disableConverterOptions): row.enabled = False
			row.prop(globalSettings, "tangentSemantic", "")
			row.prop(globalSettings, "tangentSize", "")
			row.prop(globalSettings, "splitMirrored", toggle = True)
			row.prop(globalSettings, "splitRotated", toggle = True)
			row = xmlConverterOptionsBox.row(True)
			if (disableConverterOptions): row.enabled = False
			row.prop(globalSettings, "reorganiseVertBuff", toggle = True)
			row.prop(globalSettings, "optimiseAnimation", toggle = True)

			row = layout.row()
			row.scale_y = 1.5
			row.operator("ogre3d.preferences_back", icon = 'BACK')
			return

		# ####################################################
		# display log view.
		# ####################################################
		elif (MainExporterPanel.sViewState == MainExporterPanel.VS_LOG):
			LogManager.drawLog(layout)
			return

		# ####################################################
		# display main view.
		# ####################################################

		# display selection list.
		col = layout.column()
		col.label("Selected:")
		selectedObjectList = globalSettings.selectedObjectList
		col.template_list(selectedObjectList, "collection", selectedObjectList, "collectionIndex")

		# ####################################################
		# Material settings
		disableMaterialSettings = not globalSettings.exportMaterials
		materialExportBox = layout.column(True)
		materialExportBox.label("Material Settings:")
		row = materialExportBox.row(True)
		row.prop(globalSettings, "exportMaterials", "", 'MATERIAL', toggle = True)
		row = row.row(True)
		if (disableMaterialSettings): row.enabled = False
		row.prop(globalSettings, "materialFile", "")
		row.prop(globalSettings, "copyTextures", "", 'TEXTURE', toggle = True)
		row = materialExportBox.row(True)
		if (disableMaterialSettings): row.enabled = False
		row.prop_enum(globalSettings, "materialExportMode", 'rend')
		row.prop_enum(globalSettings, "materialExportMode", 'game')
		row.prop_enum(globalSettings, "materialExportMode", 'custom')
		row = materialExportBox.row(True)
		if (disableMaterialSettings or globalSettings.materialExportMode != 'custom'): row.enabled = False
		row.prop(globalSettings, "templatePath", "")

		# ####################################################
		# Mesh settings
		disableMeshSettings = not globalSettings.exportMeshes
		meshExportBox = layout.column(True)
		meshExportBox.label("Mesh Settings:")
		row = meshExportBox.row(True)
		row.prop(globalSettings, "exportMeshes", "", 'MESH_MONKEY', toggle = True)
		row = row.row(True)
		if (disableMeshSettings): row.enabled = False
		row.prop(globalSettings, "fixUpAxisToY", icon = 'NONE', toggle = True)
		row.prop(globalSettings, "requireMaterials", icon = 'NONE', toggle = True)
		row.prop(globalSettings, "applyModifiers", icon = 'NONE', toggle = True)
		row = meshExportBox.row(True)
		if (disableMeshSettings): row.enabled = False
		row.prop(globalSettings, "skeletonNameFollowMesh", icon = 'NONE', toggle = True)
		row.prop(globalSettings, "runOgreXMLConverter", icon = 'NONE', toggle = True)

		exportPathValid = os.path.isdir(globalSettings.exportPath)

		exportPathBox = layout.column(True)
		exportPathBox.label("Export Path:")
		exportPathBox.prop(globalSettings, "exportPath", "",
			icon = ('NONE' if (exportPathValid) else 'ERROR'))

		row = layout.row(True)
		subrow = row.row()
		subrow.scale_y = 1.5
		exportRow = subrow.row(True)
		exportRow.scale_y = 1.5
		if (not exportPathValid or len(selectedObjectList.collection) == 0 or \
			(not globalSettings.exportMeshes and not globalSettings.exportMaterials)):
			exportRow.enabled = False
		exportRow.operator("ogre3d.export", icon = 'SCRIPTWIN')
		subrow.operator("ogre3d.preferences", icon = 'SETTINGS')
		subrow.operator("ogre3d.help", icon = 'HELP')
		row = row.row()
		row.scale_y = 1.5
		row.alignment = 'RIGHT'
		row.operator("ogre3d.log", "", icon = 'CONSOLE')
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
    def modal(self, context, event):
        if (event.type == 'ESC'):  # Cancel
            for objectLog, process in self.pendingProcesses.items():
                process.kill()
                objectLog.mStatus = "(Canceling...)"
            self.canceling = True
            self.refresh(context)
            return {'RUNNING_MODAL'}

        if (LogManager.getLogCount() == 0):
            # add first item to log so we can see the progress.
            # TODO: Fix this for when no mesh data are exported but materials are.
            LogManager.addObjectLog(self.collection[0].name,
                                    ObjectLog.TYPE_MESH)
            LogManager.setProgress(0)
            self.refresh(context)
            return {'RUNNING_MODAL'}

        # poll subprocesses to make sure they are done and log accordingly.
        pendingDelete = list()
        for objectLog, process in self.pendingProcesses.items():
            result = process.poll()
            if (result == None): continue
            if (result == 0):
                objectLog.mStatus = ""
                objectLog.logMessage("OgreXMLConverter Success!")
                objectLog.mState = ObjectLog.ST_SUCCEED
                self.completedCount += 1
            elif (self.canceling):
                objectLog.mStatus = "(Canceled)"
                objectLog.logMessage("OgreXMLConverter Canceled.",
                                     Message.LVL_INFO)
                objectLog.mState = ObjectLog.ST_CANCELED
            else:
                objectLog.mStatus = ""
                objectLog.logMessage(
                    "OgreXMLConverter Failed! Check log file for more detail.",
                    Message.LVL_ERROR)
                objectLog.mState = ObjectLog.ST_FAILED
            pendingDelete.append(objectLog)  # cache it for delete.
        # delete from dictionary what needs to be deleted.
        # (Wish python has smarter way to do this -_-" Why can't they have erase iterator system?)
        for objectLog in pendingDelete:
            del self.pendingProcesses[objectLog]
        # check that we do not have too many process running. If so, skip until done.
        if (len(self.pendingProcesses) == OperatorExport.MAX_PENDING_PROCESSES
            ):
            self.refresh(context)
            return {'RUNNING_MODAL'}

        # Check exit strategy.
        if (self.itemIndex == self.collectionCount or self.canceling):
            if (len(self.pendingProcesses)): return {'RUNNING_MODAL'}
            context.window_manager.event_timer_remove(self.timer)
            LogManager.setProgress(100)
            self.refresh(context)
            return {'FINISHED'}

        # TODO: Handle exportMeshes == FALSE state.
        item = self.collection[self.itemIndex]
        object = bpy.data.objects[item.objectName]
        #~ time.sleep(0.1)
        result = exportMesh(
            object,
            "%s%s.mesh.xml" % (self.globalSettings.exportPath, item.name))
        objectLog = LogManager.getObjectLog(-1)
        if (not result[0]): objectLog.mState = ObjectLog.ST_FAILED
        elif (result[1]):
            self.pendingProcesses[objectLog] = result[1]
            objectLog.mStatus = "(Converting...)"
            objectLog.mState = ObjectLog.ST_CONVERTING
        else:
            objectLog.mState = ObjectLog.ST_SUCCEED
            self.completedCount += 1

        # update progress bar.
        LogManager.setProgress(
            (100 * self.completedCount) / self.collectionCount)

        self.itemIndex += 1
        if (self.itemIndex < self.collectionCount):
            LogManager.addObjectLog(self.collection[self.itemIndex].name,
                                    ObjectLog.TYPE_MESH)

        # tell blender to refresh.
        self.refresh(context)
        return {'RUNNING_MODAL'}
Ejemplo n.º 18
0
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
Ejemplo n.º 19
0
	def modal(self, context, event):
		if (event.type == 'ESC'):  # Cancel
			for objectLog, process in self.pendingProcesses.items():
				process.kill() 
				objectLog.mStatus = "(Canceling...)"
			self.canceling = True
			self.refresh(context)
			return {'RUNNING_MODAL'}

		if (LogManager.getLogCount() == 0):
			# add first item to log so we can see the progress.
			# TODO: Fix this for when no mesh data are exported but materials are.
			LogManager.addObjectLog(self.collection[0].name, ObjectLog.TYPE_MESH)
			LogManager.setProgress(0)
			self.refresh(context)
			return {'RUNNING_MODAL'}

		# poll subprocesses to make sure they are done and log accordingly.
		pendingDelete = list()
		for objectLog, process in self.pendingProcesses.items():
			result = process.poll()
			if (result == None): continue
			if (result == 0):
				objectLog.mStatus = ""
				objectLog.logMessage("OgreXMLConverter Success!")
				objectLog.mState = ObjectLog.ST_SUCCEED
				self.completedCount += 1
			elif (self.canceling):
				objectLog.mStatus = "(Canceled)"
				objectLog.logMessage("OgreXMLConverter Canceled.", Message.LVL_INFO)
				objectLog.mState = ObjectLog.ST_CANCELED
			else:
				objectLog.mStatus = ""
				objectLog.logMessage("OgreXMLConverter Failed! Check log file for more detail.", Message.LVL_ERROR)
				objectLog.mState = ObjectLog.ST_FAILED
			pendingDelete.append(objectLog) # cache it for delete.
		# delete from dictionary what needs to be deleted.
		# (Wish python has smarter way to do this -_-" Why can't they have erase iterator system?)
		for objectLog in pendingDelete: del self.pendingProcesses[objectLog]
		# check that we do not have too many process running. If so, skip until done.
		if (len(self.pendingProcesses) == OperatorExport.MAX_PENDING_PROCESSES):
			self.refresh(context)
			return {'RUNNING_MODAL'}

		# Check exit strategy.
		if (self.itemIndex == self.collectionCount or self.canceling):
			if (len(self.pendingProcesses)): return {'RUNNING_MODAL'}
			context.window_manager.event_timer_remove(self.timer)
			LogManager.setProgress(100)
			self.refresh(context)
			return {'FINISHED'}

		# TODO: Handle exportMeshes == FALSE state.
		item = self.collection[self.itemIndex]
		object = bpy.data.objects[item.objectName]
		#~ time.sleep(0.1)
		result = exportMesh(object, "%s%s.mesh.xml" % (self.globalSettings.exportPath, item.name))
		objectLog = LogManager.getObjectLog(-1)
		if (not result[0]): objectLog.mState = ObjectLog.ST_FAILED
		elif (result[1]):
			self.pendingProcesses[objectLog] = result[1]
			objectLog.mStatus = "(Converting...)"
			objectLog.mState = ObjectLog.ST_CONVERTING
		else:
			objectLog.mState = ObjectLog.ST_SUCCEED
			self.completedCount += 1

		# update progress bar.
		LogManager.setProgress((100 * self.completedCount) / self.collectionCount)

		self.itemIndex += 1
		if (self.itemIndex < self.collectionCount):
			LogManager.addObjectLog(self.collection[self.itemIndex].name, ObjectLog.TYPE_MESH)

		# tell blender to refresh.
		self.refresh(context)
		return {'RUNNING_MODAL'}