view SceneGraph/BlenderScript/export_xml3.py @ 998:ad5232ad4952

add fb_test, minor fix
author yutaka@localhost.localdomain
date Fri, 15 Oct 2010 02:13:55 +0900
parents e1856ef4fc74
children
line wrap: on
line source

#!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