2.5: Top Menu
[blender.git] / release / scripts / lightwave_import.py
1 #!BPY
2 """
3 Name: 'LightWave (.lwo)...'
4 Blender: 239
5 Group: 'Import'
6 Tooltip: 'Import LightWave Object File Format'
7 """
8
9 __author__ = ["Alessandro Pirovano, Anthony D'Agostino (Scorpius)", "Campbell Barton (ideasman42)", "ZanQdo"]
10 __url__ = ("www.blender.org", "blenderartist.org",
11 "Anthony's homepage, http://www.redrival.com/scorpius", "Alessandro's homepage, http://uaraus.altervista.org")
12
13 importername = "lwo_import 0.4.0"
14
15 # +---------------------------------------------------------+
16 # | Save your work before and after use.                    |
17 # | Please report any useful comment to:                    |
18 # | uaraus-dem@yahoo.it                                     |
19 # | Thanks                                                  |
20 # +---------------------------------------------------------+
21 # +---------------------------------------------------------+
22 # | Copyright (c) 2002 Anthony D'Agostino                   |
23 # | http://www.redrival.com/scorpius                        |
24 # | scorpius@netzero.com                                    |
25 # | April 21, 2002                                          |
26 # | Import Export Suite v0.5                                |
27 # +---------------------------------------------------------+
28 # | Read and write LightWave Object File Format (*.lwo)     |
29 # +---------------------------------------------------------+
30 # +---------------------------------------------------------+
31 # | Alessandro Pirovano tweaked starting on March 2005      |
32 # | http://uaraus.altervista.org                            |
33 # +---------------------------------------------------------+
34 # +----------------------------------------------------------
35 # | GPL license block
36 # |
37 # | This program is free software; you can redistribute it and/or modify
38 # | it under the terms of the GNU General Public License as published by
39 # | the Free Software Foundation; either version 2 of the License, or
40 # | (at your option) any later version.
41 # |
42 # | This program is distributed in the hope that it will be useful,
43 # | but WITHOUT ANY WARRANTY; without even the implied warranty of
44 # | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45 # | GNU General Public License for more details.
46 # |
47 # | You should have received a copy of the GNU General Public License
48 # | along with this program; if not, write to the Free Software
49 # | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
50 # +----------------------------------------------------------
51 # +---------------------------------------------------------+
52 # | Release log:                                            |
53 # | 0.4.0 : Updated for blender 2.44                        |
54 # |         ZanQdo - made the mesh import the right way up  |
55 # |         Ideasman42 - Updated functions for the bew API  |
56 # |           as well as removing the text object class     |
57 # | 0.2.2 : This code works with Blender 2.42 RC3           |
58 # |         Added a new PolyFill function for BPYMesh's     |
59 # |           ngon() to use, checked compatibility          |
60 # |           lightwaves ngons are imported as fgons        |
61 # |         Checked compatibility against 1711 lwo files    |
62 # | 0.2.1 : This code works with Blender 2.40 RC1           |
63 # |         modified material mode assignment to deal with  |
64 # |         Python API modification                         |
65 # |         Changed script license to GNU GPL               |
66 # | 0.2.0:  This code works with Blender 2.40a2 or up       |
67 # |         Major rewrite to deal with large meshes         |
68 # |         - 2 pass file parsing                           |
69 # |         - lower memory foot###if DEBUG: print                        |
70 # |           (as long as python gc allows)                 |
71 # |         2.40a2 - Removed subsurf settings patches=poly  |
72 # |         2.40a2 - Edge generation instead of 2vert faces |
73 # | 0.1.16: fixed (try 2) texture offset calculations       |
74 # |         added hint on axis mapping                      |
75 # |         added hint on texture blending mode             |
76 # |         added hint on texture transparency setting      |
77 # |         search images in original directory first       |
78 # |         fixed texture order application                 |
79 # | 0.1.15: added release log                               |
80 # |         fixed texture offset calculations (non-UV)      |
81 # |         fixed reverting vertex order in face generation |
82 # |         associate texture on game-engine settings       |
83 # |         vector math definitely based on mathutils       |
84 # |         search images in "Images" and "../Images" dir   |
85 # |         revised logging facility                        |
86 # |         fixed subsurf texture and material mappings     |
87 # | 0.1.14: patched missing mod_vector (not definitive)     |
88 # | 0.1.13: first public release                            |
89 # +---------------------------------------------------------+
90
91 #blender related import
92 import Blender
93 import bpy
94
95 # use for comprehensiveImageLoad
96 import BPyImage
97
98 # Use this ngon function
99 import BPyMesh
100
101 import BPyMessages
102
103 #python specific modules import
104 try:
105         import struct, chunk, cStringIO
106 except:
107         struct= chunk= cStringIO= None
108
109 # python 2.3 has no reversed() iterator. this will only work on lists and tuples
110 try:
111         reversed
112 except:
113         def reversed(l): return l[::-1]
114
115 ### # Debuggin disabled in release.
116 ### # do a search replace to enabe debug prints
117 ### DEBUG = False
118
119 # ===========================================================
120 # === Utility Preamble ======================================
121 # ===========================================================
122
123 textname = None
124 #uncomment the following line to enable logging facility to the named text object
125 #textname = "lwo_log"
126
127 TXMTX = Blender.Mathutils.Matrix(\
128 [1, 0, 0, 0],\
129 [0, 0, 1, 0],\
130 [0, 1, 0, 0],\
131 [0, 0, 0, 1])
132
133 # ===========================================================
134 # === Make sure it is a string ... deal with strange chars ==
135 # ===========================================================
136 def safestring(st):
137         myst = ""
138         for ll in xrange(len(st)):
139                 if st[ll] < " ":
140                         myst += "#"
141                 else:
142                         myst += st[ll]
143         return myst
144
145 # ===========================================================
146 # === Main read functions ===================================
147 # ===========================================================
148
149 # =============================
150 # === Read LightWave Format ===
151 # =============================
152 def read(filename):
153         if BPyMessages.Error_NoFile(filename):
154                 return
155
156         print "This is: %s" % importername
157         print "Importing file:", filename
158         bpy.data.scenes.active.objects.selected = []
159         
160         start = Blender.sys.time()
161         file = open(filename, "rb")
162         
163         editmode = Blender.Window.EditMode()    # are we in edit mode?  If so ...
164         if editmode: Blender.Window.EditMode(0) # leave edit mode before getting the mesh    # === LWO header ===
165         
166         try:
167                 form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
168         except:
169                 Blender.Draw.PupMenu('Error%t|This is not a lightwave file')
170                 return
171         
172         if (form_type == "LWOB"):
173                 read_lwob(file, filename)
174         elif (form_type == "LWO2"):
175                 read_lwo2(file, filename)
176         else:
177                 print "Can't read a file with the form_type: %s" % form_type
178                 return
179
180         Blender.Window.DrawProgressBar(1.0, "")    # clear progressbar
181         file.close()
182         end = Blender.sys.time()
183         seconds = " in %.2f %s" % (end-start, "seconds")
184         if form_type == "LWO2": fmt = " (v6.0 Format)"
185         if form_type == "LWOB": fmt = " (v5.5 Format)"
186         print "Successfully imported " + filename.split('\\')[-1].split('/')[-1] + fmt + seconds
187         
188         if editmode: Blender.Window.EditMode(1)  # optional, just being nice
189         Blender.Redraw()
190
191 # enddef read
192
193
194 # =================================
195 # === Read LightWave 5.5 format ===
196 # =================================
197 def read_lwob(file, filename):
198         #This function is directly derived from the LWO2 import routine
199         #dropping all the material analysis parts
200
201         ###if DEBUG: print "LightWave 5.5 format"
202
203         dir_part = Blender.sys.dirname(filename)
204         fname_part = Blender.sys.basename(filename)
205         #ask_weird = 1
206
207         #first initialization of data structures
208         defaultname = Blender.sys.splitext(fname_part)[0]
209         tag_list = []              #tag list: global for the whole file?
210         surf_list = []             #surf list: global for the whole file?
211         clip_list = []             #clip list: global for the whole file?
212         object_index = 0
213         object_list = None
214         objspec_list = None
215
216         #add default material for orphaned faces, if any
217         surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")})
218
219         #pass 2: effectively generate objects
220         ###if DEBUG: print "Pass 1: dry import"
221         file.seek(0)
222         objspec_list = ["imported", {}, [], [], {}, {}, 0, {}, {}]
223         # === LWO header ===
224         form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
225         if (form_type != "LWOB"):
226                 ###if DEBUG: print "??? Inconsistent file type: %s" % form_type
227                 return
228         while 1:
229                 try:
230                         lwochunk = chunk.Chunk(file)
231                 except EOFError:
232                         break
233                 ###if DEBUG: print ' ',
234                 if lwochunk.chunkname == "LAYR":
235                         ###if DEBUG: print "---- LAYR",
236                         objname = read_layr(lwochunk)
237                         ###if DEBUG: print objname
238                         if objspec_list != None: #create the object
239                                 create_objects(clip_list, objspec_list, surf_list)
240                                 update_material(clip_list, objspec_list, surf_list) #give it all the object
241                         objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
242                         object_index += 1
243                 elif lwochunk.chunkname == "PNTS":                         # Verts
244                         ###if DEBUG: print "---- PNTS",
245                         verts = read_verts(lwochunk)
246                         objspec_list[2] = verts
247                 elif lwochunk.chunkname == "POLS": # Faces v5.5
248                         ###if DEBUG: print "-------- POLS(5.5)"
249                         faces = read_faces_5(lwochunk)
250                         flag = 0
251                         #flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
252                         if flag<2:
253                                 if objspec_list[3] != []:
254                                         #create immediately the object
255                                         create_objects(clip_list, objspec_list, surf_list)
256                                         update_material(clip_list, objspec_list, surf_list) #give it all the object
257                                         #update with new data
258                                         objspec_list = [objspec_list[0],                  #update name
259                                                                         {},                               #init
260                                                                         objspec_list[2],                  #same vertexes
261                                                                         faces,                            #give it the new faces
262                                                                         {},                               #no need to copy - filled at runtime
263                                                                         {},                               #polygon tagging will follow
264                                                                         flag,                             #patch flag
265                                                                         objspec_list[7],                  #same uvcoords
266                                                                         {}]                               #no vmad mapping
267                                         object_index += 1
268                                 #end if already has a face list
269                                 objspec_list[3] = faces
270                                 objname = objspec_list[0]
271                                 if objname == None:
272                                         objname = defaultname
273                         #end if processing a valid poly type
274                 else:                                                       # Misc Chunks
275                         ###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname
276                         lwochunk.skip()
277                 #uncomment here to log data structure as it is built
278                 # ###if DEBUG: print object_list
279         #last object read
280         create_objects(clip_list, objspec_list, surf_list)
281         update_material(clip_list, objspec_list, surf_list) #give it all the object
282         objspec_list = None
283         surf_list = None
284         clip_list = None
285
286
287         ###if DEBUG: print "\nFound %d objects:" % object_index
288
289 # enddef read_lwob
290
291
292 # =============================
293 # === Read LightWave Format ===
294 # =============================
295 def read_lwo2(file, filename, typ="LWO2"):
296
297         ###if DEBUG: print "LightWave 6 (and above) format"
298
299         dir_part = Blender.sys.dirname(filename)
300         fname_part = Blender.sys.basename(filename)
301         ask_weird = 1
302
303         #first initialization of data structures
304         defaultname = Blender.sys.splitext(fname_part)[0]
305         tag_list = []              #tag list: global for the whole file?
306         surf_list = []             #surf list: global for the whole file?
307         clip_list = []             #clip list: global for the whole file?
308         object_index = 0
309         object_list = None
310         objspec_list = None
311         # init value is: object_list = [[None, {}, [], [], {}, {}, 0, {}, {}]]
312         #0 - objname                    #original name
313         #1 - obj_dict = {TAG}           #objects created
314         #2 - verts = []                 #object vertexes
315         #3 - faces = []                 #object faces (associations poly -> vertexes)
316         #4 - obj_dim_dict = {TAG}       #tuples size and pos in local object coords - used for NON-UV mappings
317         #5 - polytag_dict = {TAG}       #tag to polygons mapping
318         #6 - patch_flag                 #0 = surf; 1 = patch (subdivision surface) - it was the image list
319         #7 - uvcoords_dict = {name}     #uvmap coordinates (mixed mode per vertex/per face)
320         #8 - facesuv_dict = {name}      #vmad only coordinates associations poly & vertex -> uv tuples
321
322         #pass 1: look in advance for materials
323         ###if DEBUG: print "Starting Pass 1: hold on tight"
324         while 1:
325                 try:
326                         lwochunk = chunk.Chunk(file)
327                 except EOFError:
328                         break
329                 ###if DEBUG: print ' ',
330                 if lwochunk.chunkname == "TAGS":                         # Tags
331                         ###if DEBUG: print "---- TAGS"
332                         tag_list.extend(read_tags(lwochunk))
333                 elif lwochunk.chunkname == "SURF":                         # surfaces
334                         ###if DEBUG: print "---- SURF"
335                         surf_list.append(read_surfs(lwochunk, surf_list, tag_list))
336                 elif lwochunk.chunkname == "CLIP":                         # texture images
337                         ###if DEBUG: print "---- CLIP"
338                         clip_list.append(read_clip(lwochunk, dir_part))
339                         ###if DEBUG: print "read total %s clips up to now" % len(clip_list)
340                 else:                                                       # Misc Chunks
341                         if ask_weird:
342                                 ckname = safestring(lwochunk.chunkname)
343                                 if "#" in ckname:
344                                         choice = Blender.Draw.PupMenu("WARNING: file could be corrupted.%t|Import anyway|Give up")
345                                         if choice != 1:
346                                                 ###if DEBUG: print "---- %s: Maybe file corrupted. Terminated by user" % lwochunk.chunkname
347                                                 return
348                                         ask_weird = 0
349                         ###if DEBUG: print "---- %s: skipping (maybe later)" % lwochunk.chunkname
350                         lwochunk.skip()
351
352         #add default material for orphaned faces, if any
353         surf_list.append({'NAME': "_Orphans", 'g_MAT': bpy.data.materials.new("_Orphans")})
354
355         #pass 2: effectively generate objects
356         ###if DEBUG: print "Pass 2: now for the hard part"
357         file.seek(0)
358         # === LWO header ===
359         form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
360         if (form_type != "LWO2"):
361                 ###if DEBUG: print "??? Inconsistent file type: %s" % form_type
362                 return
363         while 1:
364                 try:
365                         lwochunk = chunk.Chunk(file)
366                 except EOFError:
367                         break
368                 ###if DEBUG: print ' ',
369                 if lwochunk.chunkname == "LAYR":
370                         ###if DEBUG: print "---- LAYR"
371                         objname = read_layr(lwochunk)
372                         ###if DEBUG: print objname
373                         if objspec_list != None: #create the object
374                                 create_objects(clip_list, objspec_list, surf_list)
375                                 update_material(clip_list, objspec_list, surf_list) #give it all the object
376                         objspec_list = [objname, {}, [], [], {}, {}, 0, {}, {}]
377                         object_index += 1
378                 elif lwochunk.chunkname == "PNTS":                         # Verts
379                         ###if DEBUG: print "---- PNTS"
380                         verts = read_verts(lwochunk)
381                         objspec_list[2] = verts
382                 elif lwochunk.chunkname == "VMAP":                         # MAPS (UV)
383                         ###if DEBUG: print "---- VMAP"
384                         #objspec_list[7] = read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
385                         read_vmap(objspec_list[7], len(objspec_list[2]), lwochunk)
386                 elif lwochunk.chunkname == "VMAD":                         # MAPS (UV) per-face
387                         ###if DEBUG: print "---- VMAD"
388                         #objspec_list[7], objspec_list[8] = read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
389                         read_vmad(objspec_list[7], objspec_list[8], len(objspec_list[3]), len(objspec_list[2]), lwochunk)
390                 elif lwochunk.chunkname == "POLS": # Faces v6.0
391                         ###if DEBUG: print "-------- POLS(6)"
392                         faces, flag = read_faces_6(lwochunk)
393                         #flag is 0 for regular polygon, 1 for patches (= subsurf), 2 for anything else to be ignored
394                         if flag<2:
395                                 if objspec_list[3] != []:
396                                         #create immediately the object
397                                         create_objects(clip_list, objspec_list, surf_list)
398                                         update_material(clip_list, objspec_list, surf_list) #give it all the object
399                                         #update with new data
400                                         objspec_list = [objspec_list[0],                  #update name
401                                                                         {},                               #init
402                                                                         objspec_list[2],                  #same vertexes
403                                                                         faces,                            #give it the new faces
404                                                                         {},                               #no need to copy - filled at runtime
405                                                                         {},                               #polygon tagging will follow
406                                                                         flag,                             #patch flag
407                                                                         objspec_list[7],                  #same uvcoords
408                                                                         {}]                               #no vmad mapping
409                                         object_index += 1
410                                 #end if already has a face list
411                                 objspec_list[3] = faces
412                                 objname = objspec_list[0]
413                                 if objname == None:
414                                         objname = defaultname
415                         #end if processing a valid poly type
416                 elif lwochunk.chunkname == "PTAG":                         # PTags
417                         ###if DEBUG: print "---- PTAG"
418                         polytag_dict = read_ptags(lwochunk, tag_list)
419                         for kk, polytag_dict_val in polytag_dict.iteritems(): objspec_list[5][kk] = polytag_dict_val
420                 else:                                                       # Misc Chunks
421                         ###if DEBUG: print "---- %s: skipping (definitely!)" % lwochunk.chunkname
422                         lwochunk.skip()
423                 #uncomment here to log data structure as it is built
424                 
425         #last object read
426         create_objects(clip_list, objspec_list, surf_list)
427         update_material(clip_list, objspec_list, surf_list) #give it all the object
428         objspec_list = None
429         surf_list = None
430         clip_list = None
431
432         ###if DEBUG: print "\nFound %d objects:" % object_index
433 # enddef read_lwo2
434
435
436
437
438
439
440 # ===========================================================
441 # === File reading routines =================================
442 # ===========================================================
443 # ==================
444 # === Read Verts ===
445 # ==================
446 def read_verts(lwochunk):
447         #data = cStringIO.StringIO(lwochunk.read())
448         numverts = lwochunk.chunksize/12
449         return [struct.unpack(">fff", lwochunk.read(12)) for i in xrange(numverts)]
450 # enddef read_verts
451
452
453 # =================
454 # === Read Name ===
455 # =================
456 # modified to deal with odd lenght strings
457 def read_name(file):
458         name = ""
459         while 1:
460                 char = file.read(1)
461                 if char == "\0": break
462                 else: name += char
463         len_name = len(name) + 1 #count the trailing zero
464         if len_name%2==1:
465                 char = file.read(1) #remove zero padding to even lenght
466                 len_name += 1
467         return name, len_name
468
469
470 # ==================
471 # === Read Layer ===
472 # ==================
473 def read_layr(lwochunk):
474         data = cStringIO.StringIO(lwochunk.read())
475         idx, flags = struct.unpack(">hh", data.read(4))
476         pivot = struct.unpack(">fff", data.read(12))
477         layer_name, discard = read_name(data)
478         if not layer_name: layer_name = "NoName"
479         return layer_name
480 # enddef read_layr
481
482
483 # ======================
484 # === Read Faces 5.5 ===
485 # ======================
486 def read_faces_5(lwochunk):
487         data = cStringIO.StringIO(lwochunk.read())
488         faces = []
489         i = 0
490         while i < lwochunk.chunksize:
491                 #if not i%1000 and my_meshtools.show_progress:
492                 #   Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
493                 
494                 numfaceverts, = struct.unpack(">H", data.read(2))
495                 facev = [struct.unpack(">H", data.read(2))[0] for j in xrange(numfaceverts)]
496                 facev.reverse()
497                 faces.append(facev)
498                 surfaceindex, = struct.unpack(">H", data.read(2))
499                 if surfaceindex < 0:
500                         ###if DEBUG: print "***Error. Referencing uncorrect surface index"
501                         return
502                 i += (4+numfaceverts*2)
503         return faces
504
505
506 # ==================================
507 # === Read Variable-Length Index ===
508 # ==================================
509 def read_vx(data):
510         byte1, = struct.unpack(">B", data.read(1))
511         if byte1 != 0xFF:    # 2-byte index
512                 byte2, = struct.unpack(">B", data.read(1))
513                 index = byte1*256 + byte2
514                 index_size = 2
515         else:                # 4-byte index
516                 byte2, byte3, byte4 = struct.unpack(">3B", data.read(3))
517                 index = byte2*65536 + byte3*256 + byte4
518                 index_size = 4
519         return index, index_size
520
521
522 # ======================
523 # === Read uvmapping ===
524 # ======================
525 def read_vmap(uvcoords_dict, maxvertnum, lwochunk):
526         
527         if maxvertnum == 0:
528                 ###if DEBUG: print "Found VMAP but no vertexes to map!"
529                 return uvcoords_dict
530         data = cStringIO.StringIO(lwochunk.read())
531         map_type = data.read(4)
532         if map_type != "TXUV":
533                 ###if DEBUG: print "Reading VMAP: No Texture UV map Were Found. Map Type: %s" % map_type
534                 return uvcoords_dict
535         dimension, = struct.unpack(">H", data.read(2))
536         name, i = read_name(data) #i initialized with string lenght + zeros
537         ###if DEBUG: print "TXUV %d %s" % (dimension, name)
538         #note if there is already a VMAD it will be lost
539         #it is assumed that VMAD will follow the corresponding VMAP
540         Vector = Blender.Mathutils.Vector
541         try: #if uvcoords_dict.has_key(name):
542                 my_uv_dict = uvcoords_dict[name]          #update existing
543         except: #else:
544                 my_uv_dict = {}    #start a brand new: this could be made more smart
545         while (i < lwochunk.chunksize - 6):      #4+2 header bytes already read
546                 vertnum, vnum_size = read_vx(data)
547                 uv = struct.unpack(">ff", data.read(8))
548                 if vertnum >= maxvertnum:
549                         ###if DEBUG: print "Hem: more uvmap than vertexes? ignoring uv data for vertex %d" % vertnum
550                         pass
551                 else:
552                         my_uv_dict[vertnum] = Vector(uv)
553                 i += 8 + vnum_size
554         #end loop on uv pairs
555         uvcoords_dict[name] = my_uv_dict
556         #this is a per-vertex mapping AND the uv tuple is vertex-ordered, so faces_uv is the same as faces
557         #return uvcoords_dict
558         return
559
560 # ========================
561 # === Read uvmapping 2 ===
562 # ========================
563 def read_vmad(uvcoords_dict, facesuv_dict, maxfacenum, maxvertnum, lwochunk):
564         if maxvertnum == 0 or maxfacenum == 0:
565                 ###if DEBUG: print "Found VMAD but no vertexes to map!"
566                 return uvcoords_dict, facesuv_dict
567         data = cStringIO.StringIO(lwochunk.read())
568         map_type = data.read(4)
569         if map_type != "TXUV":
570                 ###if DEBUG: print "Reading VMAD: No Texture UV map Were Found. Map Type: %s" % map_type
571                 return uvcoords_dict, facesuv_dict
572         dimension, = struct.unpack(">H", data.read(2))
573         name, i = read_name(data) #i initialized with string lenght + zeros
574         ###if DEBUG: print "TXUV %d %s" % (dimension, name)
575         try: #if uvcoords_dict.has_key(name):
576                 my_uv_dict = uvcoords_dict[name]          #update existing
577         except: #else:
578                 my_uv_dict = {}    #start a brand new: this could be made more smart
579         my_facesuv_list = []
580         newindex = maxvertnum + 10 #why +10? Why not?
581         #end variable initialization
582         Vector = Blender.Mathutils.Vector
583         while (i < lwochunk.chunksize - 6):  #4+2 header bytes already read
584                 vertnum, vnum_size = read_vx(data)
585                 i += vnum_size
586                 polynum, vnum_size = read_vx(data)
587                 i += vnum_size
588                 uv = struct.unpack(">ff", data.read(8))
589                 if polynum >= maxfacenum or vertnum >= maxvertnum:
590                         ###if DEBUG: print "Hem: more uvmap than vertexes? ignorig uv data for vertex %d" % vertnum
591                         pass
592                 else:
593                         my_uv_dict[newindex] = Vector(uv)
594                         my_facesuv_list.append([polynum, vertnum, newindex])
595                         newindex += 1
596                 i += 8
597         #end loop on uv pairs
598         uvcoords_dict[name] = my_uv_dict
599         facesuv_dict[name] = my_facesuv_list
600         ###if DEBUG: print "updated %d vertexes data" % (newindex-maxvertnum-10)
601         return
602
603
604 # =================
605 # === Read tags ===
606 # =================
607 def read_tags(lwochunk):
608         data = cStringIO.StringIO(lwochunk.read())
609         tag_list = []
610         current_tag = ""
611         i = 0
612         while i < lwochunk.chunksize:
613                 char = data.read(1)
614                 if char == "\0":
615                         tag_list.append(current_tag)
616                         if (len(current_tag) % 2 == 0): char = data.read(1)
617                         current_tag = ""
618                 else:
619                         current_tag += char
620                 i += 1
621         ###if DEBUG: print "read %d tags, list follows: %s" % (len(tag_list), tag_list)
622         return tag_list
623
624
625 # ==================
626 # === Read Ptags ===
627 # ==================
628 def read_ptags(lwochunk, tag_list):
629         data = cStringIO.StringIO(lwochunk.read())
630         polygon_type = data.read(4)
631         if polygon_type != "SURF":
632                 ###if DEBUG: print "No Surf Were Found. Polygon Type: %s" % polygon_type
633                 return {}
634         ptag_dict = {}
635         i = 0
636         while(i < lwochunk.chunksize-4): #4 bytes polygon type already read
637                 #if not i%1000 and my_meshtools.show_progress:
638                 #   Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading PTAGS")
639                 poln, poln_size = read_vx(data)
640                 i += poln_size
641                 tag_index, = struct.unpack(">H", data.read(2))
642                 if tag_index > (len(tag_list)):
643                         ###if DEBUG: print "Reading PTAG: Surf belonging to undefined TAG: %d. Skipping" % tag_index
644                         return {}
645                 i += 2
646                 tag_key = tag_list[tag_index]
647                 try:
648                         ptag_dict[tag_list[tag_index]].append(poln)
649                 except: #if not(ptag_dict.has_key(tag_key)):
650                         ptag_dict[tag_list[tag_index]] = [poln]
651         
652         ###if DEBUG: for i, ptag_dict_val in ptag_dict.iteritems(): print "read %d polygons belonging to TAG %s" % (len(ptag_dict_val ), i)
653         return ptag_dict
654
655
656
657 # ==================
658 # === Read Clips ===
659 # ==================
660 def read_clip(lwochunk, dir_part):
661 # img, IMG, g_IMG refers to blender image objects
662 # ima, IMAG, g_IMAG refers to clip dictionary 'ID' entries: refer to blok and surf
663         clip_dict = {}
664         data = cStringIO.StringIO(lwochunk.read())
665         data_str = data.read(4)
666         if len(data_str) < 4: # can be zero also??? :/
667                 # Should not happen but lw can import so we should too
668                 return 
669         
670         image_index, = struct.unpack(">L", data_str)
671         clip_dict['ID'] = image_index
672         i = 4
673         while(i < lwochunk.chunksize):
674                 subchunkname, = struct.unpack("4s", data.read(4))
675                 subchunklen, = struct.unpack(">H", data.read(2))
676                 if subchunkname == "STIL":
677                         ###if DEBUG: print "-------- STIL"
678                         clip_name, k = read_name(data)
679                         #now split text independently from platform
680                         #depend on the system where image was saved. NOT the one where the script is run
681                         no_sep = "\\"
682                         if Blender.sys.sep == no_sep: no_sep ="/"
683                         if (no_sep in clip_name):
684                                 clip_name = clip_name.replace(no_sep, Blender.sys.sep)
685                         short_name = Blender.sys.basename(clip_name)
686                         if clip_name == "" or short_name == "":
687                                 ###if DEBUG: print "Reading CLIP: Empty clip name not allowed. Skipping"
688                                 discard = data.read(subchunklen-k)
689                         clip_dict['NAME'] = clip_name
690                         clip_dict['BASENAME'] = short_name
691                 elif subchunkname == "XREF":                           #cross reference another image
692                         ###if DEBUG: print "-------- XREF"
693                         image_index, = struct.unpack(">L", data.read(4))
694                         clip_name, k = read_name(data)
695                         clip_dict['NAME'] = clip_name
696                         clip_dict['XREF'] = image_index
697                 elif subchunkname == "NEGA":                           #negate texture effect
698                         ###if DEBUG: print "-------- NEGA"
699                         n, = struct.unpack(">H", data.read(2))
700                         clip_dict['NEGA'] = n
701                 else:                                                       # Misc Chunks
702                         ###if DEBUG: print "-------- CLIP:%s: skipping" % subchunkname
703                         discard = data.read(subchunklen)
704                 i = i + 6 + subchunklen
705         #end loop on surf chunks
706         ###if DEBUG: print "read image:%s" % clip_dict
707         if 'XREF' in clip_dict: # has_key
708                 ###if DEBUG: print "Cross-reference: no image pre-allocated."
709                 return clip_dict
710         #look for images
711         #img = load_image("",clip_dict['NAME'])
712         NAME= BASENAME= None 
713         
714         try:
715                 NAME= clip_dict['NAME']
716                 BASENAME= clip_dict['BASENAME']
717         except:
718                 clip_dict['g_IMG'] = None
719                 return
720         # ###if DEBUG: print 'test', NAME, BASENAME
721         img = BPyImage.comprehensiveImageLoad(NAME, dir_part, PLACE_HOLDER= False, RECURSIVE=False)
722         if not img:
723                 ###if DEBUG: print "***No image %s found: trying LWO file subdir" % NAME
724                 img = BPyImage.comprehensiveImageLoad(BASENAME, dir_part, PLACE_HOLDER= False, RECURSIVE=False)
725         
726         ###if DEBUG: if not img: print "***No image %s found: giving up" % BASENAME
727         #lucky we are: we have an image
728         ###if DEBUG: print "Image pre-allocated."
729         clip_dict['g_IMG'] = img
730         
731         return clip_dict
732
733
734 # ===========================
735 # === Read Surfaces Block ===
736 # ===========================
737 def read_surfblok(subchunkdata):
738         lenght = len(subchunkdata)
739         my_dict = {}
740         my_uvname = ""
741         data = cStringIO.StringIO(subchunkdata)
742         ##############################################################
743         # blok header sub-chunk
744         ##############################################################
745         subchunkname, = struct.unpack("4s", data.read(4))
746         subchunklen, = struct.unpack(">h", data.read(2))
747         accumulate_i = subchunklen + 6
748         if subchunkname != 'IMAP':
749                 ###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname
750                 return {}, ""
751         ###if DEBUG: print "---------- IMAP"
752         ordinal, i = read_name(data)
753         my_dict['ORD'] = ordinal
754         #my_dict['g_ORD'] = -1
755         my_dict['ENAB'] = True
756         while(i < subchunklen): # ---------left 6------------------------- loop on header parameters
757                 sub2chunkname, = struct.unpack("4s", data.read(4))
758                 sub2chunklen, = struct.unpack(">h", data.read(2))
759                 i = i + 6 + sub2chunklen
760                 if sub2chunkname == "CHAN":
761                         ###if DEBUG: print "------------ CHAN"
762                         sub2chunkname, = struct.unpack("4s", data.read(4))
763                         my_dict['CHAN'] = sub2chunkname
764                         sub2chunklen -= 4
765                 elif sub2chunkname == "ENAB":                             #only present if is to be disabled
766                         ###if DEBUG: print "------------ ENAB"
767                         ena, = struct.unpack(">h", data.read(2))
768                         my_dict['ENAB'] = ena
769                         sub2chunklen -= 2
770                 elif sub2chunkname == "NEGA":                             #only present if is to be enabled
771                         ###if DEBUG: print "------------ NEGA"
772                         ena, = struct.unpack(">h", data.read(2))
773                         if ena == 1:
774                                 my_dict['NEGA'] = ena
775                         sub2chunklen -= 2
776                 elif sub2chunkname == "OPAC":                             #only present if is to be disabled
777                         ###if DEBUG: print "------------ OPAC"
778                         opa, = struct.unpack(">h", data.read(2))
779                         s, = struct.unpack(">f", data.read(4))
780                         envelope, env_size = read_vx(data)
781                         my_dict['OPAC'] = opa
782                         my_dict['OPACVAL'] = s
783                         sub2chunklen -= 6
784                 elif sub2chunkname == "AXIS":
785                         ###if DEBUG: print "------------ AXIS"
786                         ena, = struct.unpack(">h", data.read(2))
787                         my_dict['DISPLAXIS'] = ena
788                         sub2chunklen -= 2
789                 else:                                                       # Misc Chunks
790                         ###if DEBUG: print "------------ SURF: BLOK: IMAP: %s: skipping" % sub2chunkname
791                         discard = data.read(sub2chunklen)
792         #end loop on blok header subchunks
793         ##############################################################
794         # blok attributes sub-chunk
795         ##############################################################
796         subchunkname, = struct.unpack("4s", data.read(4))
797         subchunklen, = struct.unpack(">h", data.read(2))
798         accumulate_i += subchunklen + 6
799         if subchunkname != 'TMAP':
800                 ###if DEBUG: print "---------- SURF: BLOK: %s: block aborting" % subchunkname
801                 return {}, ""
802         ###if DEBUG: print "---------- TMAP"
803         i = 0
804         while(i < subchunklen): # -----------left 6----------------------- loop on header parameters
805                 sub2chunkname, = struct.unpack("4s", data.read(4))
806                 sub2chunklen, = struct.unpack(">h", data.read(2))
807                 i = i + 6 + sub2chunklen
808                 if sub2chunkname == "CNTR":
809                         ###if DEBUG: print "------------ CNTR"
810                         x, y, z = struct.unpack(">fff", data.read(12))
811                         envelope, env_size = read_vx(data)
812                         my_dict['CNTR'] = [x, y, z]
813                         sub2chunklen -= (12+env_size)
814                 elif sub2chunkname == "SIZE":
815                         ###if DEBUG: print "------------ SIZE"
816                         x, y, z = struct.unpack(">fff", data.read(12))
817                         envelope, env_size = read_vx(data)
818                         my_dict['SIZE'] = [x, y, z]
819                         sub2chunklen -= (12+env_size)
820                 elif sub2chunkname == "ROTA":
821                         ###if DEBUG: print "------------ ROTA"
822                         x, y, z = struct.unpack(">fff", data.read(12))
823                         envelope, env_size = read_vx(data)
824                         my_dict['ROTA'] = [x, y, z]
825                         sub2chunklen -= (12+env_size)
826                 elif sub2chunkname == "CSYS":
827                         ###if DEBUG: print "------------ CSYS"
828                         ena, = struct.unpack(">h", data.read(2))
829                         my_dict['CSYS'] = ena
830                         sub2chunklen -= 2
831                 else:                                                       # Misc Chunks
832                         ###if DEBUG: print "------------ SURF: BLOK: TMAP: %s: skipping" % sub2chunkname
833                         pass
834                 if  sub2chunklen > 0:
835                         discard = data.read(sub2chunklen)
836         #end loop on blok attributes subchunks
837         ##############################################################
838         # ok, now other attributes without sub_chunks
839         ##############################################################
840         while(accumulate_i < lenght): # ---------------------------------- loop on header parameters: lenght has already stripped the 6 bypes header
841                 subchunkname, = struct.unpack("4s", data.read(4))
842                 subchunklen, = struct.unpack(">H", data.read(2))
843                 accumulate_i = accumulate_i + 6 + subchunklen
844                 if subchunkname == "PROJ":
845                         ###if DEBUG: print "---------- PROJ"
846                         p, = struct.unpack(">h", data.read(2))
847                         my_dict['PROJ'] = p
848                         subchunklen -= 2
849                 elif subchunkname == "AXIS":
850                         ###if DEBUG: print "---------- AXIS"
851                         a, = struct.unpack(">h", data.read(2))
852                         my_dict['MAJAXIS'] = a
853                         subchunklen -= 2
854                 elif subchunkname == "IMAG":
855                         ###if DEBUG: print "---------- IMAG"
856                         i, i_size = read_vx(data)
857                         my_dict['IMAG'] = i
858                         subchunklen -= i_size
859                 elif subchunkname == "WRAP":
860                         ###if DEBUG: print "---------- WRAP"
861                         ww, wh = struct.unpack(">hh", data.read(4))
862                         #reduce width and height to just 1 parameter for both
863                         my_dict['WRAP'] = max([ww,wh])
864                         #my_dict['WRAPWIDTH'] = ww
865                         #my_dict['WRAPHEIGHT'] = wh
866                         subchunklen -= 4
867                 elif subchunkname == "WRPW":
868                         ###if DEBUG: print "---------- WRPW"
869                         w, = struct.unpack(">f", data.read(4))
870                         my_dict['WRPW'] = w
871                         envelope, env_size = read_vx(data)
872                         subchunklen -= (env_size+4)
873                 elif subchunkname == "WRPH":
874                         ###if DEBUG: print "---------- WRPH"
875                         w, = struct.unpack(">f", data.read(4))
876                         my_dict['WRPH'] = w
877                         envelope, env_size = read_vx(data)
878                         subchunklen -= (env_size+4)
879                 elif subchunkname == "VMAP":
880                         ###if DEBUG: print "---------- VMAP"
881                         vmp, i = read_name(data)
882                         my_dict['VMAP'] = vmp
883                         my_uvname = vmp
884                         subchunklen -= i
885                 else:                                                    # Misc Chunks
886                         ###if DEBUG: print "---------- SURF: BLOK: %s: skipping" % subchunkname
887                         pass
888                 if  subchunklen > 0:
889                         discard = data.read(subchunklen)
890         #end loop on blok subchunks
891         return my_dict, my_uvname
892
893
894 # =====================
895 # === Read Surfaces ===
896 # =====================
897 def read_surfs(lwochunk, surf_list, tag_list):
898         my_dict = {}
899         data = cStringIO.StringIO(lwochunk.read())
900         surf_name, i = read_name(data)
901         parent_name, j = read_name(data)
902         i += j
903         if (surf_name == "") or not(surf_name in tag_list):
904                 ###if DEBUG: print "Reading SURF: Actually empty surf name not allowed. Skipping"
905                 return {}
906         if (parent_name != ""):
907                 parent_index = [x['NAME'] for x in surf_list].count(parent_name)
908                 if parent_index >0:
909                         my_dict = surf_list[parent_index-1]
910         my_dict['NAME'] = surf_name
911         ###if DEBUG: print "Surface data for TAG %s" % surf_name
912         while(i < lwochunk.chunksize):
913                 subchunkname, = struct.unpack("4s", data.read(4))
914                 subchunklen, = struct.unpack(">H", data.read(2))
915                 i = i + 6 + subchunklen #6 bytes subchunk header
916                 if subchunkname == "COLR":                             #color: mapped on color
917                         ###if DEBUG: print "-------- COLR"
918                         r, g, b = struct.unpack(">fff", data.read(12))
919                         envelope, env_size = read_vx(data)
920                         my_dict['COLR'] = [r, g, b]
921                         subchunklen -= (12+env_size)
922                 elif subchunkname == "DIFF":                           #diffusion: mapped on reflection (diffuse shader)
923                         ###if DEBUG: print "-------- DIFF"
924                         s, = struct.unpack(">f", data.read(4))
925                         envelope, env_size = read_vx(data)
926                         my_dict['DIFF'] = s
927                         subchunklen -= (4+env_size)
928                 elif subchunkname == "SPEC":                           #specularity: mapped to specularity (spec shader)
929                         ###if DEBUG: print "-------- SPEC"
930                         s, = struct.unpack(">f", data.read(4))
931                         envelope, env_size = read_vx(data)
932                         my_dict['SPEC'] = s
933                         subchunklen -= (4+env_size)
934                 elif subchunkname == "REFL":                           #reflection: mapped on raymirror
935                         ###if DEBUG: print "-------- REFL"
936                         s, = struct.unpack(">f", data.read(4))
937                         envelope, env_size = read_vx(data)
938                         my_dict['REFL'] = s
939                         subchunklen -= (4+env_size)
940                 elif subchunkname == "TRNL":                           #translucency: mapped on same param
941                         ###if DEBUG: print "-------- TRNL"
942                         s, = struct.unpack(">f", data.read(4))
943                         envelope, env_size = read_vx(data)
944                         my_dict['TRNL'] = s
945                         subchunklen -= (4+env_size)
946                 elif subchunkname == "GLOS":                           #glossiness: mapped on specularity hardness (spec shader)
947                         ###if DEBUG: print "-------- GLOS"
948                         s, = struct.unpack(">f", data.read(4))
949                         envelope, env_size = read_vx(data)
950                         my_dict['GLOS'] = s
951                         subchunklen -= (4+env_size)
952                 elif subchunkname == "TRAN":                           #transparency: inverted and mapped on alpha channel
953                         ###if DEBUG: print "-------- TRAN"
954                         s, = struct.unpack(">f", data.read(4))
955                         envelope, env_size = read_vx(data)
956                         my_dict['TRAN'] = s
957                         subchunklen -= (4+env_size)
958                 elif subchunkname == "LUMI":                           #luminosity: mapped on emit channel
959                         ###if DEBUG: print "-------- LUMI"
960                         s, = struct.unpack(">f", data.read(4))
961                         envelope, env_size = read_vx(data)
962                         my_dict['LUMI'] = s
963                         subchunklen -= (4+env_size)
964                 elif subchunkname == "GVAL":                           #glow: mapped on add channel
965                         ###if DEBUG: print "-------- GVAL"
966                         s, = struct.unpack(">f", data.read(4))
967                         envelope, env_size = read_vx(data)
968                         my_dict['GVAL'] = s
969                         subchunklen -= (4+env_size)
970                 elif subchunkname == "SMAN":                           #smoothing angle
971                         ###if DEBUG: print "-------- SMAN"
972                         s, = struct.unpack(">f", data.read(4))
973                         my_dict['SMAN'] = s
974                         subchunklen -= 4
975                 elif subchunkname == "SIDE":                           #double sided?
976                         ###if DEBUG: print "-------- SIDE"                             #if 1 side do not define key
977                         s, = struct.unpack(">H", data.read(2))
978                         if s == 3:
979                                 my_dict['SIDE'] = s
980                         subchunklen -= 2
981                 elif subchunkname == "RIND":                           #Refraction: mapped on IOR
982                         ###if DEBUG: print "-------- RIND"
983                         s, = struct.unpack(">f", data.read(4))
984                         envelope, env_size = read_vx(data)
985                         my_dict['RIND'] = s
986                         subchunklen -= (4+env_size)
987                 elif subchunkname == "BLOK":                           #blocks
988                         ###if DEBUG: print "-------- BLOK"
989                         rr, uvname = read_surfblok(data.read(subchunklen))
990                         #paranoia setting: preventing adding an empty dict
991                         if rr: # != {}
992                                 try:
993                                         my_dict['BLOK'].append(rr)
994                                 except:
995                                         my_dict['BLOK'] = [rr]
996                                         
997                         if uvname: # != "":
998                                 my_dict['UVNAME'] = uvname                            #theoretically there could be a number of them: only one used per surf
999                         # all are dictionaries - so testing keys 
1000                         if not('g_IMAG' in my_dict) and ('CHAN' in rr) and ('OPAC' in rr) and ('IMAG' in rr):
1001                                 if (rr['CHAN'] == 'COLR') and (rr['OPAC'] == 0):
1002                                         my_dict['g_IMAG'] = rr['IMAG']                 #do not set anything, just save image object for later assignment
1003                         subchunklen = 0 #force ending
1004                 else:                                                       # Misc Chunks
1005                         pass
1006                         ###if DEBUG: print "-------- SURF:%s: skipping" % subchunkname
1007                 if  subchunklen > 0:
1008                         discard = data.read(subchunklen)
1009         #end loop on surf chunks
1010         try:#if my_dict.has_key('BLOK'):
1011            my_dict['BLOK'].reverse() #texture applied in reverse order with respect to reading from lwo
1012         except:
1013                 pass
1014         
1015         #uncomment this if material pre-allocated by read_surf
1016         my_dict['g_MAT'] = bpy.data.materials.new(my_dict['NAME'])
1017         ###if DEBUG: print "-> Material pre-allocated."
1018         return my_dict
1019
1020 # =========================
1021 # === Recalculate Faces ===
1022 # =========================
1023
1024 def get_uvface(complete_list, facenum):
1025         # extract from the complete list only vertexes of the desired polygon
1026         '''
1027         my_facelist = []
1028         for elem in complete_list:
1029                 if elem[0] == facenum:
1030                         my_facelist.append(elem)
1031         return my_facelist
1032         '''
1033         return [elem for elem in complete_list if elem[0] == facenum]
1034
1035 def get_newindex(polygon_list, vertnum):
1036         # extract from the polygon list the new index associated to a vertex
1037         if not polygon_list: # == []
1038                 return -1
1039         for elem in polygon_list:
1040                 if elem[1] == vertnum:
1041                         return elem[2]
1042         # ###if DEBUG: print "WARNING: expected vertex %s for polygon %s. Polygon_list dump follows" % (vertnum, polygon_list[0][0])
1043         # ###if DEBUG: print polygon_list
1044         return -1
1045
1046 def get_surf(surf_list, cur_tag):
1047         for elem in surf_list: # elem can be None
1048                 if elem and elem['NAME'] == cur_tag:
1049                         return elem
1050         return {}
1051
1052
1053
1054 # ====================================
1055 # === Modified Create Blender Mesh ===
1056 # ====================================
1057 def my_create_mesh(clip_list, surf, objspec_list, current_facelist, objname, not_used_faces):
1058         #take the needed faces and update the not-used face list
1059         complete_vertlist = objspec_list[2]
1060         complete_facelist = objspec_list[3]
1061         uvcoords_dict = objspec_list[7]
1062         facesuv_dict = objspec_list[8]
1063         vertex_map = {} #implementation as dict
1064         cur_ptag_faces = []
1065         cur_ptag_faces_indexes = []
1066         maxface = len(complete_facelist)
1067         for ff in current_facelist:
1068                 if ff >= maxface:
1069                         ###if DEBUG: print "Non existent face addressed: Giving up with this object"
1070                         return None, not_used_faces              #return the created object
1071                 cur_face = complete_facelist[ff]
1072                 cur_ptag_faces_indexes.append(ff)
1073                 if not_used_faces: # != []
1074                         not_used_faces[ff] = -1
1075                 for vv in cur_face: vertex_map[vv] = 1
1076         #end loop on faces
1077         store_edge = 0
1078         
1079         scn= bpy.data.scenes.active
1080         msh = bpy.data.meshes.new()
1081         obj = scn.objects.new(msh)
1082         
1083         mat = None
1084         try:
1085                 msh.materials = [surf['g_MAT']]
1086         except:
1087                 pass
1088         
1089         msh.mode |= Blender.Mesh.Modes.AUTOSMOOTH #smooth it anyway
1090         if 'SMAN' in surf: # has_key
1091                 #not allowed mixed mode mesh (all the mesh is smoothed and all with the same angle)
1092                 #only one smoothing angle will be active! => take the max one
1093                 msh.degr = min(80, int(surf['SMAN']/3.1415926535897932384626433832795*180.0))     #lwo in radians - blender in degrees
1094         
1095         try:
1096                 img= lookup_imag(clip_list, surf['g_IMAG'])['g_IMG']
1097         except:
1098                 img= None
1099         
1100         #uv_flag = ((surf.has_key('UVNAME')) and (uvcoords_dict.has_key(surf['UVNAME'])) and (img != None))
1101         uv_flag = (('UVNAME' in surf) and (surf['UVNAME'] in uvcoords_dict))
1102
1103         ###if DEBUG: print "\n#===================================================================#"
1104         ###if DEBUG: print "Processing Object: %s" % objname
1105         ###if DEBUG: print "#===================================================================#"
1106         
1107         if uv_flag:
1108                 msh.verts.extend([(0.0,0.0,0.0),])
1109                 j = 1
1110         else:
1111                 j = 0
1112         
1113         def tmp_get_vert(k, i):
1114                 vertex_map[k] = i+j # j is the dummy vert
1115                 # ###if DEBUG: print complete_vertlist[i]
1116                 return complete_vertlist[k]
1117         
1118         
1119         
1120         msh.verts.extend([tmp_get_vert(k, i) for i, k in enumerate(vertex_map.iterkeys())])
1121         msh.transform(TXMTX)                                    # faster then applying while reading.
1122         #end sweep over vertexes
1123
1124         #append faces
1125         FACE_TEX= Blender.Mesh.FaceModes.TEX
1126         FACE_ALPHA= Blender.Mesh.FaceTranspModes.ALPHA
1127         EDGE_DRAW_FLAG= Blender.Mesh.EdgeFlags.EDGEDRAW | Blender.Mesh.EdgeFlags.EDGERENDER
1128         
1129         
1130         edges = []
1131         face_data = [] # [(indicies, material, uvs, image), ]
1132         face_uvs = []
1133         edges_fgon = []
1134         
1135         if uv_flag:
1136                 uvcoords_dict_context = uvcoords_dict[surf['UVNAME']]
1137                 try:    current_uvdict = facesuv_dict[surf['UVNAME']]
1138                 except: current_uvdict = None
1139                 
1140         default_uv = Blender.Mathutils.Vector(0,0)
1141         def tmp_get_face_uvs(cur_face, i):
1142                 uvs = []
1143                 if current_uvdict:
1144                         uvface = get_uvface(current_uvdict,i)
1145                         for vi in cur_face:
1146                                 ni = get_newindex(uvface, vi)
1147                                 if ni == -1: ni = vi
1148                                 
1149                                 try:
1150                                         uvs.append(uvcoords_dict_context[ ni ])
1151                                 except:
1152                                         ###if DEBUG: print '\tWarning, Corrupt UVs'
1153                                         uvs.append(default_uv)
1154                 else:
1155                         for vi in cur_face:
1156                                 try:
1157                                         uvs.append(uvcoords_dict_context[ vi ])
1158                                 except:
1159                                         ###if DEBUG: print '\tWarning, Corrupt UVs'
1160                                         uvs.append(default_uv)
1161                 
1162                 return uvs
1163         cur_face
1164         for i in cur_ptag_faces_indexes:
1165                 cur_face = complete_facelist[i]
1166                 numfaceverts = len(cur_face)
1167                 
1168                 if numfaceverts == 2:           edges.append((vertex_map[cur_face[0]], vertex_map[cur_face[1]]))
1169                 elif numfaceverts == 3 or numfaceverts == 4:    
1170                         rev_face = [__i for __i in reversed(cur_face)]
1171                         face_data.append( [vertex_map[j] for j in rev_face] )
1172                         if uv_flag: face_uvs.append(tmp_get_face_uvs(rev_face, i))
1173                 elif numfaceverts > 4:
1174                         meta_faces= BPyMesh.ngon(complete_vertlist, cur_face, PREF_FIX_LOOPS= True)
1175                         edge_face_count = {}
1176                         for mf in meta_faces:
1177                                 # These will always be tri's since they are scanfill faces
1178                                 mf = cur_face[mf[2]], cur_face[mf[1]], cur_face[mf[0]]
1179                                 face_data.append( [vertex_map[j] for j in mf] )
1180                                 
1181                                 if uv_flag: face_uvs.append(tmp_get_face_uvs(mf, i))
1182                                 
1183                                 #if USE_FGON:
1184                                 if len(meta_faces) > 1:
1185                                         mf = face_data[-1] # reuse mf
1186                                         for j in xrange(3):
1187                                                 v1= mf[j]
1188                                                 v2= mf[j-1]
1189                                                 if v1!=v2:
1190                                                         if v1>v2:
1191                                                                 v2,v1= v1,v2
1192                                                         try:
1193                                                                 edge_face_count[v1,v2]+= 1
1194                                                         except:
1195                                                                 edge_face_count[v1,v2]= 0
1196                                 
1197
1198                         
1199                         if edge_face_count:
1200                                 edges_fgon.extend( [vert_key for vert_key, count in edge_face_count.iteritems() if count] )
1201         
1202         if edges:
1203                 msh.edges.extend(edges)
1204         
1205         face_mapping_removed = msh.faces.extend(face_data, indexList=True)
1206         if 'TRAN' in surf or (mat and mat.alpha<1.0): # incase mat is null
1207                 transp_flag = True
1208         else:
1209                 transp_flag = False
1210         
1211         if uv_flag:
1212                 msh.faceUV = True
1213                 msh_faces= msh.faces
1214                 for i, uvs in enumerate(face_uvs):
1215                         i_mapped = face_mapping_removed[i]
1216                         if i_mapped != None:
1217                                 f = msh_faces[i_mapped]
1218                                 f.uv = uvs
1219                                 if img:
1220                                         f.image = img
1221                                 
1222                                 if transp_flag: f.transp |= FACE_ALPHA
1223         
1224         if edges_fgon:
1225                 msh_edges = msh.edges
1226                 FGON= Blender.Mesh.EdgeFlags.FGON
1227                 edges_fgon = msh.findEdges( edges_fgon )
1228                 if type(edges_fgon) != list: edges_fgon = [edges_fgon]
1229                 for ed in edges_fgon:
1230                         if ed!=None:
1231                                 msh_edges[ed].flag |= FGON
1232         
1233         if not(uv_flag):        #clear eventual UV data
1234                 msh.faceUV = False
1235         
1236         if uv_flag:
1237                 msh.verts.delete([0,])
1238         
1239         return obj, not_used_faces              #return the created object
1240
1241
1242 # ============================================
1243 # === Set Subsurf attributes on given mesh ===
1244 # ============================================
1245 def set_subsurf(obj):
1246         mods = obj.modifiers                      # get the object's modifiers
1247         mod = mods.append(Blender.Modifier.Type.SUBSURF)  # add a new subsurf modifier
1248         mod[Blender.Modifier.Settings.LEVELS] = 2         # set subsurf subdivision levels to 2
1249         mod[Blender.Modifier.Settings.RENDLEVELS] = 2     # set subsurf rendertime subdivision levels to 2
1250         obj.makeDisplayList()
1251
1252
1253 # =================================
1254 # === object size and dimension ===
1255 # =================================
1256 def obj_size_pos(obj):
1257         bbox = obj.getBoundBox()
1258         bbox_min = map(lambda *row: min(row), *bbox) #transpose & get min
1259         bbox_max = map(lambda *row: max(row), *bbox) #transpose & get max
1260         obj_size = (bbox_max[0]-bbox_min[0], bbox_max[1]-bbox_min[1], bbox_max[2]-bbox_min[2])
1261         obj_pos = ( (bbox_max[0]+bbox_min[0]) / 2, (bbox_max[1]+bbox_min[1]) / 2, (bbox_max[2]+bbox_min[2]) / 2)
1262         return (obj_size, obj_pos)
1263
1264
1265 # =========================
1266 # === Create the object ===
1267 # =========================
1268 def create_objects(clip_list, objspec_list, surf_list):
1269         nf = len(objspec_list[3])
1270         not_used_faces = range(nf)
1271         ptag_dict = objspec_list[5]
1272         obj_dict = {}  #links tag names to object, used for material assignments
1273         obj_dim_dict = {}
1274         obj_list = []  #have it handy for parent association
1275         middlechar = "+"
1276         endchar = ""
1277         if (objspec_list[6] == 1):
1278                 middlechar = endchar = "#"
1279         for cur_tag, ptag_dict_val in ptag_dict.iteritems():
1280                 if ptag_dict_val != []:
1281                         cur_surf = get_surf(surf_list, cur_tag)
1282                         cur_obj, not_used_faces=  my_create_mesh(clip_list, cur_surf, objspec_list, ptag_dict_val, objspec_list[0][:9]+middlechar+cur_tag[:9], not_used_faces)
1283                         # Works now with new modifiers
1284                         if objspec_list[6] == 1:
1285                                 set_subsurf(cur_obj)
1286                         if cur_obj: # != None
1287                                 obj_dict[cur_tag] = cur_obj
1288                                 obj_dim_dict[cur_tag] = obj_size_pos(cur_obj)
1289                                 obj_list.append(cur_obj)
1290         #end loop on current group
1291         #and what if some faces not used in any named PTAG? get rid of unused faces
1292         orphans = []
1293         for tt in not_used_faces:
1294                 if tt > -1: orphans.append(tt)
1295         #end sweep on unused face list
1296         not_used_faces = None
1297         if orphans: # != []
1298                 cur_surf = get_surf(surf_list, "_Orphans")
1299                 cur_obj, not_used_faces = my_create_mesh(clip_list, cur_surf, objspec_list, orphans, objspec_list[0][:9]+middlechar+"Orphans", [])
1300                 if cur_obj: # != None
1301                         if objspec_list[6] == 1:
1302                                 set_subsurf(cur_obj)
1303                         obj_dict["_Orphans"] = cur_obj
1304                         obj_dim_dict["_Orphans"] = obj_size_pos(cur_obj)
1305                         obj_list.append(cur_obj)
1306         objspec_list[1]= obj_dict
1307         objspec_list[4]= obj_dim_dict
1308         
1309         return
1310
1311
1312
1313 # ===========================================
1314 # === Lookup for image index in clip_list ===
1315 # ===========================================
1316 def lookup_imag(clip_list, ima_id):
1317         for ii in clip_list:
1318                 if ii and ii['ID'] == ima_id:
1319                         if 'XREF' in ii: # has_key
1320                                 #cross reference - recursively look for images
1321                                 return lookup_imag(clip_list, ii['XREF'])
1322                         else:
1323                                 return ii
1324         return None
1325
1326
1327 # ===================================================
1328 # === Create and assign image mapping to material ===
1329 # ===================================================
1330 def create_blok(surf, mat, clip_list, obj_size, obj_pos):
1331
1332         def output_size_ofs(size, pos, blok):
1333                 #just automate repetitive task
1334                 # 0 == X, 1 == Y, 2 == Z
1335                 size_default = [1.0] * 3
1336                 size2 = [1.0] * 3
1337                 ofs_default = [0.0] * 3
1338                 offset = [1.0] * 3
1339                 axis_default = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z]
1340                 axis = [1.0] * 3
1341                 c_map_txt = ["    X--", "    -Y-", "    --Z"]
1342                 c_map = [0,1,2]             # standard, good for Z axis projection
1343                 if blok['MAJAXIS'] == 0:
1344                         c_map = [1,2,0]         # X axis projection
1345                 if blok['MAJAXIS'] == 2:
1346                         c_map = [0,2,1]         # Y axis projection
1347
1348                 ###if DEBUG: print "!!!axis mapping:"
1349                 #this is the smart way
1350                 ###if DEBUG: for mp in c_map: print c_map_txt[mp]
1351
1352                 if blok['SIZE'][0] != 0.0:          #paranoia controls
1353                         size_default[0] = (size[0]/blok['SIZE'][0])
1354                         ofs_default[0] = ((blok['CNTR'][0]-pos[0])/blok['SIZE'][0])
1355                 if blok['SIZE'][1] != 0.0:
1356                         size_default[2] = (size[2]/blok['SIZE'][1])
1357                         ofs_default[2] = ((blok['CNTR'][1]-pos[2])/blok['SIZE'][1])
1358                 if blok['SIZE'][2] != 0.0:
1359                         size_default[1] = (size[1]/blok['SIZE'][2])
1360                         ofs_default[1] = ((blok['CNTR'][2]-pos[1])/blok['SIZE'][2])
1361
1362                 for mp in xrange(3):
1363                         axis[mp] = axis_default[c_map[mp]]
1364                         size2[mp] = size_default[c_map[mp]]
1365                         offset[mp] = ofs_default[c_map[mp]]
1366                         if offset[mp]>10.0: offset[mp]-10.0
1367                         if offset[mp]<-10.0: offset[mp]+10.0
1368 #        size = [size_default[mp] for mp in c_map]
1369
1370                 ###if DEBUG: print "!!!texture size and offsets:"
1371                 ###if DEBUG: print "    sizeX = %.5f; sizeY = %.5f; sizeZ = %.5f" % (size[0],size[1],size[2])
1372                 ###if DEBUG: print "    ofsX = %.5f; ofsY = %.5f; ofsZ = %.5f" % (offset[0],offset[1],offset[2])
1373                 return axis, size2, offset
1374
1375         ti = 0
1376         alphaflag = 0 #switched to 1 if some tex in this block is using alpha
1377         lastimag = 0 #experimental ....
1378         for blok in surf['BLOK']:
1379                 ###if DEBUG: print "#...................................................................#"
1380                 ###if DEBUG: print "# Processing texture block no.%s for surf %s" % (ti,surf['NAME'])
1381                 ###if DEBUG: print "#...................................................................#"
1382                 # tobj.pdict (blok)
1383                 if ti > 9: break                                    #only 8 channels 0..7 allowed for texture mapping
1384                 #if not blok['ENAB']:
1385                 #    ###if DEBUG: print "***Image is not ENABled! Quitting this block"
1386                 #    break
1387                 if not('IMAG' in blok): # has_key
1388                         ###if DEBUG: print "***No IMAGE for this block? Quitting"
1389                         break                 #extract out the image index within the clip_list
1390                 if blok['IMAG'] == 0: blok['IMAG'] = lastimag #experimental ....
1391                 ###if DEBUG: print "looking for image number %d" % blok['IMAG']
1392                 ima = lookup_imag(clip_list, blok['IMAG'])
1393                 if ima == None:
1394                         ###if DEBUG: print "***Block index image not within CLIP list? Quitting Block"
1395                         break                              #safety check (paranoia setting)
1396                 img = ima['g_IMG']
1397                 lastimag = blok['IMAG']  #experimental ....
1398                 if img == None:
1399                         ###if DEBUG: print "***Failed to pre-allocate image %s found: giving up" % ima['BASENAME']
1400                         break
1401                 tname = str(ima['ID'])
1402                 if blok['ENAB']:
1403                         tname += "+"
1404                 else:
1405                         tname += "x" #let's signal when should not be enabled
1406                 if 'CHAN' in blok: # has_key
1407                         tname += blok['CHAN']
1408                 newtex = bpy.data.textures.new(tname)
1409                 newtex.setType('Image')                 # make it anu image texture
1410                 newtex.image = img
1411                 #how does it extends beyond borders
1412                 if 'WRAP' in blok: # has_key
1413                         if (blok['WRAP'] == 3) or (blok['WRAP'] == 2):
1414                                 newtex.setExtend('Extend')
1415                         elif (blok['WRAP'] == 1):
1416                                 newtex.setExtend('Repeat')
1417                         elif (blok['WRAP'] == 0):
1418                                 newtex.setExtend('Clip')
1419                 ###if DEBUG: print "generated texture %s" % tname
1420
1421                 #MapTo is determined by CHAN parameter
1422                 #assign some defaults
1423                 colfac = 1.0
1424                 dvar = 1.0
1425                 norfac = 0.5
1426                 nega = False
1427                 mapflag = Blender.Texture.MapTo.COL  #default to color
1428                 maptype = Blender.Texture.Mappings.FLAT
1429                 if 'CHAN' in blok: # has_key
1430                         if blok['CHAN'] == 'COLR' and 'OPACVAL' in blok: # has_key
1431                                 colfac = blok['OPACVAL']
1432                                 # Blender needs this to be clamped
1433                                 colfac = max(0.0, min(1.0, colfac))
1434                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> Col = %.3f" % colfac
1435                         if blok['CHAN'] == 'BUMP':
1436                                 mapflag = Blender.Texture.MapTo.NOR
1437                                 if 'OPACVAL' in blok: norfac = blok['OPACVAL'] # has_key
1438                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> Nor = %.3f" % norfac
1439                         if blok['CHAN'] == 'LUMI':
1440                                 mapflag = Blender.Texture.MapTo.EMIT
1441                                 if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key
1442                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
1443                         if blok['CHAN'] == 'DIFF':
1444                                 mapflag = Blender.Texture.MapTo.REF
1445                                 if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key
1446                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
1447                         if blok['CHAN'] == 'SPEC':
1448                                 mapflag = Blender.Texture.MapTo.SPEC
1449                                 if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key
1450                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
1451                         if blok['CHAN'] == 'TRAN':
1452                                 mapflag = Blender.Texture.MapTo.ALPHA
1453                                 if 'OPACVAL' in blok: dvar = blok['OPACVAL'] # has_key
1454                                 ###if DEBUG: print "!!!Set Texture -> MapTo -> DVar = %.3f" % dvar
1455                                 alphaflag = 1
1456                                 nega = True
1457                 if 'NEGA' in blok: # has_key
1458                         ###if DEBUG: print "!!!Watch-out: effect of this texture channel must be INVERTED!"
1459                         nega = not nega
1460
1461                 blendmode_list = ['Mix',
1462                                                  'Subtractive',
1463                                                  'Difference',
1464                                                  'Multiply',
1465                                                  'Divide',
1466                                                  'Mix with calculated alpha layer and stencil flag',
1467                                                  'Texture Displacement',
1468                                                  'Additive']
1469                 set_blendmode = 7 #default additive
1470                 if 'OPAC' in blok: # has_key
1471                         set_blendmode = blok['OPAC']
1472                 if set_blendmode == 5: #transparency
1473                         newtex.imageFlags |= Blender.Texture.ImageFlags.CALCALPHA
1474                         if nega: newtex.flags |= Blender.Texture.Flags.NEGALPHA
1475                 ###if DEBUG: print "!!!Set Texture -> MapTo -> Blending Mode = %s" % blendmode_list[set_blendmode]
1476
1477                 #the TexCo flag is determined by PROJ parameter
1478                 axis = [Blender.Texture.Proj.X, Blender.Texture.Proj.Y, Blender.Texture.Proj.Z]
1479                 size = [1.0] * 3
1480                 ofs = [0.0] * 3
1481                 if 'PROJ' in blok: # has_key
1482                         if blok['PROJ'] == 0: #0 - Planar
1483                                 ###if DEBUG: print "!!!Flat projection"
1484                                 coordflag = Blender.Texture.TexCo.ORCO
1485                                 maptype = Blender.Texture.Mappings.FLAT
1486                         elif blok['PROJ'] == 1: #1 - Cylindrical
1487                                 ###if DEBUG: print "!!!Cylindrical projection"
1488                                 coordflag = Blender.Texture.TexCo.ORCO
1489                                 maptype = Blender.Texture.Mappings.TUBE
1490                         elif blok['PROJ'] == 2: #2 - Spherical
1491                                 ###if DEBUG: print "!!!Spherical projection"
1492                                 coordflag = Blender.Texture.TexCo.ORCO
1493                                 maptype = Blender.Texture.Mappings.SPHERE
1494                         elif blok['PROJ'] == 3: #3 - Cubic
1495                                 ###if DEBUG: print "!!!Cubic projection"
1496                                 coordflag = Blender.Texture.TexCo.ORCO
1497                                 maptype = Blender.Texture.Mappings.CUBE
1498                         elif blok['PROJ'] == 4: #4 - Front Projection
1499                                 ###if DEBUG: print "!!!Front projection"
1500                                 coordflag = Blender.Texture.TexCo.ORCO
1501                                 maptype = Blender.Texture.Mappings.FLAT # ??? could it be a FLAT with some other TexCo type?
1502                         elif blok['PROJ'] == 5: #5 - UV
1503                                 ###if DEBUG: print "UVMapped"
1504                                 coordflag = Blender.Texture.TexCo.UV
1505                                 maptype = Blender.Texture.Mappings.FLAT  #in case of UV default to FLAT mapping => effectively not used
1506                         if blok['PROJ'] != 5: #This holds for any projection map except UV
1507                                 axis, size, ofs = output_size_ofs(obj_size, obj_pos, blok)
1508                                 
1509                                 # Clamp ofs and size else blender will raise an error
1510                                 for ii in xrange(3):
1511                                         ofs[ii]= min(10.0, max(-10, ofs[ii]))
1512                                         size[ii]= min(100, max(-100, size[ii]))
1513
1514                 mat.setTexture(ti, newtex, coordflag, mapflag)
1515                 current_mtex = mat.getTextures()[ti]
1516                 current_mtex.mapping = maptype
1517                 current_mtex.colfac = colfac
1518                 current_mtex.dvar = dvar
1519                 current_mtex.norfac = norfac
1520                 current_mtex.neg = nega
1521                 current_mtex.xproj = axis[0]
1522                 current_mtex.yproj = axis[1]
1523                 current_mtex.zproj = axis[2]
1524                 current_mtex.size = tuple(size)
1525                 current_mtex.ofs = tuple(ofs)
1526                 if (set_blendmode == 5): #transparency
1527                         current_mtex.stencil = not (nega)
1528
1529                 ti += 1
1530         #end loop over bloks
1531         return alphaflag
1532
1533
1534 # ========================================
1535 # === Create and assign a new material ===
1536 # ========================================
1537 #def update_material(surf_list, ptag_dict, obj, clip_list, uv_dict, dir_part):
1538 def update_material(clip_list, objspec, surf_list):
1539         if (surf_list == []) or (objspec[5] == {}) or (objspec[1] == {}):
1540                 ###if DEBUG: print "something getting wrong in update_material: dump follows  ..."
1541                 ###if DEBUG: print surf_list
1542                 ###if DEBUG: print objspec[5]
1543                 ###if DEBUG: print objspec[1]
1544                 return
1545         obj_dict = objspec[1]
1546         all_faces = objspec[3]
1547         obj_dim_dict = objspec[4]
1548         ptag_dict = objspec[5]
1549         uvcoords_dict = objspec[7]
1550         facesuv_dict = objspec[8]
1551         for surf in surf_list:
1552                 if surf and surf['NAME'] in ptag_dict: # in ptag_dict.keys()
1553                         ###if DEBUG: print "#-------------------------------------------------------------------#"
1554                         ###if DEBUG: print "Processing surface (material): %s" % surf['NAME']
1555                         ###if DEBUG: print "#-------------------------------------------------------------------#"
1556                         #material set up
1557                         facelist = ptag_dict[surf['NAME']]
1558                         #bounding box and position
1559                         cur_obj = obj_dict[surf['NAME']]
1560                         obj_size = obj_dim_dict[surf['NAME']][0]
1561                         obj_pos = obj_dim_dict[surf['NAME']][1]
1562                         ###if DEBUG: print surf
1563                         #uncomment this if material pre-allocated by read_surf
1564                         mat = surf['g_MAT']
1565                         if mat == None:
1566                                 ###if DEBUG: print "Sorry, no pre-allocated material to update. Giving up for %s." % surf['NAME']
1567                                 break
1568                         #mat = Blender.Material.New(surf['NAME'])
1569                         #surf['g_MAT'] = mat
1570                         if 'COLR' in surf: # has_key
1571                                 mat.rgbCol = surf['COLR']
1572                         if 'LUMI' in surf:
1573                                 mat.setEmit(surf['LUMI'])
1574                         if 'GVAL' in surf: # has_key
1575                                 mat.setAdd(surf['GVAL'])
1576                         if 'SPEC' in surf: # has_key
1577                                 mat.setSpec(surf['SPEC'])                                                       #it should be * 2 but seems to be a bit higher lwo [0.0, 1.0] - blender [0.0, 2.0]
1578                         if 'DIFF' in surf: # has_key
1579                                 mat.setRef(surf['DIFF'])                                                        #lwo [0.0, 1.0] - blender [0.0, 1.0]
1580                         if 'GLOS' in surf: # has_key                                                    #lwo [0.0, 1.0] - blender [0, 255]
1581                                 glo = int(371.67 * surf['GLOS'] - 42.334)                       #linear mapping - seems to work better than exp mapping
1582                                 if glo <32:  glo = 32                                                           #clamped to 32-255
1583                                 if glo >255: glo = 255
1584                                 mat.setHardness(glo)
1585                         if 'TRNL' in surf: # has_key
1586                                 mat.setTranslucency(surf['TRNL'])                #NOT SURE ABOUT THIS lwo [0.0, 1.0] - blender [0.0, 1.0]
1587
1588                         mm = mat.mode
1589                         mm |= Blender.Material.Modes.TRANSPSHADOW
1590                         if 'REFL' in surf: # has_key
1591                                 mat.setRayMirr(surf['REFL'])                     #lwo [0.0, 1.0] - blender [0.0, 1.0]
1592                                 mm |= Blender.Material.Modes.RAYMIRROR
1593                         if 'TRAN' in surf: # has_key
1594                                 mat.setAlpha(1.0-surf['TRAN'])                                        #lwo [0.0, 1.0] - blender [1.0, 0.0]
1595                                 mm |= Blender.Material.Modes.RAYTRANSP
1596                         if 'RIND' in surf: # has_key
1597                                 s = surf['RIND']
1598                                 if s < 1.0: s = 1.0
1599                                 if s > 3.0: s = 3.0
1600                                 mat.setIOR(s)                                                         #clipped to blender [1.0, 3.0]
1601                                 mm |= Blender.Material.Modes.RAYTRANSP
1602                         if 'BLOK' in surf and surf['BLOK'] != []:
1603                                 #update the material according to texture.
1604                                 alphaflag = create_blok(surf, mat, clip_list, obj_size, obj_pos)
1605                                 if alphaflag:
1606                                         mm |= Blender.Material.Modes.RAYTRANSP
1607                         mat.mode = mm
1608                         #finished setting up the material
1609                 #end if exist SURF
1610         #end loop on materials (SURFs)
1611         return
1612
1613
1614 # ======================
1615 # === Read Faces 6.0 ===
1616 # ======================
1617 def read_faces_6(lwochunk):
1618         data = cStringIO.StringIO(lwochunk.read())
1619         faces = []
1620         polygon_type = data.read(4)
1621         subsurf = 0
1622         if polygon_type != "FACE" and polygon_type != "PTCH":
1623                 ###if DEBUG: print "No FACE/PATCH Were Found. Polygon Type: %s" % polygon_type
1624                 return "", 2
1625         if polygon_type == 'PTCH': subsurf = 1
1626         i = 0
1627         while(i < lwochunk.chunksize-4):
1628                 #if not i%1000 and my_meshtools.show_progress:
1629                 #       Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
1630                 facev = []
1631                 numfaceverts, = struct.unpack(">H", data.read(2))
1632                 i += 2
1633
1634                 for j in xrange(numfaceverts):
1635                         index, index_size = read_vx(data)
1636                         i += index_size
1637                         facev.append(index)
1638                 faces.append(facev)
1639         ###if DEBUG: print "read %s faces; type of block %d (0=FACE; 1=PATCH)" % (len(faces), subsurf)
1640         return faces, subsurf
1641
1642 def main():
1643         if not struct:
1644                 Blender.Draw.PupMenu('This importer requires a full python install')
1645                 return
1646         
1647         Blender.Window.FileSelector(read, "Import LWO", '*.lwo')
1648
1649 if __name__=='__main__':
1650         main()
1651
1652
1653 # Cams debugging lwo loader
1654 """
1655 TIME= Blender.sys.time()
1656 import os
1657 print 'Searching for files'
1658 os.system('find /fe/lwo/Objects/ -follow -iname "*.lwo" > /tmp/templwo_list')
1659 # os.system('find /storage/ -iname "*.lwo" > /tmp/templwo_list')
1660 print '...Done'
1661 file= open('/tmp/templwo_list', 'r')
1662 lines= file.readlines()
1663
1664 # sort by filesize for faster testing
1665 lines_size = [(os.path.getsize(f[:-1]), f[:-1]) for f in lines]
1666 lines_size.sort()
1667 lines = [f[1] for f in lines_size]
1668
1669 file.close()
1670
1671 def between(v,a,b):
1672         if v <= max(a,b) and v >= min(a,b):
1673                 return True
1674                 
1675         return False
1676 size= 0.0
1677 for i, _lwo in enumerate(lines):
1678         #if i==425:      # SCANFILL
1679         #if 1:
1680         #if i==520:      # SCANFILL CRASH
1681         #if i==47:       # SCANFILL CRASH
1682         #if between(i, 525, 550):
1683         #if i > 1635:
1684         #if i != 1519: # 730
1685         if i>141:
1686                 #if 1:
1687                 # _lwo= _lwo[:-1]
1688                 print 'Importing', _lwo, '\nNUMBER', i, 'of', len(lines)
1689                 _lwo_file= _lwo.split('/')[-1].split('\\')[-1]
1690                 newScn= bpy.data.scenes.new(_lwo_file)
1691                 bpy.data.scenes.active = newScn
1692                 size += ((os.path.getsize(_lwo)/1024.0))/ 1024.0
1693                 read(_lwo)
1694                 # Remove objects to save memory?
1695                 '''
1696                 for ob in newScn.objects:
1697                         if ob.type=='Mesh':
1698                                 me= ob.getData(mesh=1)
1699                                 me.verts= None
1700                         newScn.unlink(ob)
1701                 '''
1702                 print 'mb size so far', size
1703
1704 print 'TOTAL TIME: %.6f' % (Blender.sys.time() - TIME)
1705 """