changeset 1234:be0eb46dd20a draft

update blender script for SceneGraph XML
author kazz <kazz@cr.ie.u-ryukyu.ac.jp>
date Thu, 20 Oct 2011 00:02:53 +0900
parents 247da1f5e625
children 1bb43068289b
files SceneGraph/BlenderScript/export_xml3.py
diffstat 1 files changed, 502 insertions(+), 465 deletions(-) [+]
line wrap: on
line diff
--- a/SceneGraph/BlenderScript/export_xml3.py	Tue Oct 18 12:25:08 2011 +0900
+++ b/SceneGraph/BlenderScript/export_xml3.py	Thu Oct 20 00:02:53 2011 +0900
@@ -1,465 +1,502 @@
-#!BPY
-"""Registration info for Blender menus:
-Name: 'Libps3 (.xml)'
-Blender: 240
-Group: 'Export'
-Tooltip: 'Export to (.xml) for libps3'
-"""
-
-
-######################################################
-# Importing modules
-######################################################
-
-import math
-#import subprocess
-import os
-#import Blender
-import struct
-import base64
-#from Blender import NMesh, Scene, Object, Material, Texture, Window
-#from Blender import sys as bsys, Mathutils, Draw, BGL
-#from Blender.sys import *
-
-global anim
-anim = 0
-
-
-global images, imageCount
-images = {}
-imageCount = 0
-
-
-__author__ = ["Shinji KONO"]
-__url__ = ("www.ie.u-ryukyu.ac.jp/~kono/")
-__version__ = "0.01a"
-__bpydoc__ = """\
-
-Cerium XML converter
-
-"""
-
-
-######################################################
-# Data Structures
-######################################################
-
-
-
-
-######################################################
-# Functions
-######################################################
-
-
-def create_derived_objects(ob):
-	if ob.parent and ob.parent.dupli_type != 'NONE':
-		return False, None
-
-	if ob.dupli_type != 'NONE':
-		ob.create_dupli_list()
-		return True, [(dob.object, dob.matrix) for dob in ob.dupli_list]
-	else:
-		return False, [(ob, ob.matrix)]
-
-# also used by X3D exporter
-def free_derived_objects(ob):
-	ob.free_dupli_list()
-
-
-#exporting an anime
-###change
-#def export_anime(object_name):
-def export_anime(object_name,file):
-	startF = Blender.Get('staframe')
-	endF = Blender.Get('endframe')
-	#str = ""
-	file.write("")
-	file.write("\t\t<anim frame=\"{0:d}\">\n".format((endF) ))
-	for i in range (startF, endF+1):
-		Blender.Set('curframe', i)
-		Blender.Redraw()
-		time1 = Blender.sys.time()
-
-		##### XML header ######
-		#get all the objects in this scene
-		activelayers = Window.ViewLayer()
-		for i in range(len(activelayers)):
-			activelayers[i] = 2**(activelayers[i]-1)
-		object_list1 = Blender.Scene.GetCurrent().getChildren()
-		object_list = []
-		matnames= []
-		for obj in object_list1:
-			if obj.Layer in activelayers:
-				object_list.append(obj)
-
-				if obj.type == 'Mesh':
-					materials_obj_list = []
-					materials_obj_list = obj.getData().materials
-					for mat in materials_obj_list:
-						if mat.name not in matnames:
-							matnames.append(mat.name)
-
-		##### Process Meshes ######
-		for obj in object_list:
-			matrix = obj.getMatrix()
-			if obj == object_name:
-				file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((matrix[3][0], matrix[3][1], matrix[3][2]) ))
-
-	file.write("\t\t</anim>\n")
-	#return str
-
-
-
-# exporting a mesh
-##change
-#def exportMesh(mesh, obj):
-def exportMesh(mesh, obj, file):
-
-	vdata = []   # list of [ii0, ii1, ii2, ...] lists indexed by Blender-Vertex-index
-	vlist = []
-	flist = []
-	tri_first = []
-	tri_second = []
-	tri_third = []
-
-	def addVertex(bvindex, coord, normal, uv):
-		index = -1
-		if bvindex < len(vdata):
-			for ivindex in vdata[bvindex]:
-				v = vlist[ivindex]
-				if (abs(v[0][0]-coord[0])<0.0001) and \
-				(abs(v[0][1]-coord[1])<0.0001) and \
-				(abs(v[0][2]-coord[2])<0.0001) and \
-				(abs(v[1][0]-normal[0])<0.0001) and \
-				(abs(v[1][1]-normal[1])<0.0001) and \
-				(abs(v[1][2]-normal[2])<0.0001):
-					if ((v[2]==[]) and (uv==[])) or \
-					((abs(v[2][0]-uv[0])<0.0001) and \
-					(abs(v[2][1]-uv[1])<0.0001)):
-						index = ivindex
-		if index < 0:
-			index = len(vlist)
-			vlist.append([coord, normal, uv])
-			while bvindex >= len(vdata):
-				vdata.append([])
-			vdata[bvindex].append(index)
-		return index
-
-	def addFace(mindex, index0, index1, index2):
-		while mindex >= len(flist):
-			flist.append([])
-		flist[mindex].append([index0, index1, index2])
-
-	###change
-	def getFaces():
-		##change
-		#str = ""
-		file.write("")
-		# matrix = obj.matrix
-		# already calcurated?
-		matrix = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
-
-		for mindex in range(len(flist)):
-			fl = flist[mindex]
-			if fl != []:
-				parent_name = obj.parent
-				if parent_name:
-					parent_name = "{0:s}".format(parent_name)
-					###change
-					#str += "\t<surface name=\"{0:s}\" size=\"{0:d}\" prim=\"Triangle\" parent={0:s}>\n".format((obj.name, len(fl)*3, parent_name[8:-1])
-					file.write("\t<surface name=\"{0:s}\" size=\"{1:d}\" prim=\"Triangle\" parent={2:s}>\n".format((obj.name, len(fl)*3, parent_name[8:-1]) ))
-				else:
-					###change
-					#str += "\t<surface name=\"{0:s}\" size=\"{0:d}\" prim=\"Triangle\" parent=\"NULL\">\n".format((obj.name, len(fl)*3)
-					file.write("\t<surface name=\"{0:s}\" size=\"{1:d}\" prim=\"Triangle\" parent=\"NULL\">\n".format((obj.name, len(fl)*3) ))
-				###change
-				#str += "\t\t<coordinate>\n"
-				file.write("\t\t<coordinate>\n")
-				for f in fl:
-					tri_first = vlist[f[0]]
-					tri_second = vlist[f[1]]
-					tri_third = vlist[f[2]]
-
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_first[0][0] + matrix[3][0], tri_first[0][1] + matrix[3][1], tri_first[0][2] + matrix[3][2]) ))
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_second[0][0] + matrix[3][0], tri_second[0][1] + matrix[3][1], tri_second[0][2] + matrix[3][2]) ))
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_third[0][0] + matrix[3][0], tri_third[0][1] + matrix[3][1], tri_third[0][2] + matrix[3][2]) ))
-				file.write("\t\t</coordinate>\n")
-
-				file.write("\t\t<normal>\n")
-				for f in fl:
-					tri_first = vlist[f[0]]
-					tri_second = vlist[f[1]]
-					tri_third = vlist[f[2]]
-
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_first[1][0], tri_first[1][1], tri_first[1][2]) ))
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_second[1][0], tri_second[1][1], tri_second[1][2]) ))
-					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format((tri_third[1][0], tri_third[1][1], tri_third[1][2]) ))
-				file.write("\t\t</normal>\n" )
-
-				file.write("\t\t<model>\n" )
-				###parameter of translate
-				file.write("\t\t\t{0:f} {1:f} {2:f}\n".format( (matrix[3][0], matrix[3][1], matrix[3][2]) ))
-				file.write("\t\t</model>\n")
-
-				if tri_first[2] != []:
-					file.write("\t\t<texture>\n")
-					for f in fl:
-						tri_first = vlist[f[0]]
-						tri_second = vlist[f[1]]
-						tri_third = vlist[f[2]]
-
-						file.write("\t\t\t{0:f} {1:f}\n".format((tri_first[2][0], tri_first[2][1]) ))
-						file.write("\t\t\t{0:f} {1:f}\n".format((tri_second[2][0], tri_second[2][1]) ))
-						file.write("\t\t\t{0:f} {0:f}\n".format((tri_third[2][0], tri_third[2][1]) ))
-					file.write("\t\t</texture>\n")
-				else:
-					file.write("\t\t<texture/>\n")
-
-
-				### get texture_image and change base64 data
-				texture = mesh.faces[0].image
-				if texture:
-					file.write(loadTexture(texture.name))	
-				else:
-					file.write("\t\t<image name=\"{0:s}\">\n".format(("sample_white.png") ))
-					file.write("\t\t</image>\n")
-
-		#return str
-
-	vdata = []
-	vlist = []
-	flist = []
-	for face in mesh.faces:
-		iis = [-1, -1, -1, -1]
-		for vi in range(len(face.v)):
-			vert = face.v[vi]
-			if face.smooth:
-				normal = vert.no
-			else:
-				normal = face.no
-			if len(face.uv) == len(face.v):
-				uv = face.uv[vi]
-			else:
-				uv = []
-			iis[vi] = addVertex(vert.index, vert.co, normal, uv)
-		addFace(face.materialIndex, iis[0], iis[1], iis[2])
-		if len(face.v)==4:
-			addFace(face.materialIndex, iis[2], iis[3], iis[0])
-
-	#str = ""
-	#str += getFaces()
-	getFaces();
-
-	#return str
-
-def make_material_chunk(material, image):
-	if image:
-		file.write(loadTexture(image))	
-	else:
-		file.write("\t\t<image name=\"{0:s}\">\n".format(("sample_white.png") ))
-		global sample_whited
-		if (sample_whited == 0):
-
-		    file.write("\t\t\tiVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAAEElEQVQImWP8zwABTAwUMQBJQQEP\n");
-		    file.write("\t\t\tlYH+agAAAABJRU5ErkJggg==\n");
-		    sample_whited=1
-
-		file.write("\t\t</image>\n")
-
-######################################################
-# EXPORT
-######################################################
-
-
-def save_xml(filename, context):
-	'''Save the Blender scene to a Cerium xml file.'''
-	# Time the export
-	global MatSaved
-	global anim
-	MatSaved = 0
-	
-	if not filename.lower().endswith('.xml'):
-		filename += '.xml' 
-	print("Saving to '" + filename + "'...\n")
-	file = open(filename, 'w')
-    
-	# XXX
-#       if not BPyMessages.Warning_SaveOver(filename):
-#               return
-	
-	# XXX
-	time1 = time.clock()
-#       time1= Blender.sys.time()
-#       Blender.Window.WaitCursor(1)
-
-	##### XML header ######
-	file.write("<?xml version=\"1.0\"?>\n")
-	file.write("<OBJECT-3D>\n")
-
-	sce = context.scene
-  
-	# Get all the supported objects selected in this scene:
-	# ob_sel= list(sce.objects.context)
-	# mesh_objects = [ (ob, me) for ob in ob_sel   for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ]
-	# empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ]
-
-	# Make a list of all materials used in the selected meshes (use a dictionary,
-	# each material is added once):
-	materialDict = {}
-	mesh_objects = []
-	for ob in [ob for ob in context.scene.objects if ob.is_visible()]:
-#       for ob in sce.objects.context:
-
-		# get derived objects
-		free, derived = create_derived_objects(ob)
-
-		if derived == None: continue
-
-		for ob_derived, mat in derived:
-#               for ob_derived, mat in getDerivedObjects(ob, False):
-
-			if ob.type not in ('MESH', 'CURVE', 'SURFACE', 'TEXT', 'META'):
-				continue
-
-			data = ob_derived.create_mesh(True, 'PREVIEW')
-#                       data = getMeshFromObject(ob_derived, None, True, False, sce)
-			if data:
-				data.transform(mat)
-#                               data.transform(mat, recalc_normals=False)
-				mesh_objects.append((ob_derived, data))
-				mat_ls = data.materials
-				mat_ls_len = len(mat_ls)
-
-				# get material/image tuples.
-				if len(data.uv_textures):
-#                               if data.faceUV:
-					if not mat_ls:
-						mat = mat_name = None
-
-					for f, uf in zip(data.faces, data.active_uv_texture.data):
-						if mat_ls:
-							mat_index = f.material_index
-#                                                       mat_index = f.mat
-							if mat_index >= mat_ls_len:
-								mat_index = f.mat = 0
-							mat = mat_ls[mat_index]
-							if mat: mat_name = mat.name
-							else:   mat_name = None
-						# else there alredy set to none
-
-						img = uf.image
-#                                               img = f.image
-						if img: img_name = img.name
-						else:   img_name = None
-
-						materialDict.setdefault((mat_name, img_name), (mat, img) )
-
-
-				else:
-					for mat in mat_ls:
-						if mat: # material may be None so check its not.
-							materialDict.setdefault((mat.name, None), (mat, None) )
-
-					# Why 0 Why!
-					for f in data.faces:
-						if f.material_index >= mat_ls_len:
-#                                               if f.mat >= mat_ls_len:
-							f.material_index = 0
-							# f.mat = 0
-
-		if free:
-			free_derived_objects(ob)
-
-
-	# Make material chunks for all materials used in the meshes:
-	for mat_and_image in materialDict.values():
-		print("make material chunk {0:s}\n".format(mat_and_image[1]))
-		make_material_chunk(mat_and_image[0], mat_and_image[1])
-
-	# Give all objects a unique ID and build a dictionary from object name to object id:
-	"""
-	name_to_id = {}
-	for ob, data in mesh_objects:
-		name_to_id[ob.name]= len(name_to_id)
-	#for ob in empty_objects:
-	#       name_to_id[ob.name]= len(name_to_id)
-	"""
-
-	# Create object chunks for all meshes:
-	for ob, blender_mesh in mesh_objects:
-		print("export mesh {0:s}\n".format(ob.name))
-		exportMesh(blender_mesh,ob,file)
-		if (anim):
-		    export_anime(obj,file)
-		file.write("\t</surface>\n")
-#               if not blender_mesh.users:
-		bpy.data.remove_mesh(blender_mesh)
-#               blender_mesh.verts = None
-
-	# Close the file:
-	file.close()
-
-
-
-
-def loadTexture(texture):
-	global images, imageCount
-	name = texture.name
-	if name in images:
-		return "\t\t<image name=\"" + name + "\"/>\n"	
-	out = "\t\t<image name=\"" + name + "\">\n"
-	imageCount += 1
-	images[name] = imageCount
-	image_path = texture.getFilename()
-	input = open(expandpath(image_path), 'r')	
-	output = open('output.txt', 'w')
-	base64.encode(input,output)
-	input.close()
-	output.close()
-	input = open('output.txt', 'r')
-	for b64 in input.readlines():
-		out += "\t\t\t{0:s}".format(b64)
-	input.close()
-	os.remove('output.txt')
-	out += "\t\t</image>\n"
-	return out
-
-
-from bpy.props import *
-class ExportPS3(bpy.types.Operator):
-	'''Export to Cerium XML file format.'''
-	bl_idname = "export.ps3cerium"
-	bl_label = 'Export PS3 Cerium'
-
-	# List of operator properties, the attributes will be assigned
-	# to the class instance from the operator settings before calling.
-
-
-	path = StringProperty(name="File Path", description="File path used for exporting the Cerium XML file", maxlen= 1024, default= "")
-
-
-	def execute(self, context):
-		save_xml(self.properties.path, context)
-		return ('FINISHED',)
-
-	def invoke(self, context, event):
-		wm = context.manager
-		wm.add_fileselect(self)
-		return ('RUNNING_MODAL',)
-
-	def poll(self, context): # Poll isnt working yet
-		return context.active_object != None
-
-bpy.ops.add(ExportPS3)
-
-# Add to a menu
-import dynamic_menu
-
-def menu_func(self, context):
-    default_path = bpy.data.filename.replace(".blend", ".xml")
-    self.layout.operator(ExportPS3.bl_idname, text="PS3 Cerium...").path = default_path 
-
-menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
-
-# end
+#!BPY
+"""Registration info for Blender menus:
+Name: 'Libps3 (.xml)'
+Blender: 240
+Group: 'Export'
+Tooltip: 'Export to (.xml) for libps3'
+"""
+
+bl_info = {
+    "name": "PS3 Cerium (.xml)",
+    "author": "Shinji KONO",
+    "version": (2, 0, 0),
+    "blender": (2, 5, 8),
+    "api": 37702,
+    "location": "File > Import-Export",
+    "description": "Export PS3 Cerium (.xml)",
+    "warning": "",
+   # "wiki_url": "",
+   # "tracker_url": "",
+    "category": "Import-Export"}
+
+
+
+######################################################
+# Importing modules
+######################################################
+
+import math
+#import subprocess
+import os
+#import Blender
+import struct
+import base64
+import bpy
+#from Blender import NMesh, Scene, Object, Material, Texture, Window
+#from Blender import sys as bsys, Mathutils, Draw, BGL
+#from Blender.sys import *
+
+global anim
+anim = 0
+
+
+global images, imageCount
+images = {}
+imageCount = 0
+
+
+__author__ = ["Shinji KONO"]
+__url__ = ("www.ie.u-ryukyu.ac.jp/~kono/")
+__version__ = "0.01a"
+__bpydoc__ = """\
+
+Cerium XML converter
+
+"""
+
+
+######################################################
+# Data Structures
+######################################################
+
+
+
+
+######################################################
+# Functions
+######################################################
+
+
+def create_derived_objects(ob):
+	if ob.parent and ob.parent.dupli_type != 'NONE':
+		return False, None
+
+	if ob.dupli_type != 'NONE':
+		ob.create_dupli_list()
+		return True, [(dob.object, dob.matrix_basis) for dob in ob.dupli_list]
+	else:
+		return False, [(ob, ob.matrix_basis)] # Which do we use basis, local or world for matrix?
+
+# also used by X3D exporter
+def free_derived_objects(ob):
+	ob.free_dupli_list()
+
+
+#exporting an anime
+###change
+#def export_anime(object_name):
+def export_anime(object_name,file):
+	startF = Blender.Get('staframe')
+	endF = Blender.Get('endframe')
+	#str = ""
+	file.write("")
+	file.write("\t\t<anim frame=\"{0:d}\">\n".format(endF))
+	for i in range (startF, endF+1):
+		Blender.Set('curframe', i)
+		Blender.Redraw()
+#		time1 = Blender.sys.time()
+
+		##### XML header ######
+		#get all the objects in this scene
+		activelayers = Window.ViewLayer()
+		for i in range(len(activelayers)):
+			activelayers[i] = 2**(activelayers[i]-1)
+		object_list1 = Blender.Scene.GetCurrent().getChildren()
+		object_list = []
+		matnames= []
+		for obj in object_list1:
+			if obj.Layer in activelayers:
+				object_list.append(obj)
+
+				if obj.type == 'Mesh':
+					materials_obj_list = []
+					materials_obj_list = obj.getData().materials
+					for mat in materials_obj_list:
+						if mat.name not in matnames:
+							matnames.append(mat.name)
+
+		##### Process Meshes ######
+		for obj in object_list:
+			matrix = obj.getMatrix()
+			if obj == object_name:
+				file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(matrix[3][0], matrix[3][1], matrix[3][2]))
+
+	file.write("\t\t</anim>\n")
+	#return str
+
+
+
+# exporting a mesh
+##change
+#def exportMesh(mesh, obj):
+def exportMesh(mesh, obj, file):
+
+	vdata = []   # list of [ii0, ii1, ii2, ...] lists indexed by Blender-Vertex-index
+	vlist = []
+	flist = []
+	tri_first = []
+	tri_second = []
+	tri_third = []
+
+	def addVertex(bvindex, coord, normal, uv):
+		index = -1
+		if bvindex < len(vdata):
+			for ivindex in vdata[bvindex]:
+				v = vlist[ivindex]
+				if (abs(v[0][0]-coord[0])<0.0001) and \
+				(abs(v[0][1]-coord[1])<0.0001) and \
+				(abs(v[0][2]-coord[2])<0.0001) and \
+				(abs(v[1][0]-normal[0])<0.0001) and \
+				(abs(v[1][1]-normal[1])<0.0001) and \
+				(abs(v[1][2]-normal[2])<0.0001):
+					if ((v[2]==[]) and (uv==[])) or \
+					((abs(v[2][0]-uv[0])<0.0001) and \
+					(abs(v[2][1]-uv[1])<0.0001)):
+						index = ivindex
+		if index < 0:
+			index = len(vlist)
+			vlist.append([coord, normal, uv])
+			while bvindex >= len(vdata):
+				vdata.append([])
+			vdata[bvindex].append(index)
+		return index
+
+	def addFace(mindex, index0, index1, index2):
+		while mindex >= len(flist):
+			flist.append([])
+		flist[mindex].append([index0, index1, index2])
+
+	###change
+	def getFaces():
+		##change
+		#str = ""
+		file.write("")
+		# matrix = obj.matrix
+		# already calcurated?
+		matrix = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]]
+
+		for mindex in range(len(flist)):
+			fl = flist[mindex]
+			if fl != []:
+				parent_name = obj.parent
+				if parent_name:
+					parent_name = "{0:s}".format(parent_name)
+					###change
+					#str += "\t<surface name=\"{0:s}\" size=\"{0:d}\" prim=\"Triangle\" parent={0:s}>\n".format((obj.name, len(fl)*3, parent_name[8:-1])
+					file.write("\t<surface name=\"{0:s}\" size=\"{1:d}\" prim=\"Triangle\" parent={2:s}>\n".format(obj.name, len(fl)*3, parent_name[8:-1]))
+				else:
+					###change
+					#str += "\t<surface name=\"{0:s}\" size=\"{0:d}\" prim=\"Triangle\" parent=\"NULL\">\n".format((obj.name, len(fl)*3)
+					file.write("\t<surface name=\"{0:s}\" size=\"{1:d}\" prim=\"Triangle\" parent=\"NULL\">\n".format(obj.name, len(fl)*3))
+				###change
+				#str += "\t\t<coordinate>\n"
+				file.write("\t\t<coordinate>\n")
+				for f in fl:
+					tri_first = vlist[f[0]]
+					tri_second = vlist[f[1]]
+					tri_third = vlist[f[2]]
+
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_first[0][0] + matrix[3][0], tri_first[0][1] + matrix[3][1], tri_first[0][2] + matrix[3][2] ))
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_second[0][0] + matrix[3][0], tri_second[0][1] + matrix[3][1], tri_second[0][2] + matrix[3][2] ))
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_third[0][0] + matrix[3][0], tri_third[0][1] + matrix[3][1], tri_third[0][2] + matrix[3][2]))
+				file.write("\t\t</coordinate>\n")
+
+				file.write("\t\t<normal>\n")
+				for f in fl:
+					tri_first = vlist[f[0]]
+					tri_second = vlist[f[1]]
+					tri_third = vlist[f[2]]
+
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_first[1][0], tri_first[1][1], tri_first[1][2]))
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_second[1][0], tri_second[1][1], tri_second[1][2]))
+					file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(tri_third[1][0], tri_third[1][1], tri_third[1][2]))
+				file.write("\t\t</normal>\n" )
+
+				file.write("\t\t<model>\n" )
+				###parameter of translate
+				file.write("\t\t\t{0:f} {1:f} {2:f}\n".format(matrix[3][0], matrix[3][1], matrix[3][2]))
+				file.write("\t\t</model>\n")
+
+				if tri_first[2] != []:
+					file.write("\t\t<texture>\n")
+					for f in fl:
+						tri_first = vlist[f[0]]
+						tri_second = vlist[f[1]]
+						tri_third = vlist[f[2]]
+
+						file.write("\t\t\t{0:f} {1:f}\n".format(tri_first[2][0], tri_first[2][1]))
+						file.write("\t\t\t{0:f} {1:f}\n".format(tri_second[2][0], tri_second[2][1]))
+						file.write("\t\t\t{0:f} {0:f}\n".format(tri_third[2][0], tri_third[2][1]))
+					file.write("\t\t</texture>\n")
+				else:
+					file.write("\t\t<texture/>\n")
+
+
+				### get texture_image and change base64 data
+				#texture = mesh.faces[0].image
+				texture = None
+				if mesh.uv_texture_stencil:
+					texture = mesh.uv_texture_stencil.data[0].image
+				if texture:
+					file.write(loadTexture(texture.name))	
+				else:
+					file.write("\t\t<image name=\"{0:s}\">\n".format("sample_white.png"))
+					file.write("\t\t</image>\n")
+
+		#return str
+
+	vdata = []
+	vlist = []
+	flist = []
+	for face in mesh.faces:
+		iis = [-1, -1, -1, -1]
+		for vi in range(len(face.vertices)):
+#			vert = face.vertices[vi]
+			vert = mesh.vertices[face.vertices[vi]]
+			if face.use_smooth:
+				normal = vert.normal
+			else:
+				normal = face.normal
+			uvs = []
+			if not (mesh.uv_texture_stencil is None):
+				uv_texture = mesh.uv_texture_stencil.data[face.index]
+				uvs = [uv_texture.uv1, uv_texture.uv2, uv_texture.uv3, uv_texture.uv4]
+
+			if len(uvs) == len(face.vertices):
+				uv = uvs[vi]
+			else:
+				uv = []
+			iis[vi] = addVertex(vert.index, vert.co, normal, uv)
+			# MEMO: bpy.context.scene.objects['Cube'].data.uv_textures['UVTex'].data[0].uv1
+		addFace(face.material_index, iis[0], iis[1], iis[2])
+		if len(face.vertices) == 4:
+			addFace(face.material_index, iis[2], iis[3], iis[0])
+
+	#str = ""
+	#str += getFaces()
+	getFaces();
+
+	#return str
+	
+sample_whited = 0
+
+def make_material_chunk(material, image, file):
+	if image:
+		file.write(loadTexture(image))	
+	else:
+		file.write("\t\t<image name=\"{0:s}\">\n".format("sample_white.png"))
+		global sample_whited
+		if (sample_whited == 0):
+
+		    file.write("\t\t\tiVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAAEElEQVQImWP8zwABTAwUMQBJQQEP\n");
+		    file.write("\t\t\tlYH+agAAAABJRU5ErkJggg==\n");
+		    sample_whited=1
+
+		file.write("\t\t</image>\n")
+
+######################################################
+# EXPORT
+######################################################
+
+
+def save_xml(filename, context):
+	'''Save the Blender scene to a Cerium xml file.'''
+	# Time the export
+	global MatSaved
+	global anim
+	MatSaved = 0
+	
+	if not filename.lower().endswith('.xml'):
+		filename += '.xml' 
+	print("Saving to '" + filename + "'...\n")
+	file = open(filename, 'w')
+    
+	# XXX
+#       if not BPyMessages.Warning_SaveOver(filename):
+#               return
+	
+	# XXX
+#	time1 = time.clock()
+#       time1= Blender.sys.time()
+#       Blender.Window.WaitCursor(1)
+
+	##### XML header ######
+	file.write("<?xml version=\"1.0\"?>\n")
+	file.write("<OBJECT-3D>\n")
+
+	sce = context.scene
+  
+	# Get all the supported objects selected in this scene:
+	# ob_sel= list(sce.objects.context)
+	# mesh_objects = [ (ob, me) for ob in ob_sel   for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ]
+	# empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ]
+
+	# Make a list of all materials used in the selected meshes (use a dictionary,
+	# each material is added once):
+	materialDict = {}
+	mesh_objects = []
+	for ob in [ob for ob in context.scene.objects if ob.is_visible(bpy.context.scene)]:
+#       for ob in sce.objects.context:
+
+		# get derived objects
+		free, derived = create_derived_objects(ob)
+
+		if derived == None: continue
+
+		for ob_derived, mat in derived:
+#               for ob_derived, mat in getDerivedObjects(ob, False):
+
+			if ob.type not in ('MESH', 'CURVE', 'SURFACE', 'TEXT', 'META'):
+				continue
+
+			data = ob_derived.to_mesh(sce, True, 'PREVIEW')
+#                       data = getMeshFromObject(ob_derived, None, True, False, sce)
+			if data:
+				data.transform(mat)
+#                               data.transform(mat, recalc_normals=False)
+				mesh_objects.append((ob_derived, data))
+				mat_ls = data.materials
+				mat_ls_len = len(mat_ls)
+
+				# get material/image tuples.
+				if len(data.uv_textures):
+#                               if data.faceUV:
+					if not mat_ls:
+						mat = mat_name = None
+
+					for f, uf in zip(data.faces, data.uv_texture_stencil.data):
+						if mat_ls:
+							mat_index = f.material_index
+#                                                       mat_index = f.mat
+							if mat_index >= mat_ls_len:
+								mat_index = f.mat = 0
+							mat = mat_ls[mat_index]
+							if mat: mat_name = mat.name
+							else:   mat_name = None
+						# else there alredy set to none
+
+						img = uf.image
+#                                               img = f.image
+						if img: img_name = img.name
+						else:   img_name = None
+
+						materialDict.setdefault((mat_name, img_name), (mat, img) )
+
+
+				else:
+					for mat in mat_ls:
+						if mat: # material may be None so check its not.
+							materialDict.setdefault((mat.name, None), (mat, None) )
+
+					# Why 0 Why!
+					for f in data.faces:
+						if f.material_index >= mat_ls_len:
+#                                               if f.mat >= mat_ls_len:
+							f.material_index = 0
+							# f.mat = 0
+
+		if free:
+			free_derived_objects(ob)
+
+
+	# Make material chunks for all materials used in the meshes:
+	for mat_and_image in materialDict.values():
+		print("make material chunk {0:s}\n".format(mat_and_image[1]))
+		make_material_chunk(mat_and_image[0], mat_and_image[1], file)
+
+	# Give all objects a unique ID and build a dictionary from object name to object id:
+	"""
+	name_to_id = {}
+	for ob, data in mesh_objects:
+		name_to_id[ob.name]= len(name_to_id)
+	#for ob in empty_objects:
+	#       name_to_id[ob.name]= len(name_to_id)
+	"""
+
+	# Create object chunks for all meshes:
+	for ob, blender_mesh in mesh_objects:
+		print("export mesh {0:s}\n".format(ob.name))
+		exportMesh(blender_mesh,ob,file)
+		if (anim):
+		    export_anime(obj,file)
+		file.write("\t</surface>\n")
+#               if not blender_mesh.users:
+#		bpy.data.remove_mesh(blender_mesh)
+		bpy.data.meshes.remove(blender_mesh)
+#               blender_mesh.verts = None
+
+	# Close the file:
+	file.close()
+
+
+
+
+def loadTexture(texture):
+	global images, imageCount
+	name = texture.name
+	if name in images:
+		return "\t\t<image name=\"" + name + "\"/>\n"	
+	out = "\t\t<image name=\"" + name + "\">\n"
+	imageCount += 1
+	images[name] = imageCount
+	image_path = texture.filepath
+	input = open(expandpath(image_path), 'r')	
+	output = open('output.txt', 'w')
+	base64.encode(input,output)
+	input.close()
+	output.close()
+	input = open('output.txt', 'r')
+	for b64 in input.readlines():
+		out += "\t\t\t{0:s}".format(b64)
+	input.close()
+	os.remove('output.txt')
+	out += "\t\t</image>\n"
+	return out
+
+from bpy.props import *
+class ExportPS3(bpy.types.Operator):
+	'''Export to Cerium XML file format.'''
+	bl_idname = "export.ps3cerium"
+	bl_label = 'Export PS3 Cerium'
+
+	# List of operator properties, the attributes will be assigned
+	# to the class instance from the operator settings before calling.
+
+	path = StringProperty(subtype='FILE_PATH')
+
+#	path = StringProperty(name="File Path", description="File path used for exporting the Cerium XML file", maxlen= 1024, default= "")
+
+
+	def execute(self, context):
+#		save_xml(self.properties.path, context)
+		save_xml("/test.xml", context)
+		return {'FINISHED'}
+	def invoke(self, context, event):
+		wm = context.window_manager
+		wm.fileselect_add(self)
+		return {'RUNNING_MODAL'}
+
+
+# Add to a menu
+
+def menu_func(self, context):
+    default_path = bpy.data.filepath.replace(".blend", ".xml")
+    self.layout.operator(ExportPS3.bl_idname, text="PS3 Cerium (.xml)").path = default_path 
+
+    
+def register():
+    bpy.utils.register_module(__name__)
+
+    bpy.types.INFO_MT_file_export.append(menu_func)
+
+
+def unregister():
+    bpy.utils.unregister_module(__name__)
+
+    bpy.types.INFO_MT_file_export.remove(menu_func)
+
+
+if __name__ == "__main__":
+    register()
+
+# end