~ubuntu-branches/ubuntu/gutsy/blender/gutsy-security

« back to all changes in this revision

Viewing changes to release/scripts/obj_import.py

  • Committer: Bazaar Package Importer
  • Author(s): Florian Ernst
  • Date: 2005-11-06 12:40:03 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051106124003-3pgs7tcg5rox96xg
Tags: 2.37a-1.1
* Non-maintainer upload.
* Split out parts of 01_SConstruct_debian.dpatch again: root_build_dir
  really needs to get adjusted before the clean target runs - closes: #333958,
  see #288882 for reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!BPY
 
2
 
 
3
"""
 
4
Name: 'Wavefront (.obj)...'
 
5
Blender: 237
 
6
Group: 'Import'
 
7
Tooltip: 'Load a Wavefront OBJ File'
 
8
"""
 
9
 
 
10
__author__ = "Campbell Barton"
 
11
__url__ = ["blender", "elysiun"]
 
12
__version__ = "1.0"
 
13
 
 
14
__bpydoc__ = """\
 
15
This script imports OBJ files to Blender.
 
16
 
 
17
Usage:
 
18
 
 
19
Run this script from "File->Import" menu and then load the desired OBJ file.
 
20
"""
 
21
 
 
22
# $Id: obj_import.py,v 1.20 2005/06/12 05:54:15 ianwill Exp $
 
23
#
 
24
# --------------------------------------------------------------------------
 
25
# OBJ Import v1.0 by Campbell Barton (AKA Ideasman)
 
26
# --------------------------------------------------------------------------
 
27
# ***** BEGIN GPL LICENSE BLOCK *****
 
28
#
 
29
# This program is free software; you can redistribute it and/or
 
30
# modify it under the terms of the GNU General Public License
 
31
# as published by the Free Software Foundation; either version 2
 
32
# of the License, or (at your option) any later version.
 
33
#
 
34
# This program is distributed in the hope that it will be useful,
 
35
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
36
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
37
# GNU General Public License for more details.
 
38
#
 
39
# You should have received a copy of the GNU General Public License
 
40
# along with this program; if not, write to the Free Software Foundation,
 
41
# Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
42
#
 
43
# ***** END GPL LICENCE BLOCK *****
 
44
# --------------------------------------------------------------------------
 
45
 
 
46
ABORT_MENU = 'Failed Reading OBJ%t|File is probably another type|if not send this file to|cbarton@metavr.com|with MTL and image files for further testing.'
 
47
 
 
48
NULL_MAT = '(null)' # Name for mesh's that have no mat set.
 
49
NULL_IMG = '(null)' # Name for mesh's that have no mat set.
 
50
 
 
51
MATLIMIT = 16 # This isnt about to change but probably should not be hard coded.
 
52
 
 
53
DIR = ''
 
54
 
 
55
#==============================================#
 
56
# Return directory, where the file is          #
 
57
#==============================================#
 
58
def stripFile(path):
 
59
        lastSlash = max(path.rfind('\\'), path.rfind('/'))
 
60
        if lastSlash != -1:
 
61
                path = path[:lastSlash]
 
62
        return '%s%s' % (path, sys.sep)
 
63
 
 
64
#==============================================#
 
65
# Strips the slashes from the back of a string #
 
66
#==============================================#
 
67
def stripPath(path):
 
68
        return path.split('/')[-1].split('\\')[-1]
 
69
        
 
70
#====================================================#
 
71
# Strips the prefix off the name before writing      #
 
72
#====================================================#
 
73
def stripExt(name): # name is a string
 
74
        return name[ : name.rfind('.') ]
 
75
 
 
76
 
 
77
from Blender import *
 
78
 
 
79
 
 
80
#==================================================================================#
 
81
# This function sets textures defined in .mtl file                                 #
 
82
#==================================================================================#
 
83
def getImg(img_fileName):
 
84
        for i in Image.Get():
 
85
                if stripPath(i.filename) == stripPath(img_fileName):
 
86
                        return i
 
87
        
 
88
        # if we are this far it means the image hasnt been loaded.
 
89
        try:
 
90
                return Image.Load(img_fileName)
 
91
        except IOError:
 
92
                print '\tunable to open image file: "%s"' % img_fileName
 
93
                return
 
94
 
 
95
 
 
96
#==================================================================================#
 
97
# This function sets textures defined in .mtl file                                 #
 
98
#==================================================================================#
 
99
def loadMaterialImage(mat, img_fileName, type, meshDict):
 
100
        TEX_ON_FLAG = NMesh.FaceModes['TEX']
 
101
        
 
102
        texture = Texture.New(type)
 
103
        texture.setType('Image')
 
104
        
 
105
        image = getImg(img_fileName)
 
106
        if image:
 
107
                texture.image = image
 
108
                
 
109
        # adds textures to faces (Textured/Alt-Z mode)
 
110
        # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func.
 
111
        if image and type == 'Kd':
 
112
                for meshPair in meshDict.values():
 
113
                        for f in meshPair[0].faces:
 
114
                                #print meshPair[0].materials[f.mat].name, mat.name
 
115
                                if meshPair[0].materials[f.mat].name == mat.name:
 
116
                                        # the inline usemat command overides the material Image
 
117
                                        if not f.image:
 
118
                                                f.mode |= TEX_ON_FLAG
 
119
                                                f.image = image
 
120
        
 
121
        # adds textures for materials (rendering)
 
122
        elif type == 'Ka':
 
123
                mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR)
 
124
        elif type == 'Kd':
 
125
                mat.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.COL)
 
126
        elif type == 'Ks':
 
127
                mat.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC)
 
128
 
 
129
#==================================================================================#
 
130
# This function loads materials from .mtl file (have to be defined in obj file)    #
 
131
#==================================================================================#
 
132
def load_mtl(dir, mtl_file, meshDict, materialDict):
 
133
        
 
134
        #===============================================================================#
 
135
        # This gets a mat or creates one of the requested name if none exist.           #
 
136
        #===============================================================================#
 
137
        def getMat(matName, materialDict):
 
138
                # Make a new mat
 
139
                try:
 
140
                        return materialDict[matName]
 
141
                except NameError:
 
142
                        # Do we realy need to keep the dict up to date?, not realy but keeps consuistant.
 
143
                        materialDict[matName] = Material.New(matName)
 
144
                        return materialDict[matName]
 
145
                        
 
146
        mtl_file = stripPath(mtl_file)
 
147
        mtl_fileName = dir + mtl_file
 
148
        
 
149
        try:
 
150
                fileLines= open(mtl_fileName, 'r').readlines()
 
151
        except IOError:
 
152
                print '\tunable to open referenced material file: "%s"' % mtl_fileName
 
153
                return
 
154
        
 
155
        try:
 
156
                lIdx=0
 
157
                while lIdx < len(fileLines):
 
158
                        l = fileLines[lIdx].split()
 
159
                        
 
160
                        # Detect a line that will be ignored
 
161
                        if len(l) == 0:
 
162
                                pass
 
163
                        elif l[0] == '#' or len(l) == 0:
 
164
                                pass
 
165
                        elif l[0] == 'newmtl':
 
166
                                currentMat = getMat('_'.join(l[1:]), materialDict) # Material should alredy exist.
 
167
                        elif l[0] == 'Ka':
 
168
                                currentMat.setMirCol(float(l[1]), float(l[2]), float(l[3]))
 
169
                        elif l[0] == 'Kd':
 
170
                                currentMat.setRGBCol(float(l[1]), float(l[2]), float(l[3]))
 
171
                        elif l[0] == 'Ks':
 
172
                                currentMat.setSpecCol(float(l[1]), float(l[2]), float(l[3]))
 
173
                        elif l[0] == 'Ns':
 
174
                                currentMat.setHardness( int((float(l[1])*0.51)) )
 
175
                        elif l[0] == 'd':
 
176
                                currentMat.setAlpha(float(l[1]))
 
177
                        elif l[0] == 'Tr':
 
178
                                currentMat.setAlpha(float(l[1]))
 
179
                        elif l[0] == 'map_Ka':
 
180
                                img_fileName = dir + ' '.join(l[1:])
 
181
                                loadMaterialImage(currentMat, img_fileName, 'Ka', meshDict)
 
182
                        elif l[0] == 'map_Ks':
 
183
                                img_fileName = dir + ' '.join(l[1:])
 
184
                                loadMaterialImage(currentMat, img_fileName, 'Ks', meshDict)
 
185
                        elif l[0] == 'map_Kd':
 
186
                                img_fileName = dir + ' '.join(l[1:])
 
187
                                loadMaterialImage(currentMat, img_fileName, 'Kd', meshDict)
 
188
                        lIdx+=1
 
189
        except:
 
190
                print '\tERROR: Unable to parse MTL file.'
 
191
#===========================================================================#
 
192
# Returns unique name of object/mesh (preserve overwriting existing meshes) #
 
193
#===========================================================================#
 
194
def getUniqueName(name):
 
195
        newName = name
 
196
        uniqueInt = 0
 
197
        while 1:
 
198
                try:
 
199
                        ob = Object.Get(newName)
 
200
                        # Okay, this is working, so lets make a new name
 
201
                        newName = '%s.%d' % (name, uniqueInt)
 
202
                        uniqueInt +=1
 
203
                except AttributeError:
 
204
                        if newName not in NMesh.GetNames():
 
205
                                return newName
 
206
                        else:
 
207
                                newName = '%s.%d' % (name, uniqueInt)
 
208
                                uniqueInt +=1
 
209
 
 
210
#==================================================================================#
 
211
# This loads data from .obj file                                                   #
 
212
#==================================================================================#
 
213
def load_obj(file):
 
214
        time1 = sys.time()
 
215
        
 
216
        # Deselect all objects in the scene.
 
217
        # do this first so we dont have to bother, with objects we import
 
218
        for ob in Scene.GetCurrent().getChildren():
 
219
                ob.sel = 0
 
220
        
 
221
        TEX_OFF_FLAG = ~NMesh.FaceModes['TEX']
 
222
        
 
223
        # Get the file name with no path or .obj
 
224
        fileName = stripExt( stripPath(file) )
 
225
 
 
226
        mtl_fileName = None
 
227
 
 
228
        DIR = stripFile(file)
 
229
        
 
230
        tempFile = open(file, 'r')
 
231
        fileLines = tempFile.readlines()
 
232
        tempFile.close()
 
233
        
 
234
        uvMapList = [(0,0)] # store tuple uv pairs here
 
235
 
 
236
        # This dummy vert makes life a whole lot easier-
 
237
        # pythons index system then aligns with objs, remove later
 
238
        vertList = [None] # Could havea vert but since this is a placeholder theres no Point
 
239
        
 
240
        
 
241
        # Store all imported images in a dict, names are key
 
242
        imageDict = {}
 
243
        
 
244
        # This stores the index that the current mesh has for the current material.
 
245
        # if the mesh does not have the material then set -1
 
246
        contextMeshMatIdx = -1
 
247
        
 
248
        # Keep this out of the dict for easy accsess.
 
249
        nullMat = Material.New(NULL_MAT)
 
250
        
 
251
        currentMat = nullMat # Use this mat.
 
252
        currentImg = None # Null image is a string, otherwise this should be set to an image object.\
 
253
        currentSmooth = False
 
254
        
 
255
        # Store a list of unnamed names
 
256
        currentUnnamedGroupIdx = 1
 
257
        currentUnnamedObjectIdx = 1
 
258
        
 
259
        quadList = (0, 1, 2, 3)
 
260
        
 
261
        faceQuadVList = [None, None, None, None]
 
262
        faceTriVList = [None, None, None]
 
263
        
 
264
        #==================================================================================#
 
265
        # Load all verts first (texture verts too)                                         #
 
266
        #==================================================================================#
 
267
        nonVertFileLines = []
 
268
        smoothingGroups = {}
 
269
        materialDict = {} # Store all imported materials as unique dict, names are key
 
270
        lIdx = 0
 
271
        print '\tfile length: %d' % len(fileLines)
 
272
        try:
 
273
                while lIdx < len(fileLines):
 
274
                        # Ignore vert normals
 
275
                        if fileLines[lIdx].startswith('vn'):
 
276
                                lIdx+=1
 
277
                                continue
 
278
                        
 
279
                        # Dont Bother splitting empty or comment lines.
 
280
                        if len(fileLines[lIdx]) == 0 or\
 
281
                        fileLines[lIdx][0] == '\n' or\
 
282
                        fileLines[lIdx][0] == '#':
 
283
                                pass
 
284
                        
 
285
                        else:
 
286
                                fileLines[lIdx] = fileLines[lIdx].split()               
 
287
                                l = fileLines[lIdx]
 
288
                                
 
289
                                # Splitting may 
 
290
                                if len(l) == 0:
 
291
                                        pass
 
292
                                # Verts
 
293
                                elif l[0] == 'v':
 
294
                                        vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) )
 
295
                                
 
296
                                # UV COORDINATE
 
297
                                elif l[0] == 'vt':
 
298
                                        uvMapList.append( (float(l[1]), float(l[2])) )
 
299
                                
 
300
                                # Smoothing groups, make a list of unique.
 
301
                                elif l[0] == 's':
 
302
                                        if len(l) > 1:
 
303
                                                smoothingGroups['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet
 
304
                                                        
 
305
                                        # Keep Smoothing group line
 
306
                                        nonVertFileLines.append(l)
 
307
                                
 
308
                                # Smoothing groups, make a list of unique.
 
309
                                elif l[0] == 'usemtl':
 
310
                                        if len(l) > 1:
 
311
                                                materialDict['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet
 
312
                                                        
 
313
                                        # Keep Smoothing group line
 
314
                                        nonVertFileLines.append(l)
 
315
                                
 
316
                                else:
 
317
                                        nonVertFileLines.append(l)
 
318
                        lIdx+=1
 
319
                
 
320
        except:
 
321
                print Draw.PupMenu(ABORT_MENU)
 
322
                return
 
323
        
 
324
        del fileLines
 
325
        fileLines = nonVertFileLines
 
326
        del nonVertFileLines    
 
327
        
 
328
        #  Only want unique keys anyway
 
329
        smoothingGroups['(null)'] = None # Make sure we have at least 1.
 
330
        smoothingGroups = smoothingGroups.keys()
 
331
        print '\tfound %d smoothing groups.' % (len(smoothingGroups) -1)
 
332
        
 
333
        # Add materials to Blender for later is in teh OBJ
 
334
        for k in materialDict.keys():
 
335
                materialDict[k] = Material.New(k)
 
336
        
 
337
        
 
338
        # Make a list of all unused vert indicies that we can copy from
 
339
        VERT_USED_LIST = [0]*len(vertList)
 
340
        
 
341
        # Here we store a boolean list of which verts are used or not
 
342
        # no we know weather to add them to the current mesh
 
343
        # This is an issue with global vertex indicies being translated to per mesh indicies
 
344
        # like blenders, we start with a dummy just like the vert.
 
345
        # -1 means unused, any other value refers to the local mesh index of the vert.
 
346
 
 
347
        # currentObjectName has a char in front of it that determins weather its a group or object.
 
348
        # We ignore it when naming the object.
 
349
        currentObjectName = 'unnamed_obj_0' # If we cant get one, use this
 
350
        
 
351
        meshDict = {} # The 3 variables below are stored in a tuple within this dict for each mesh
 
352
        currentMesh = NMesh.GetRaw() # The NMesh representation of the OBJ group/Object
 
353
        currentUsedVertList = {} # A Dict of smooth groups, each smooth group has a list of used verts and they are generated on demand so as to save memory.
 
354
        currentMaterialMeshMapping = {} # Used to store material indicies so we dont have to search the mesh for materials every time.
 
355
        
 
356
        # Every mesh has a null smooth group, this is used if there are no smooth groups in the OBJ file.
 
357
        # and when for faces where no smooth group is used.
 
358
        currentSmoothGroup = '(null)' # The Name of the current smooth group
 
359
        
 
360
        # For direct accsess to the Current Meshes, Current Smooth Groups- Used verts.
 
361
        # This is of course context based and changes on the fly.
 
362
        currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
 
363
        
 
364
        # Set the initial '(null)' Smooth group, every mesh has one.
 
365
        currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
 
366
        
 
367
        
 
368
        # 0:NMesh, 1:SmoothGroups[UsedVerts[0,0,0,0]], 2:materialMapping['matname':matIndexForThisNMesh]
 
369
        meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping) 
 
370
        
 
371
 
 
372
        
 
373
                
 
374
        
 
375
        
 
376
        currentMesh.verts.append(vertList[0]) # So we can sync with OBJ indicies where 1 is the first item.
 
377
        if len(uvMapList) > 1:
 
378
                currentMesh.hasFaceUV(1) # Turn UV's on if we have ANY texture coords in this obj file.
 
379
        
 
380
 
 
381
        #==================================================================================#
 
382
        # Load all faces into objects, main loop                                           #
 
383
        #==================================================================================#
 
384
        try:
 
385
                lIdx = 0
 
386
                # Face and Object loading LOOP
 
387
                while lIdx < len(fileLines):
 
388
                        l = fileLines[lIdx]
 
389
                        
 
390
                        # FACE
 
391
                        if l[0] == 'f': 
 
392
                                # Make a face with the correct material.
 
393
                                
 
394
                                # Add material to mesh
 
395
                                if contextMeshMatIdx == -1:
 
396
                                        tmpMatLs = currentMesh.materials
 
397
                                        
 
398
                                        if len(tmpMatLs) == MATLIMIT:
 
399
                                                contextMeshMatIdx = 0 # Use first material
 
400
                                                print 'material overflow, attempting to use > 16 materials. defaulting to first.'
 
401
                                        else:
 
402
                                                contextMeshMatIdx = len(tmpMatLs)
 
403
                                                currentMaterialMeshMapping[currentMat.name] = contextMeshMatIdx
 
404
                                                currentMesh.addMaterial(currentMat)
 
405
                                
 
406
                                # Set up vIdxLs : Verts
 
407
                                # Set up vtIdxLs : UV
 
408
                                # Start with a dummy objects so python accepts OBJs 1 is the first index.
 
409
                                vIdxLs = []
 
410
                                vtIdxLs = []
 
411
                                fHasUV = len(uvMapList)-1 # Assume the face has a UV until it sho it dosent, if there are no UV coords then this will start as 0.
 
412
                                for v in l[1:]:
 
413
                                        # OBJ files can have // or / to seperate vert/texVert/normal
 
414
                                        # this is a bit of a pain but we must deal with it.
 
415
                                        objVert = v.split('/')
 
416
                                        
 
417
                                        # Vert Index - OBJ supports negative index assignment (like python)
 
418
                                        
 
419
                                        vIdxLs.append(int(objVert[0]))
 
420
                                        if fHasUV:
 
421
                                                # UV
 
422
                                                if len(objVert) == 1:
 
423
                                                        #vtIdxLs.append(int(objVert[0])) # replace with below.
 
424
                                                        vtIdxLs.append(vIdxLs[-1]) # Sticky UV coords
 
425
                                                elif objVert[1]: # != '' # Its possible that theres no texture vert just he vert and normal eg 1//2
 
426
                                                        vtIdxLs.append(int(objVert[1])) # Seperate UV coords
 
427
                                                else:
 
428
                                                        fHasUV = 0
 
429
        
 
430
                                                # Dont add a UV to the face if its larger then the UV coord list
 
431
                                                # The OBJ file would have to be corrupt or badly written for thi to happen
 
432
                                                # but account for it anyway.
 
433
                                                if len(vtIdxLs) > 0:
 
434
                                                        if vtIdxLs[-1] > len(uvMapList):
 
435
                                                                fHasUV = 0
 
436
                                                                print 'badly written OBJ file, invalid references to UV Texture coordinates.'
 
437
                                
 
438
                                # Quads only, we could import quads using the method below but it polite to import a quad as a quad.
 
439
                                if len(vIdxLs) == 4:
 
440
                                        '''
 
441
                                        f = NMesh.Face()
 
442
                                        for i in quadList: #  quadList == [0,1,2,3] 
 
443
                                                if currentUsedVertListSmoothGroup[vIdxLs[i]] == 0:
 
444
                                                        v = vertList[vIdxLs[i]]
 
445
                                                        currentMesh.verts.append(v)
 
446
                                                        f.append(v)
 
447
                                                        currentUsedVertListSmoothGroup[vIdxLs[i]] = len(currentMesh.verts)-1
 
448
                                                else:
 
449
                                                        f.v.append(currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i]]])
 
450
                                        '''
 
451
                                        if currentUsedVertListSmoothGroup[vIdxLs[0]] == 0:
 
452
                                                faceQuadVList[0] = vertList[vIdxLs[0]]
 
453
                                                currentUsedVertListSmoothGroup[vIdxLs[0]] = len(currentMesh.verts)
 
454
                                        else:
 
455
                                                faceQuadVList[0] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[0]]]
 
456
                                        
 
457
                                        if currentUsedVertListSmoothGroup[vIdxLs[1]] == 0:
 
458
                                                faceQuadVList[1] = vertList[vIdxLs[1]]
 
459
                                                currentUsedVertListSmoothGroup[vIdxLs[1]] = len(currentMesh.verts)+1
 
460
                                        else:
 
461
                                                faceQuadVList[1] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[1]]]
 
462
                                                
 
463
                                        if currentUsedVertListSmoothGroup[vIdxLs[2]] == 0:
 
464
                                                faceQuadVList[2] = vertList[vIdxLs[2]]
 
465
                                                currentUsedVertListSmoothGroup[vIdxLs[2]] = len(currentMesh.verts)+2
 
466
                                        else:
 
467
                                                faceQuadVList[2] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[2]]]
 
468
        
 
469
                                        if currentUsedVertListSmoothGroup[vIdxLs[3]] == 0:
 
470
                                                faceQuadVList[3] = vertList[vIdxLs[3]]
 
471
                                                currentUsedVertListSmoothGroup[vIdxLs[3]] = len(currentMesh.verts)+3
 
472
                                        else:
 
473
                                                faceQuadVList[3] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[3]]]
 
474
                                        
 
475
                                        currentMesh.verts.extend(faceQuadVList)
 
476
                                        f = NMesh.Face(faceQuadVList)
 
477
                                        
 
478
                                        # UV MAPPING
 
479
                                        if fHasUV:
 
480
                                                f.uv = [uvMapList[ vtIdxLs[0] ],uvMapList[ vtIdxLs[1] ],uvMapList[ vtIdxLs[2] ],uvMapList[ vtIdxLs[3] ]]
 
481
                                                if currentImg:
 
482
                                                        f.image = currentImg
 
483
                                                else:
 
484
                                                        f.mode &= TEX_OFF_FLAG
 
485
                                        
 
486
                                        f.mat = contextMeshMatIdx
 
487
                                        f.smooth = currentSmooth
 
488
                                        currentMesh.faces.append(f) # move the face onto the mesh
 
489
                                
 
490
                                elif len(vIdxLs) >= 3: # This handles tri's and fans
 
491
                                        for i in range(len(vIdxLs)-2):
 
492
                                                '''
 
493
                                                f = NMesh.Face()
 
494
                                                for ii in [0, i+1, i+2]:
 
495
                                                        if currentUsedVertListSmoothGroup[vIdxLs[ii]] == 0:
 
496
                                                                v = vertList[vIdxLs[ii]]
 
497
                                                                currentMesh.verts.append(v)
 
498
                                                                f.append(v)
 
499
                                                                currentUsedVertListSmoothGroup[vIdxLs[ii]] = len(currentMesh.verts)-1
 
500
                                                        else:
 
501
                                                                f.v.append(currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[ii]]])
 
502
                                                '''
 
503
                                                
 
504
                                                        
 
505
                                                if currentUsedVertListSmoothGroup[vIdxLs[0]] == 0:
 
506
                                                        faceTriVList[0] = vertList[vIdxLs[0]]
 
507
                                                        currentUsedVertListSmoothGroup[vIdxLs[0]] = len(currentMesh.verts)
 
508
                                                else:
 
509
                                                        faceTriVList[0] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[0]]]
 
510
                                                
 
511
                                                if currentUsedVertListSmoothGroup[vIdxLs[i+1]] == 0:
 
512
                                                        faceTriVList[1] = vertList[vIdxLs[i+1]]
 
513
                                                        currentUsedVertListSmoothGroup[vIdxLs[i+1]] = len(currentMesh.verts)+1
 
514
                                                else:
 
515
                                                        faceTriVList[1] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i+1]]]
 
516
                                                        
 
517
                                                if currentUsedVertListSmoothGroup[vIdxLs[i+2]] == 0:
 
518
                                                        faceTriVList[2] = vertList[vIdxLs[i+2]]
 
519
                                                        currentUsedVertListSmoothGroup[vIdxLs[i+2]] = len(currentMesh.verts)+2
 
520
                                                else:
 
521
                                                        faceTriVList[2] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i+2]]]
 
522
                                                
 
523
                                                currentMesh.verts.extend(faceTriVList)
 
524
                                                f = NMesh.Face(faceTriVList)                                    
 
525
                                                
 
526
                                                
 
527
                                                # UV MAPPING
 
528
                                                if fHasUV:
 
529
                                                        f.uv = [uvMapList[vtIdxLs[0]], uvMapList[vtIdxLs[i+1]], uvMapList[vtIdxLs[i+2]]]
 
530
                                                        if currentImg:
 
531
                                                                f.image = currentImg
 
532
                                                        else:
 
533
                                                                f.mode &= TEX_OFF_FLAG
 
534
                                                
 
535
                                                f.mat = contextMeshMatIdx
 
536
                                                f.smooth = currentSmooth
 
537
                                                currentMesh.faces.append(f) # move the face onto the mesh
 
538
                        
 
539
                        # FACE SMOOTHING
 
540
                        elif l[0] == 's':
 
541
                                # No value? then turn on.
 
542
                                if len(l) == 1:
 
543
                                        currentSmooth = True
 
544
                                        currentSmoothGroup = '(null)'
 
545
                                        try:
 
546
                                                currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
 
547
                                        except KeyError:
 
548
                                                currentUsedVertListSmoothGroup = VERT_USED_LIST[:]
 
549
                                                currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
 
550
                                                
 
551
                                else:
 
552
                                        if l[1] == 'off':
 
553
                                                currentSmooth = False
 
554
                                                currentSmoothGroup = '(null)'
 
555
                                                # We all have a null group so dont need to try
 
556
                                                currentUsedVertListSmoothGroup = currentUsedVertList['(null)']
 
557
                                        else: 
 
558
                                                currentSmooth = True
 
559
                                                currentSmoothGroup = '_'.join(l[1:])
 
560
        
 
561
                        # OBJECT / GROUP
 
562
                        elif l[0] == 'o' or l[0] == 'g':
 
563
                                
 
564
                                # Forget about the current image
 
565
                                currentImg = None
 
566
                                
 
567
                                # This makes sure that if an object and a group have the same name then
 
568
                                # they are not put into the same object.
 
569
                                
 
570
                                # Only make a new group.object name if the verts in the existing object have been used, this is obscure
 
571
                                # but some files face groups seperating verts and faces which results in silly things. (no groups have names.)
 
572
                                if len(l) > 1:
 
573
                                        currentObjectName = '_'.join(l[1:])
 
574
                                else: # No name given
 
575
                                        # Make a new empty name
 
576
                                        if l[0] == 'g': # Make a blank group name
 
577
                                                currentObjectName = 'unnamed_grp_%d' % currentUnnamedGroupIdx
 
578
                                                currentUnnamedGroupIdx +=1
 
579
                                        else: # is an object.
 
580
                                                currentObjectName = 'unnamed_ob_%d' % currentUnnamedObjectIdx
 
581
                                                currentUnnamedObjectIdx +=1
 
582
                                
 
583
                                
 
584
                                # If we havnt written to this mesh before then do so.
 
585
                                # if we have then we'll just keep appending to it, this is required for soem files.
 
586
                                
 
587
                                # If we are new, or we are not yet in the list of added meshes
 
588
                                # then make us new mesh.
 
589
                                if len(l) == 1 or currentObjectName not in meshDict.keys():
 
590
                                        currentMesh = NMesh.GetRaw()
 
591
                                        
 
592
                                        currentUsedVertList = {}
 
593
                                        
 
594
                                        # Sg is a string
 
595
                                        currentSmoothGroup = '(null)'
 
596
                                        currentUsedVertListSmoothGroup = VERT_USED_LIST[:]                                              
 
597
                                        currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup
 
598
                                        currentMaterialMeshMapping = {}
 
599
                                        
 
600
                                        meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping)
 
601
                                        currentMesh.hasFaceUV(1)
 
602
                                        currentMesh.verts.append( vertList[0] )
 
603
                                        contextMeshMatIdx = -1
 
604
                                        
 
605
                                else: 
 
606
                                        # Since we have this in Blender then we will check if the current Mesh has the material.
 
607
                                        # set the contextMeshMatIdx to the meshs index but only if we have it.
 
608
                                        currentMesh, currentUsedVertList, currentMaterialMeshMapping = meshDict[currentObjectName]
 
609
                                        #getMeshMaterialIndex(currentMesh, currentMat)
 
610
                                        
 
611
                                        try:
 
612
                                                contextMeshMatIdx = currentMaterialMeshMapping[currentMat.name] #getMeshMaterialIndex(currentMesh, currentMat)
 
613
                                        except KeyError:
 
614
                                                contextMeshMatIdx -1
 
615
                                        
 
616
                                        # For new meshes switch smoothing groups to null
 
617
                                        currentSmoothGroup = '(null)'
 
618
                                        currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup]
 
619
                        
 
620
                        # MATERIAL
 
621
                        elif l[0] == 'usemtl':
 
622
                                if len(l) == 1 or l[1] == NULL_MAT:
 
623
                                        currentMat = nullMat # We know we have a null mat.
 
624
                                else:
 
625
                                        currentMat = materialDict['_'.join(l[1:])]
 
626
                                        try:
 
627
                                                contextMeshMatIdx = currentMaterialMeshMapping[currentMat.name]
 
628
                                        except KeyError:
 
629
                                                contextMeshMatIdx = -1 #getMeshMaterialIndex(currentMesh, currentMat)
 
630
                                
 
631
                        # IMAGE
 
632
                        elif l[0] == 'usemat' or l[0] == 'usemap':
 
633
                                if len(l) == 1 or l[1] == '(null)' or l[1] == 'off':
 
634
                                        currentImg = None
 
635
                                else:
 
636
                                        # Load an image.
 
637
                                        newImgName = stripPath(' '.join(l[1:])) # Use space since its a file name.
 
638
                                        
 
639
                                        try:
 
640
                                                # Assume its alredy set in the dict (may or maynot be loaded)
 
641
                                                currentImg = imageDict[newImgName]
 
642
                                        
 
643
                                        except KeyError: # Not in dict, add for first time.
 
644
                                                try: # Image has not been added, Try and load the image
 
645
                                                        currentImg = Image.Load( '%s%s' % (DIR, newImgName) ) # Use join in case of spaces 
 
646
                                                        imageDict[newImgName] = currentImg
 
647
                                                        
 
648
                                                except IOError: # Cant load, just set blank.
 
649
                                                        imageDict[newImgName] = None
 
650
                                                        currentImg = None
 
651
                        
 
652
                        # MATERIAL FILE
 
653
                        elif l[0] == 'mtllib':
 
654
                                mtl_fileName = ' '.join(l[1:]) # SHOULD SUPPORT MULTIPLE MTL?
 
655
                        lIdx+=1
 
656
                
 
657
                # Applies material properties to materials alredy on the mesh as well as Textures.
 
658
                if mtl_fileName:
 
659
                        load_mtl(DIR, mtl_fileName, meshDict, materialDict)     
 
660
                
 
661
                
 
662
                importedObjects = []
 
663
                for mk in meshDict.keys():
 
664
                        meshDict[mk][0].verts.pop(0)
 
665
                        
 
666
                        # Ignore no vert meshes.
 
667
                        if not meshDict[mk][0].verts:
 
668
                                continue
 
669
                        
 
670
                        name = getUniqueName(mk)
 
671
                        ob = NMesh.PutRaw(meshDict[mk][0], name)
 
672
                        ob.name = name
 
673
                        
 
674
                        importedObjects.append(ob)
 
675
                
 
676
                # Select all imported objects.
 
677
                for ob in importedObjects:
 
678
                        ob.sel = 1
 
679
        
 
680
                print "obj import time: ", sys.time() - time1
 
681
        
 
682
        except:
 
683
                print Draw.PupMenu(ABORT_MENU)
 
684
                return
 
685
 
 
686
 
 
687
def load_obj_callback(file):
 
688
        # Try/Fails should realy account for these, but if somthing realy bad happens then Popup error.
 
689
        try:
 
690
                load_obj(file)
 
691
        except:
 
692
                print Draw.PupMenu(ABORT_MENU)
 
693
 
 
694
Window.FileSelector(load_obj_callback, 'Import Wavefront OBJ')
 
695
 
 
696
# For testing compatibility
 
697
'''
 
698
TIME = sys.time()
 
699
import os
 
700
for obj in os.listdir('/obj/'):
 
701
        if obj.lower().endswith('obj'):
 
702
                print obj
 
703
                newScn = Scene.New(obj)
 
704
                newScn.makeCurrent()
 
705
                load_obj('/obj/' + obj)
 
706
 
 
707
print "TOTAL IMPORT TIME: ", sys.time() - TIME
 
708
'''
 
709
#load_obj('/obj/foot_bones.obj')
 
710
#load_obj('/obj/mba1.obj')
 
711
#load_obj('/obj/PixZSphere50.OBJ')