758c3b0229a2a60ad7e3bc9daafc94cf416a3309
[blender.git] / release / scripts / lightwave_import.py
1 #!BPY
2
3 """
4 Name: 'LightWave (.lwo)...'
5 Blender: 232
6 Group: 'Import'
7 Tooltip: 'Import LightWave Object File Format (.lwo)'
8 """
9
10 __author__ = "Anthony D'Agostino (Scorpius)"
11 __url__ = ("blender", "elysiun",
12 "Author's homepage, http://www.redrival.com/scorpius")
13 __version__ = "Part of IOSuite 0.5"
14
15 __bpydoc__ = """\
16 This script imports LightWave files to Blender.
17
18 Usage:
19
20 Execute this script from the "File->Import" menu and choose a LightWave file to
21 open.
22 """
23
24 # $Id$
25 #
26 # +---------------------------------------------------------+
27 # | Copyright (c) 2002 Anthony D'Agostino                   |
28 # | http://www.redrival.com/scorpius                        |
29 # | scorpius@netzero.com                                    |
30 # | April 21, 2002                                          |
31 # | Released under the Blender Artistic Licence (BAL)       |
32 # | Import Export Suite v0.5                                |
33 # +---------------------------------------------------------+
34 # | Read and write LightWave Object File Format (*.lwo)     |
35 # +---------------------------------------------------------+
36
37 import Blender, mod_meshtools
38 import struct, chunk, os, cStringIO, time, operator
39
40 # =============================
41 # === Read LightWave Format ===
42 # =============================
43 def read(filename):
44         start = time.clock()
45         file = open(filename, "rb")
46
47         # === LWO header ===
48         form_id, form_size, form_type = struct.unpack(">4s1L4s",  file.read(12))
49         if (form_type != "LWOB") and (form_type != "LWO2"):
50                 print "Can't read a file with the form_type:", form_type
51                 return
52
53         objname = os.path.splitext(os.path.basename(filename))[0]
54
55         while 1:
56                 try:
57                         lwochunk = chunk.Chunk(file)
58                 except EOFError:
59                         break
60                 if lwochunk.chunkname == "LAYR":
61                         objname = read_layr(lwochunk)
62                 elif lwochunk.chunkname == "PNTS":                         # Verts
63                         verts = read_verts(lwochunk)
64                 elif lwochunk.chunkname == "POLS" and form_type == "LWO2": # Faces v6.0
65                         faces = read_faces_6(lwochunk)
66                         mod_meshtools.create_mesh(verts, faces, objname)
67                 elif lwochunk.chunkname == "POLS" and form_type == "LWOB": # Faces v5.5
68                         faces = read_faces_5(lwochunk)
69                         mod_meshtools.create_mesh(verts, faces, objname)
70                 else:                                                                                                      # Misc Chunks
71                         lwochunk.skip()
72
73         Blender.Window.DrawProgressBar(1.0, "")    # clear progressbar
74         file.close()
75         end = time.clock()
76         seconds = " in %.2f %s" % (end-start, "seconds")
77         if form_type == "LWO2": fmt = " (v6.0 Format)"
78         if form_type == "LWOB": fmt = " (v5.5 Format)"
79         message = "Successfully imported " + os.path.basename(filename) + fmt + seconds
80         mod_meshtools.print_boxed(message)
81
82 # ==================
83 # === Read Verts ===
84 # ==================
85 def read_verts(lwochunk):
86         data = cStringIO.StringIO(lwochunk.read())
87         numverts = lwochunk.chunksize/12
88         #$verts = []
89         verts = [None] * numverts
90         for i in range(numverts):
91                 if not i%100 and mod_meshtools.show_progress:
92                         Blender.Window.DrawProgressBar(float(i)/numverts, "Reading Verts")
93                 x, y, z = struct.unpack(">fff", data.read(12))
94                 #$verts.append((x, z, y))
95                 verts[i] = (x, z, y)
96         return verts
97
98 # =================
99 # === Read Name ===
100 # =================
101 def read_name(file):
102         name = ""
103         while 1:
104                 char = file.read(1)
105                 if char == "\0": break
106                 else: name += char
107         return name
108
109 # ==================
110 # === Read Layer ===
111 # ==================
112 def read_layr(lwochunk):
113         data = cStringIO.StringIO(lwochunk.read())
114         idx, flags = struct.unpack(">hh", data.read(4))
115         pivot = struct.unpack(">fff", data.read(12))
116         layer_name = read_name(data)
117         if not layer_name: layer_name = "No Name"
118         return layer_name
119
120 # ======================
121 # === Read Faces 5.5 ===
122 # ======================
123 def read_faces_5(lwochunk):
124         data = cStringIO.StringIO(lwochunk.read())
125         faces = []
126         i = 0
127         while i < lwochunk.chunksize:
128                 if not i%100 and mod_meshtools.show_progress:
129                    Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
130                 facev = []
131                 numfaceverts, = struct.unpack(">H", data.read(2))
132                 for j in range(numfaceverts):
133                         index, = struct.unpack(">H", data.read(2))
134                         facev.append(index)
135                 facev.reverse()
136                 faces.append(facev)
137                 surfaceindex, = struct.unpack(">H", data.read(2))
138                 if surfaceindex < 0:
139                         print "detail polygons follow, error."
140                         return
141                 i += (4+numfaceverts*2)
142         return faces
143
144 # ==================================
145 # === Read Variable-Length Index ===
146 # ==================================
147 def read_vx(data):
148         byte1, = struct.unpack(">B", data.read(1))
149         if byte1 != 0xFF:       # 2-byte index
150                 byte2, = struct.unpack(">B", data.read(1))
151                 index = byte1*256 + byte2
152                 index_size = 2
153         else:                           # 4-byte index
154                 byte2, byte3, byte4 = struct.unpack(">3B", data.read(3))
155                 index = byte2*65536 + byte3*256 + byte4
156                 index_size = 4
157         return index, index_size
158
159 # ======================
160 # === Read Faces 6.0 ===
161 # ======================
162 def read_faces_6(lwochunk):
163         data = cStringIO.StringIO(lwochunk.read())
164         faces = []
165         polygon_type = data.read(4)
166         if polygon_type != "FACE":
167                 print "No Faces Were Found. Polygon Type:", polygon_type
168                 return ""
169         i = 0
170         while(i < lwochunk.chunksize-4):
171                 if not i%100 and mod_meshtools.show_progress:
172                    Blender.Window.DrawProgressBar(float(i)/lwochunk.chunksize, "Reading Faces")
173                 facev = []
174                 numfaceverts, = struct.unpack(">H", data.read(2))
175                 i += 2
176
177                 for j in range(numfaceverts):
178                         index, index_size = read_vx(data)
179                         i += index_size
180                         facev.append(index)
181                 facev.reverse()
182                 faces.append(facev)
183         return faces
184
185 def fs_callback(filename):
186         read(filename)
187
188 Blender.Window.FileSelector(fs_callback, "Import LWO")