Mercurial > hg > Members > kono > Cerium
comparison SceneGraph/BlenderScript/export_xml3.py @ 660:e1856ef4fc74
export xml3 not yet worked.
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 27 Nov 2009 20:16:51 +0900 |
parents | 30a72124c7fd |
children |
comparison
equal
deleted
inserted
replaced
659:00391feebc79 | 660:e1856ef4fc74 |
---|---|
19 import base64 | 19 import base64 |
20 #from Blender import NMesh, Scene, Object, Material, Texture, Window | 20 #from Blender import NMesh, Scene, Object, Material, Texture, Window |
21 #from Blender import sys as bsys, Mathutils, Draw, BGL | 21 #from Blender import sys as bsys, Mathutils, Draw, BGL |
22 #from Blender.sys import * | 22 #from Blender.sys import * |
23 | 23 |
24 global anim | |
25 anim = 0 | |
26 | |
27 | |
24 global images, imageCount | 28 global images, imageCount |
25 images = {} | 29 images = {} |
26 imageCount = 0 | 30 imageCount = 0 |
27 | 31 |
28 def info(object, spacing=10, collapse=1): | 32 |
29 """Print methods and doc strings. | 33 __author__ = ["Shinji KONO"] |
30 | 34 __url__ = ("www.ie.u-ryukyu.ac.jp/~kono/") |
31 Takes module, class, list, dictionary, or string.""" | 35 __version__ = "0.01a" |
32 methodList = [e for e in dir(object) if callable(getattr(object, e))] | 36 __bpydoc__ = """\ |
33 processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s) | 37 |
34 print("\n".join(["{0:s} {1:s}".format((method.ljust(spacing), | 38 Cerium XML converter |
35 processFunc(str(getattr(object, method).__doc__)))) | 39 |
36 for method in methodList])) | 40 """ |
37 | 41 |
38 | 42 |
39 ###################################################### | 43 ###################################################### |
40 # Data Structures | 44 # Data Structures |
41 ###################################################### | 45 ###################################################### |
45 | 49 |
46 ###################################################### | 50 ###################################################### |
47 # Functions | 51 # Functions |
48 ###################################################### | 52 ###################################################### |
49 | 53 |
50 # Image Get ? | 54 |
51 # New name based on old with a different extension | 55 def create_derived_objects(ob): |
52 def newFName(ext): | 56 if ob.parent and ob.parent.dupli_type != 'NONE': |
53 return Blender.Get('filename')[: -len(Blender.Get('filename').split('.', -1)[-1]) ] + ext | 57 return False, None |
58 | |
59 if ob.dupli_type != 'NONE': | |
60 ob.create_dupli_list() | |
61 return True, [(dob.object, dob.matrix) for dob in ob.dupli_list] | |
62 else: | |
63 return False, [(ob, ob.matrix)] | |
64 | |
65 # also used by X3D exporter | |
66 def free_derived_objects(ob): | |
67 ob.free_dupli_list() | |
54 | 68 |
55 | 69 |
56 #exporting an anime | 70 #exporting an anime |
57 ###change | 71 ###change |
58 #def export_anime(object_name): | 72 #def export_anime(object_name): |
77 matnames= [] | 91 matnames= [] |
78 for obj in object_list1: | 92 for obj in object_list1: |
79 if obj.Layer in activelayers: | 93 if obj.Layer in activelayers: |
80 object_list.append(obj) | 94 object_list.append(obj) |
81 | 95 |
82 if obj.getType() == "Mesh": | 96 if obj.type == 'Mesh': |
83 materials_obj_list = [] | 97 materials_obj_list = [] |
84 materials_obj_list = obj.getData().materials | 98 materials_obj_list = obj.getData().materials |
85 for mat in materials_obj_list: | 99 for mat in materials_obj_list: |
86 if mat.name not in matnames: | 100 if mat.name not in matnames: |
87 matnames.append(mat.name) | 101 matnames.append(mat.name) |
140 ###change | 154 ###change |
141 def getFaces(): | 155 def getFaces(): |
142 ##change | 156 ##change |
143 #str = "" | 157 #str = "" |
144 file.write("") | 158 file.write("") |
145 matrix = obj.getMatrix() | 159 # matrix = obj.matrix |
160 # already calcurated? | |
161 matrix = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]] | |
146 | 162 |
147 for mindex in range(len(flist)): | 163 for mindex in range(len(flist)): |
148 fl = flist[mindex] | 164 fl = flist[mindex] |
149 if fl != []: | 165 if fl != []: |
150 parent_name = obj.getParent() | 166 parent_name = obj.parent |
151 if parent_name: | 167 if parent_name: |
152 parent_name = "{0:s}".format(parent_name) | 168 parent_name = "{0:s}".format(parent_name) |
153 ###change | 169 ###change |
154 #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]) | 170 #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]) |
155 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]) )) | 171 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]) )) |
202 | 218 |
203 | 219 |
204 ### get texture_image and change base64 data | 220 ### get texture_image and change base64 data |
205 texture = mesh.faces[0].image | 221 texture = mesh.faces[0].image |
206 if texture: | 222 if texture: |
207 file.write(loadTexture(texture)) | 223 file.write(loadTexture(texture.name)) |
208 | |
209 else: | 224 else: |
210 file.write("\t\t<image name=\"{0:s}\">\n".format(("sample_white.png") )) | 225 file.write("\t\t<image name=\"{0:s}\">\n".format(("sample_white.png") )) |
211 | |
212 file.write("\t\t\tiVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAAEElEQVQImWP8zwABTAwUMQBJQQEP\n"); | |
213 file.write("\t\t\tlYH+agAAAABJRU5ErkJggg==\n"); | |
214 | |
215 file.write("\t\t</image>\n") | 226 file.write("\t\t</image>\n") |
216 | 227 |
217 #return str | 228 #return str |
218 | 229 |
219 vdata = [] | 230 vdata = [] |
240 #str += getFaces() | 251 #str += getFaces() |
241 getFaces(); | 252 getFaces(); |
242 | 253 |
243 #return str | 254 #return str |
244 | 255 |
256 def make_material_chunk(material, image): | |
257 if image: | |
258 file.write(loadTexture(image)) | |
259 else: | |
260 file.write("\t\t<image name=\"{0:s}\">\n".format(("sample_white.png") )) | |
261 global sample_whited | |
262 if (sample_whited == 0): | |
263 | |
264 file.write("\t\t\tiVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAAAAADhZOFXAAAAEElEQVQImWP8zwABTAwUMQBJQQEP\n"); | |
265 file.write("\t\t\tlYH+agAAAABJRU5ErkJggg==\n"); | |
266 sample_whited=1 | |
267 | |
268 file.write("\t\t</image>\n") | |
245 | 269 |
246 ###################################################### | 270 ###################################################### |
247 # EXPORT | 271 # EXPORT |
248 ###################################################### | 272 ###################################################### |
249 def save_xml(filename, unindexedname, anim): | 273 |
250 print("XML EXPORT\n") | 274 |
251 time1 = Blender.sys.time() | 275 def save_xml(filename, context): |
276 '''Save the Blender scene to a Cerium xml file.''' | |
277 # Time the export | |
278 global MatSaved | |
279 global anim | |
280 MatSaved = 0 | |
281 | |
282 if not filename.lower().endswith('.xml'): | |
283 filename += '.xml' | |
252 print("Saving to '" + filename + "'...\n") | 284 print("Saving to '" + filename + "'...\n") |
253 file = open(filename, 'w') | 285 file = open(filename, 'w') |
254 | 286 |
255 count_h = 0 | 287 # XXX |
256 n = 0 | 288 # if not BPyMessages.Warning_SaveOver(filename): |
257 filename_h = filename[:-4] + ".h" #header file for cpp | 289 # return |
258 file_h = open(filename_h, 'w') | 290 |
291 # XXX | |
292 time1 = time.clock() | |
293 # time1= Blender.sys.time() | |
294 # Blender.Window.WaitCursor(1) | |
259 | 295 |
260 ##### XML header ###### | 296 ##### XML header ###### |
261 file.write("<?xml version=\"1.0\"?>\n") | 297 file.write("<?xml version=\"1.0\"?>\n") |
262 | |
263 #get all the objects in this scene | |
264 activelayers = Window.ViewLayer() | |
265 for i in range(len(activelayers)): | |
266 activelayers[i] = 2**(activelayers[i]-1) | |
267 object_list1 = Blender.Scene.GetCurrent().getChildren() | |
268 object_list = [] | |
269 matnames= [] | |
270 for obj in object_list1: | |
271 if obj.Layer in activelayers: | |
272 object_list.append(obj) | |
273 | |
274 if obj.getType() == "Mesh": | |
275 materials_obj_list = [] | |
276 materials_obj_list = obj.getData().materials | |
277 for mat in materials_obj_list: | |
278 if mat.name not in matnames: | |
279 matnames.append(mat.name) | |
280 | |
281 ##### Process Meshes ###### | |
282 meshlist = [] | |
283 file.write("<OBJECT-3D>\n") | 298 file.write("<OBJECT-3D>\n") |
284 for obj in object_list: | 299 |
285 if obj.getType() == "Mesh": | 300 sce = context.scene |
286 objectname = obj.getName() | 301 |
287 mesh = Blender.NMesh.GetRawFromObject(objectname) | 302 # Get all the supported objects selected in this scene: |
288 meshname = mesh.name | 303 # ob_sel= list(sce.objects.context) |
289 meshlight = 0 | 304 # mesh_objects = [ (ob, me) for ob in ob_sel for me in (BPyMesh.getMeshFromObject(ob, None, True, False, sce),) if me ] |
290 if len(mesh.materials) > 0: | 305 # empty_objects = [ ob for ob in ob_sel if ob.type == 'Empty' ] |
291 mat0 = mesh.materials[0] | 306 |
292 if mat0.emit > 0: | 307 # Make a list of all materials used in the selected meshes (use a dictionary, |
293 meshlight = 1 | 308 # each material is added once): |
294 if meshlight: | 309 materialDict = {} |
295 print("processing Object \"{0:s}\" as Meshlight (Mesh \"{1:s}\")...".format((objectname, meshname))) | 310 mesh_objects = [] |
296 else: | 311 for ob in [ob for ob in context.scene.objects if ob.is_visible()]: |
297 print("processing Object \"{0:s}\" (Mesh \"{1:s}\")...".format((objectname, meshname))) | 312 # for ob in sce.objects.context: |
298 try: | 313 |
299 meshlist.index(meshname) | 314 # get derived objects |
300 except ValueError: | 315 free, derived = create_derived_objects(ob) |
301 ###change | 316 |
302 #file.write(exportMesh(mesh,obj)) | 317 if derived == None: continue |
303 exportMesh(mesh,obj,file) | 318 |
304 meshlist.append(meshname) | 319 for ob_derived, mat in derived: |
305 if anim == 1: | 320 # for ob_derived, mat in getDerivedObjects(ob, False): |
306 #file.write("\t\t<anim>\n") | 321 |
307 ###change | 322 if ob.type not in ('MESH', 'CURVE', 'SURFACE', 'TEXT', 'META'): |
308 #file.write(export_anime(obj)) | 323 continue |
309 export_anime(obj,file) | 324 |
310 #file.write("\t\t</anim>\n") | 325 data = ob_derived.create_mesh(True, 'PREVIEW') |
311 file.write("\t</surface>\n") | 326 # data = getMeshFromObject(ob_derived, None, True, False, sce) |
312 file_h.write("#define {0:s} scene_graph".format((obj.name))) | 327 if data: |
313 while n != count_h: | 328 data.transform(mat) |
314 file_h.write("->next") | 329 # data.transform(mat, recalc_normals=False) |
315 n = n + 1 | 330 mesh_objects.append((ob_derived, data)) |
316 file_h.write("\n") | 331 mat_ls = data.materials |
317 count_h = count_h + 1 | 332 mat_ls_len = len(mat_ls) |
318 n = 0 | 333 |
319 | 334 # get material/image tuples. |
320 | 335 if len(data.uv_textures): |
321 ##### XML FOOTER ###### | 336 # if data.faceUV: |
322 file.write("</OBJECT-3D>") | 337 if not mat_ls: |
338 mat = mat_name = None | |
339 | |
340 for f, uf in zip(data.faces, data.active_uv_texture.data): | |
341 if mat_ls: | |
342 mat_index = f.material_index | |
343 # mat_index = f.mat | |
344 if mat_index >= mat_ls_len: | |
345 mat_index = f.mat = 0 | |
346 mat = mat_ls[mat_index] | |
347 if mat: mat_name = mat.name | |
348 else: mat_name = None | |
349 # else there alredy set to none | |
350 | |
351 img = uf.image | |
352 # img = f.image | |
353 if img: img_name = img.name | |
354 else: img_name = None | |
355 | |
356 materialDict.setdefault((mat_name, img_name), (mat, img) ) | |
357 | |
358 | |
359 else: | |
360 for mat in mat_ls: | |
361 if mat: # material may be None so check its not. | |
362 materialDict.setdefault((mat.name, None), (mat, None) ) | |
363 | |
364 # Why 0 Why! | |
365 for f in data.faces: | |
366 if f.material_index >= mat_ls_len: | |
367 # if f.mat >= mat_ls_len: | |
368 f.material_index = 0 | |
369 # f.mat = 0 | |
370 | |
371 if free: | |
372 free_derived_objects(ob) | |
373 | |
374 | |
375 # Make material chunks for all materials used in the meshes: | |
376 for mat_and_image in materialDict.values(): | |
377 print("make material chunk {0:s}\n".format(mat_and_image[1])) | |
378 make_material_chunk(mat_and_image[0], mat_and_image[1]) | |
379 | |
380 # Give all objects a unique ID and build a dictionary from object name to object id: | |
381 """ | |
382 name_to_id = {} | |
383 for ob, data in mesh_objects: | |
384 name_to_id[ob.name]= len(name_to_id) | |
385 #for ob in empty_objects: | |
386 # name_to_id[ob.name]= len(name_to_id) | |
387 """ | |
388 | |
389 # Create object chunks for all meshes: | |
390 for ob, blender_mesh in mesh_objects: | |
391 print("export mesh {0:s}\n".format(ob.name)) | |
392 exportMesh(blender_mesh,ob,file) | |
393 if (anim): | |
394 export_anime(obj,file) | |
395 file.write("\t</surface>\n") | |
396 # if not blender_mesh.users: | |
397 bpy.data.remove_mesh(blender_mesh) | |
398 # blender_mesh.verts = None | |
399 | |
400 # Close the file: | |
323 file.close() | 401 file.close() |
324 file_h.close() | 402 |
325 print("Finished.\n") | 403 |
326 | |
327 time2 = Blender.sys.time() | |
328 print("Processing time: {0:f}\n".format((time2-time1))) | |
329 Draw.Exit() | |
330 | |
331 | |
332 ### SAVE ANIMATION ### | |
333 def save_anim(filename): | |
334 global MatSaved | |
335 | |
336 MatSaved = 0 | |
337 unindexedname = filename | |
338 save_xml(filename, unindexedname, 1) | |
339 | |
340 | |
341 #### SAVE STILL (hackish...) #### | |
342 def save_still(filename): | |
343 global MatSaved | |
344 | |
345 MatSaved = 0 | |
346 unindexedname = filename | |
347 save_xml(filename, unindexedname, 0) | |
348 | |
349 ###################################################### | |
350 # Settings GUI | |
351 ###################################################### | |
352 | |
353 # Assign event numbers to buttons | |
354 evtNoEvt = 0 | |
355 evtExport = 1 | |
356 evtExportAnim = 2 | |
357 | |
358 # Set initial values of buttons | |
359 | |
360 ## <size>800 600</size> | |
361 | |
362 sceneSizeX = Scene.GetCurrent().getRenderingContext().imageSizeX() | |
363 sceneSizeY = Scene.GetCurrent().getRenderingContext().imageSizeY() | |
364 | |
365 SizeX = Draw.Create(sceneSizeX) | |
366 SizeY = Draw.Create(sceneSizeY) | |
367 TexExponent = Draw.Create(2.3) | |
368 | |
369 ## <metropolis>1</metropolis> | |
370 MLT = Draw.Create(1) | |
371 | |
372 ## <large_mutation_prob>0.1</large_mutation_prob> | |
373 LMP = Draw.Create(0.1) | |
374 | |
375 ## <max_change>0.02</max_change> | |
376 MaxChange = Draw.Create(0.02) | |
377 | |
378 ## <russian_roulette_live_prob>0.7</russian_roulette_live_prob> | |
379 RRLP = Draw.Create(0.7) | |
380 | |
381 ## <max_depth>100</max_depth> | |
382 MaxDepth = Draw.Create(100) | |
383 | |
384 ## <bidirectional>false</bidirectional> | |
385 Bidirectional = Draw.Create(0) | |
386 | |
387 ## <strata_width>14</strata_width> | |
388 StrataWidth = Draw.Create(14) | |
389 | |
390 ## <logging>0</logging> | |
391 Logging = Draw.Create(0) | |
392 | |
393 ## <save_untonemapped_exr>false</save_untonemapped_exr> | |
394 SaveUTMExr = Draw.Create(0) | |
395 | |
396 ## <save_tonemapped_exr>false</save_tonemapped_exr> | |
397 SaveTMExr = Draw.Create(0) | |
398 | |
399 ## <lens_radius>0.0</lens_radius> | |
400 LensRadius = Draw.Create(0.0) | |
401 | |
402 ## <focus_distance>2.0</focus_distance> | |
403 FocusDistance = Draw.Create(2.0) | |
404 | |
405 ## <turbidity>2.0</turbidity> | |
406 Turbidity = Draw.Create(2.0) | |
407 | |
408 GroundPlane = Draw.Create(1) | |
409 | |
410 ## Separate materials | |
411 MatFile = Draw.Create(1) | |
412 | |
413 # text color fix | |
414 textcol = [0, 0, 0] | |
415 | |
416 | |
417 def gui(): | |
418 global evtNoEvt, evtExport, evtExportAnim | |
419 global SizeX, SizeY, TexExponent, MLT, LMP, MaxChange, RRLP, MaxDepth, Bidirectional, StrataWidth, Logging, SaveUTMExr, SaveTMExr, LensRadius, FocusDistance,Turbidity, GroundPlane, MatFile | |
420 global textcol | |
421 | |
422 Draw.Button("Export", evtExport, 10, 25, 100, 18, "Open file dialog and export") | |
423 Draw.Button("Export Animation", evtExportAnim, 130, 25, 150, 18, "Open filedialog and export animation (careful: takes a lot of diskspace!!!)") | |
424 BGL.glColor3f(textcol[0], textcol[1], textcol[2]) ; BGL.glRasterPos2i(10,10) ; Draw.Text("Press Q or ESC to quit.", "tiny") | |
425 | |
426 BGL.glRasterPos2i(10,60) ; Draw.Text("xml exporter for libps3") | |
427 | |
428 | |
429 def event(evt, val): # function that handles keyboard and mouse events | |
430 if evt == Draw.ESCKEY or evt == Draw.QKEY: | |
431 stop = Draw.PupMenu("OK?%t|Cancel export %x1") | |
432 if stop == 1: | |
433 Draw.Exit() | |
434 return | |
435 | |
436 def buttonEvt(evt): # function that handles button events | |
437 if evt == evtExport: | |
438 Blender.Window.FileSelector(save_still, "Export", newFName('xml')) | |
439 if evt == evtExportAnim: | |
440 Blender.Window.FileSelector(save_anim, "Export Animation", newFName('xml')) | |
441 #if there was an event, redraw the window | |
442 if evt: | |
443 Draw.Redraw() | |
444 | 404 |
445 | 405 |
446 def loadTexture(texture): | 406 def loadTexture(texture): |
447 global images, imageCount | 407 global images, imageCount |
448 name = texture.getName() | 408 name = texture.name |
449 if name in images: | 409 if name in images: |
450 return "\t\t<image name=\"" + name + "\"/>\n" | 410 return "\t\t<image name=\"" + name + "\"/>\n" |
451 out = "\t\t<image name=\"" + name + "\">\n" | 411 out = "\t\t<image name=\"" + name + "\">\n" |
452 imageCount += 1 | 412 imageCount += 1 |
453 images[name] = imageCount | 413 images[name] = imageCount |
463 input.close() | 423 input.close() |
464 os.remove('output.txt') | 424 os.remove('output.txt') |
465 out += "\t\t</image>\n" | 425 out += "\t\t</image>\n" |
466 return out | 426 return out |
467 | 427 |
468 Draw.Register(gui, event, buttonEvt) | 428 |
469 | 429 from bpy.props import * |
470 | 430 class ExportPS3(bpy.types.Operator): |
431 '''Export to Cerium XML file format.''' | |
432 bl_idname = "export.ps3cerium" | |
433 bl_label = 'Export PS3 Cerium' | |
434 | |
435 # List of operator properties, the attributes will be assigned | |
436 # to the class instance from the operator settings before calling. | |
437 | |
438 | |
439 path = StringProperty(name="File Path", description="File path used for exporting the Cerium XML file", maxlen= 1024, default= "") | |
440 | |
441 | |
442 def execute(self, context): | |
443 save_xml(self.properties.path, context) | |
444 return ('FINISHED',) | |
445 | |
446 def invoke(self, context, event): | |
447 wm = context.manager | |
448 wm.add_fileselect(self) | |
449 return ('RUNNING_MODAL',) | |
450 | |
451 def poll(self, context): # Poll isnt working yet | |
452 return context.active_object != None | |
453 | |
454 bpy.ops.add(ExportPS3) | |
455 | |
456 # Add to a menu | |
457 import dynamic_menu | |
458 | |
459 def menu_func(self, context): | |
460 default_path = bpy.data.filename.replace(".blend", ".xml") | |
461 self.layout.operator(ExportPS3.bl_idname, text="PS3 Cerium...").path = default_path | |
462 | |
463 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func) | |
464 | |
465 # end |