diff options
author | Willian Padovani Germano <wpgermano@gmail.com> | 2005-06-12 09:54:15 +0400 |
---|---|---|
committer | Willian Padovani Germano <wpgermano@gmail.com> | 2005-06-12 09:54:15 +0400 |
commit | 3d4438dcd76d74b47daba6c8a1ab2683ba6db123 (patch) | |
tree | 48b663807ce3f0db0260f9b3d4dbccb59e9ddfb3 /release/scripts | |
parent | 70c9f9b319bc3b510cf7c1654835ab166e821ecb (diff) |
Scripts:
- Campbell Barton updated his Wavefront obj importer;
- Jean-Michel Soler updated his paths import (eps part).
BPython bug fixes:
- oldie found by Ken Hughes: reference count of two pyobjects not being decremented in slider callback (Draw.c):
http://projects.blender.org/tracker/index.php?func=detail&aid=2727&group_id=9&atid=127
- Gergely Erdelyi found that setText() in Text3d module was not updating str length var, leading to mem corruption and provided a patch:
http://projects.blender.org/tracker/?func=detail&aid=2713&group_id=9&atid=127
- doc updates (suggested by Campbell)
Thanks guys.
Diffstat (limited to 'release/scripts')
-rw-r--r-- | release/scripts/bpymodules/eps2obj.py | 99 | ||||
-rw-r--r-- | release/scripts/obj_import.py | 802 |
2 files changed, 537 insertions, 364 deletions
diff --git a/release/scripts/bpymodules/eps2obj.py b/release/scripts/bpymodules/eps2obj.py index 8db89892fc6..f940bc332e8 100644 --- a/release/scripts/bpymodules/eps2obj.py +++ b/release/scripts/bpymodules/eps2obj.py @@ -1,20 +1,22 @@ #---------------------------------------------- -# (c) jm soler juillet 2004, released under Blender Artistic Licence -# for the Blender 2.34 Python Scripts Bundle. +# (c) jm soler juillet 2004-juin 2005 , released under Blender Artistic Licence +# for the Blender 2.34-2.37 Python Scripts Bundle. #---------------------------------------------- # Page officielle : # http://jmsoler.free.fr/didacticiel/blender/tutor/cpl_import_eps.htm # Communiquer les problemes et erreurs sur: # http://www.zoo-logique.org/3D.Blender/newsportal/thread.php?group=3D.Blender #---------------------------------------------- - -SHARP_IMPORT=0 -SCALE=1 -scale=1 +DEVELOPPEMENT = 0 +SHARP_IMPORT = 0 +SCALE = 1.0 +scale = 1 import sys #oldpath=sys.path + import Blender +from Blender import Draw BLversion=Blender.Get('version') try: @@ -55,16 +57,16 @@ os.split=split os.join=join def filtreFICHIER(nom): - f=open(nom,'r') + f=open(nom,'rU') t=f.readlines() f.close() if len(t)==1 and t[0].find('\r'): t=t[0].split('\r') - if len(t)>1: + if len(t)>1 and t[0].find('PS-Adobe-3.0')==-1 and t[0].find('EPSF')==-1: return t else: - name = "OK?%t| Not a valid file or an empty file ... " # if no %xN int is set, indices start from 1 - result = Draw.PupMenu(name) + name = "OK?%t| Not a valid file or an empty file or... %x1| not a pure PS-Adobe-2.0 file %x2 " + result = Blender.Draw.PupMenu(name) return 'false' #=============================== @@ -119,6 +121,28 @@ n0=0 #===================================================================== CP=[0.0,0.0] #currentPoint +# modifs 12/06/2005 +#===================================================================== +#====================== current transform ============================ +#===================================================================== +class transform: + def __init__(self,matrix=[1,0,01],x=0.0,y=0.0): + self.matrix=matrix[:] + self.xy=[x,y] + +GSTACK = [] +stack=transform() +GSTACK.append(stack) + +GSCALE = [1.0,1.0] +GTRANSLATE = [0.0,0.0] + +def G_move(l,a): + global GSCALE, GTRANSLATE, GSTACK + #print GSCALE, GTRANSLATE, GSTACK + return str((float(l)+GTRANSLATE[a]+GSTACK[-1].xy[a])*GSCALE[a]) +# modifs 12/06/2005 + #===================================================================== #===== to compare last position to the original move to displacement = #===== needed for cyclic efinition ================================= @@ -209,7 +233,13 @@ def mouvement_vers(l,n0,CP): courbes.ITEM[n0].Origine=[l[-3].replace('d',''),l[-2]] B=Bez() - B.co=[CP[0],CP[1],CP[0],CP[1],CP[0],CP[1]] + B.co=[G_move(CP[0],0), + G_move(CP[1],1), + G_move(CP[0],0), + G_move(CP[1],1), + G_move(CP[0],0), + G_move(CP[1],1)] + B.ha=[0,0] courbes.ITEM[n0].beziers_knot.append(B) @@ -242,7 +272,12 @@ def courbe_vers_c(l, l2, n0,CP): #c,C courbes.ITEM[n0].beziers_knot.append(B) """ B=Bez() - B.co=[l[2],l[3],l[4],l[5],l[0],l[1]] + B.co=[G_move(l[2],0), + G_move(l[3],1), + G_move(l[4],0), + G_move(l[5],1), + G_move(l[0],0), + G_move(l[1],1)] if len(courbes.ITEM[n0].beziers_knot)==1: CP=[l[0],l[1]] courbes.ITEM[n0].Origine=[l[0],l[1]] @@ -252,16 +287,21 @@ def courbe_vers_c(l, l2, n0,CP): #c,C B.ha=[0,0] courbes.ITEM[n0].beziers_knot.append(B) if len(l2)>1 and l2[-1] in Actions.keys(): - B.co[-2]=l2[0] - B.co[-1]=l2[1] + B.co[-2]=G_move(l2[0],0) + B.co[-1]=G_move(l2[1],1) else: - B.co[-2]=CP[0] - B.co[-1]=CP[1] + B.co[-2]=G_move(CP[0],0) + B.co[-1]=G_move(CP[1],1) return courbes,n0,CP def ligne_tracee_l(l,n0,CP): B=Bez() - B.co=[l[0],l[1],l[0],l[1],l[0],l[1]] + B.co=[G_move(l[0],0), + G_move(l[1],1), + G_move(l[0],0), + G_move(l[1],1), + G_move(l[0],0), + G_move(l[1],1)] B.ha=[0,0] courbes.ITEM[n0].beziers_knot.append(B) CP=[l[0],l[1]] @@ -315,14 +355,14 @@ def pik_pattern(t,l): """ def scan_FILE(nom): - global CP, courbes, SCALE, scale + global CP, courbes, SCALE, scale, GSTACK, GSCALE, GTRANSLATE dir,name=split(nom) name=name.split('.') n0=0 result=0 t=filtreFICHIER(nom) - - if nom.upper().find('.EPS')!=-1 or nom.upper().find('.PS')!=-1 and t!='false': + #print t + if t!='false' and (nom.upper().find('.EPS')!=-1 or nom.upper().find('.PS')!=-1 ): if not SHARP_IMPORT: warning = "Select Size : %t| As is %x1 | Scale on Height %x2| Scale on Width %x3" scale = Blender.Draw.PupMenu(warning) @@ -349,7 +389,22 @@ def scan_FILE(nom): courbes,n0,CP=Actions[l0[-1]](l0,l2,n0,CP) else: courbes,n0,CP=Actions[l0[-1]](l0,n0,CP) - + # modifs 10/06/2005 + elif l0!=[] and l0[-1] in ['scale']: + GSCALE=[float(l0[-3]),float(l0[-2])] + elif l0!=[] and l0[-1] in ['translate']: + GTRANSLATE=[float(l0[-3]),float(l0[-2])] + elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['gsave']: + l0[1]=l0[1].replace('[','') + l0[-2]=l0[-2].replace(']','') + stack=transform([float(l0[1]),float(l0[2]),float(l0[3]),float(l0[4])],float(l0[5]),float(l0[6])) + GSTACK.append(stack) + #print GSTACK + elif l0!=[] and l0[-1] in ['concat'] and l0[0] in ['grestore']: + del GSTACK[-1] + # modifs 12/06/2005 : end + + l=l+1#; print l t=[] @@ -386,5 +441,5 @@ def scan_FILE(nom): def fonctionSELECT(nom): scan_FILE(nom) -#Blender.Window.FileSelector (fonctionSELECT, 'SELECT .EPS/.PS FILE') +if DEVELOPPEMENT==1 : Blender.Window.FileSelector (fonctionSELECT, 'SELECT .EPS/.PS FILE') #sys.path=oldpath diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py index 6930ef86ef5..4b41a2c1cd3 100644 --- a/release/scripts/obj_import.py +++ b/release/scripts/obj_import.py @@ -2,14 +2,14 @@ """ Name: 'Wavefront (.obj)...' -Blender: 232 +Blender: 237 Group: 'Import' Tooltip: 'Load a Wavefront OBJ File' """ __author__ = "Campbell Barton" __url__ = ["blender", "elysiun"] -__version__ = "0.9" +__version__ = "1.0" __bpydoc__ = """\ This script imports OBJ files to Blender. @@ -22,7 +22,7 @@ Run this script from "File->Import" menu and then load the desired OBJ file. # $Id$ # # -------------------------------------------------------------------------- -# OBJ Import v0.9 by Campbell Barton (AKA Ideasman) +# OBJ Import v1.0 by Campbell Barton (AKA Ideasman) # -------------------------------------------------------------------------- # ***** BEGIN GPL LICENSE BLOCK ***** # @@ -43,6 +43,8 @@ Run this script from "File->Import" menu and then load the desired OBJ file. # ***** END GPL LICENCE BLOCK ***** # -------------------------------------------------------------------------- +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.' + NULL_MAT = '(null)' # Name for mesh's that have no mat set. NULL_IMG = '(null)' # Name for mesh's that have no mat set. @@ -51,15 +53,13 @@ MATLIMIT = 16 # This isnt about to change but probably should not be hard coded. DIR = '' #==============================================# -# Return directory, where is file # +# Return directory, where the file is # #==============================================# -def pathName(path,name): - length=len(path) - for CH in range(1, length): - if path[length-CH:] == name: - path = path[:length-CH] - break - return path +def stripFile(path): + lastSlash = max(path.rfind('\\'), path.rfind('/')) + if lastSlash != -1: + path = path[:lastSlash] + return '%s%s' % (path, sys.sep) #==============================================# # Strips the slashes from the back of a string # @@ -70,20 +70,19 @@ def stripPath(path): #====================================================# # Strips the prefix off the name before writing # #====================================================# -def stripName(name): # name is a string - prefixDelimiter = '.' - return name[ : name.find(prefixDelimiter) ] +def stripExt(name): # name is a string + return name[ : name.rfind('.') ] from Blender import * -import sys as py_sys + #==================================================================================# # This function sets textures defined in .mtl file # #==================================================================================# def getImg(img_fileName): for i in Image.Get(): - if i.filename == img_fileName: + if stripPath(i.filename) == stripPath(img_fileName): return i # if we are this far it means the image hasnt been loaded. @@ -94,12 +93,11 @@ def getImg(img_fileName): return - #==================================================================================# # This function sets textures defined in .mtl file # #==================================================================================# -def load_mat_image(mat, img_fileName, type, meshDict): - +def loadMaterialImage(mat, img_fileName, type, meshDict): + TEX_ON_FLAG = NMesh.FaceModes['TEX'] texture = Texture.New(type) texture.setType('Image') @@ -107,17 +105,19 @@ def load_mat_image(mat, img_fileName, type, meshDict): image = getImg(img_fileName) if image: texture.image = image - + # adds textures to faces (Textured/Alt-Z mode) # Only apply the diffuse texture to the face if the image has not been set with the inline usemat func. - if type == 'Kd': + if image and type == 'Kd': for meshPair in meshDict.values(): for f in meshPair[0].faces: + #print meshPair[0].materials[f.mat].name, mat.name if meshPair[0].materials[f.mat].name == mat.name: # the inline usemat command overides the material Image if not f.image: - f.image = image - + f.mode |= TEX_ON_FLAG + f.image = image + # adds textures for materials (rendering) elif type == 'Ka': mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) @@ -129,17 +129,19 @@ def load_mat_image(mat, img_fileName, type, meshDict): #==================================================================================# # This function loads materials from .mtl file (have to be defined in obj file) # #==================================================================================# -def load_mtl(dir, mtl_file, meshDict): +def load_mtl(dir, mtl_file, meshDict, materialDict): #===============================================================================# # This gets a mat or creates one of the requested name if none exist. # #===============================================================================# - def getMat(matName): + def getMat(matName, materialDict): # Make a new mat try: - return Material.Get(matName) + return materialDict[matName] except NameError: - return Material.New(matName) + # Do we realy need to keep the dict up to date?, not realy but keeps consuistant. + materialDict[matName] = Material.New(matName) + return materialDict[matName] mtl_file = stripPath(mtl_file) mtl_fileName = dir + mtl_file @@ -150,40 +152,42 @@ def load_mtl(dir, mtl_file, meshDict): print '\tunable to open referenced material file: "%s"' % mtl_fileName return - lIdx=0 - while lIdx < len(fileLines): - l = fileLines[lIdx].split() - - # Detect a line that will be ignored - if len(l) == 0: - pass - elif l[0] == '#' or len(l) == 0: - pass - elif l[0] == 'newmtl': - currentMat = getMat('_'.join(l[1:])) # Material should alredy exist. - elif l[0] == 'Ka': - currentMat.setMirCol(float(l[1]), float(l[2]), float(l[3])) - elif l[0] == 'Kd': - currentMat.setRGBCol(float(l[1]), float(l[2]), float(l[3])) - elif l[0] == 'Ks': - currentMat.setSpecCol(float(l[1]), float(l[2]), float(l[3])) - elif l[0] == 'Ns': - currentMat.setHardness( int((float(l[1])*0.51)) ) - elif l[0] == 'd': - currentMat.setAlpha(float(l[1])) - elif l[0] == 'Tr': - currentMat.setAlpha(float(l[1])) - elif l[0] == 'map_Ka': - img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Ka', meshDict) - elif l[0] == 'map_Ks': - img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Ks', meshDict) - elif l[0] == 'map_Kd': - img_fileName = dir + l[1] - load_mat_image(currentMat, img_fileName, 'Kd', meshDict) - lIdx+=1 - + try: + lIdx=0 + while lIdx < len(fileLines): + l = fileLines[lIdx].split() + + # Detect a line that will be ignored + if len(l) == 0: + pass + elif l[0] == '#' or len(l) == 0: + pass + elif l[0] == 'newmtl': + currentMat = getMat('_'.join(l[1:]), materialDict) # Material should alredy exist. + elif l[0] == 'Ka': + currentMat.setMirCol(float(l[1]), float(l[2]), float(l[3])) + elif l[0] == 'Kd': + currentMat.setRGBCol(float(l[1]), float(l[2]), float(l[3])) + elif l[0] == 'Ks': + currentMat.setSpecCol(float(l[1]), float(l[2]), float(l[3])) + elif l[0] == 'Ns': + currentMat.setHardness( int((float(l[1])*0.51)) ) + elif l[0] == 'd': + currentMat.setAlpha(float(l[1])) + elif l[0] == 'Tr': + currentMat.setAlpha(float(l[1])) + elif l[0] == 'map_Ka': + img_fileName = dir + ' '.join(l[1:]) + loadMaterialImage(currentMat, img_fileName, 'Ka', meshDict) + elif l[0] == 'map_Ks': + img_fileName = dir + ' '.join(l[1:]) + loadMaterialImage(currentMat, img_fileName, 'Ks', meshDict) + elif l[0] == 'map_Kd': + img_fileName = dir + ' '.join(l[1:]) + loadMaterialImage(currentMat, img_fileName, 'Kd', meshDict) + lIdx+=1 + except: + print '\tERROR: Unable to parse MTL file.' #===========================================================================# # Returns unique name of object/mesh (preserve overwriting existing meshes) # #===========================================================================# @@ -203,48 +207,36 @@ def getUniqueName(name): newName = '%s.%d' % (name, uniqueInt) uniqueInt +=1 - -# Gets the meshs index for this material, -1 if its not in the list -def getMeshMaterialIndex(mesh, material): - meshMatIndex = -1 - matIdx = 0 - meshMatList = mesh.materials - while matIdx < len(meshMatList): - if meshMatList[matIdx].name == material.name: - meshMatIndex = matIdx # The current mat index. - break - matIdx+=1 - # -1 if not found - return meshMatIndex - - - - #==================================================================================# # This loads data from .obj file # #==================================================================================# def load_obj(file): time1 = sys.time() + # Deselect all objects in the scene. + # do this first so we dont have to bother, with objects we import + for ob in Scene.GetCurrent().getChildren(): + ob.sel = 0 + TEX_OFF_FLAG = ~NMesh.FaceModes['TEX'] # Get the file name with no path or .obj - fileName = stripName( stripPath(file) ) - - mtl_fileName = '' + fileName = stripExt( stripPath(file) ) - DIR = pathName(file, stripPath(file)) + mtl_fileName = None - fileLines = open(file, 'r').readlines() + DIR = stripFile(file) + + tempFile = open(file, 'r') + fileLines = tempFile.readlines() + tempFile.close() uvMapList = [(0,0)] # store tuple uv pairs here # This dummy vert makes life a whole lot easier- # pythons index system then aligns with objs, remove later - vertList = [NMesh.Vert(0, 0, 0)] + vertList = [None] # Could havea vert but since this is a placeholder theres no Point - # Store all imported materials in a dict, names are key - materiaDict = {} # Store all imported images in a dict, names are key imageDict = {} @@ -257,55 +249,94 @@ def load_obj(file): nullMat = Material.New(NULL_MAT) currentMat = nullMat # Use this mat. - currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.\ - currentSmooth = 1 + currentImg = None # Null image is a string, otherwise this should be set to an image object.\ + currentSmooth = False # Store a list of unnamed names - currentUnnamedGroupIdx = 0 - currentUnnamedObjectIdx = 0 + currentUnnamedGroupIdx = 1 + currentUnnamedObjectIdx = 1 quadList = (0, 1, 2, 3) + faceQuadVList = [None, None, None, None] + faceTriVList = [None, None, None] + #==================================================================================# # Load all verts first (texture verts too) # #==================================================================================# nonVertFileLines = [] + smoothingGroups = {} + materialDict = {} # Store all imported materials as unique dict, names are key lIdx = 0 print '\tfile length: %d' % len(fileLines) - while lIdx < len(fileLines): - - # Dont Bother splitting empty or comment lines. - if len(fileLines[lIdx]) == 0: - pass - elif fileLines[lIdx][0] == '\n': - pass - elif fileLines[lIdx][0] == '#': - pass - - else: - fileLines[lIdx] = fileLines[lIdx].split() - l = fileLines[lIdx] + try: + while lIdx < len(fileLines): + # Ignore vert normals + if fileLines[lIdx].startswith('vn'): + lIdx+=1 + continue - # Splitting may - if len(l) == 0: + # Dont Bother splitting empty or comment lines. + if len(fileLines[lIdx]) == 0 or\ + fileLines[lIdx][0] == '\n' or\ + fileLines[lIdx][0] == '#': pass - # Verts - elif l[0] == 'v': - vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) ) - # UV COORDINATE - elif l[0] == 'vt': - uvMapList.append( (float(l[1]), float(l[2])) ) else: - nonVertFileLines.append(l) - lIdx+=1 + fileLines[lIdx] = fileLines[lIdx].split() + l = fileLines[lIdx] + + # Splitting may + if len(l) == 0: + pass + # Verts + elif l[0] == 'v': + vertList.append( NMesh.Vert(float(l[1]), float(l[2]), float(l[3]) ) ) + + # UV COORDINATE + elif l[0] == 'vt': + uvMapList.append( (float(l[1]), float(l[2])) ) + + # Smoothing groups, make a list of unique. + elif l[0] == 's': + if len(l) > 1: + smoothingGroups['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet + + # Keep Smoothing group line + nonVertFileLines.append(l) + + # Smoothing groups, make a list of unique. + elif l[0] == 'usemtl': + if len(l) > 1: + materialDict['_'.join(l[1:])] = None # Can we assign something more usefull? cant use sets yet + + # Keep Smoothing group line + nonVertFileLines.append(l) + + else: + nonVertFileLines.append(l) + lIdx+=1 + + except: + print Draw.PupMenu(ABORT_MENU) + return del fileLines fileLines = nonVertFileLines del nonVertFileLines + # Only want unique keys anyway + smoothingGroups['(null)'] = None # Make sure we have at least 1. + smoothingGroups = smoothingGroups.keys() + print '\tfound %d smoothing groups.' % (len(smoothingGroups) -1) + + # Add materials to Blender for later is in teh OBJ + for k in materialDict.keys(): + materialDict[k] = Material.New(k) + + # Make a list of all unused vert indicies that we can copy from - VERT_USED_LIST = [-1]*len(vertList) + VERT_USED_LIST = [0]*len(vertList) # Here we store a boolean list of which verts are used or not # no we know weather to add them to the current mesh @@ -313,270 +344,354 @@ def load_obj(file): # like blenders, we start with a dummy just like the vert. # -1 means unused, any other value refers to the local mesh index of the vert. - # objectName has a char in front of it that determins weather its a group or object. + # currentObjectName has a char in front of it that determins weather its a group or object. # We ignore it when naming the object. - objectName = 'omesh' # If we cant get one, use this + currentObjectName = 'unnamed_obj_0' # If we cant get one, use this + + meshDict = {} # The 3 variables below are stored in a tuple within this dict for each mesh + currentMesh = NMesh.GetRaw() # The NMesh representation of the OBJ group/Object + 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. + currentMaterialMeshMapping = {} # Used to store material indicies so we dont have to search the mesh for materials every time. + + # Every mesh has a null smooth group, this is used if there are no smooth groups in the OBJ file. + # and when for faces where no smooth group is used. + currentSmoothGroup = '(null)' # The Name of the current smooth group + + # For direct accsess to the Current Meshes, Current Smooth Groups- Used verts. + # This is of course context based and changes on the fly. + currentUsedVertListSmoothGroup = VERT_USED_LIST[:] + + # Set the initial '(null)' Smooth group, every mesh has one. + currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup + + + # 0:NMesh, 1:SmoothGroups[UsedVerts[0,0,0,0]], 2:materialMapping['matname':matIndexForThisNMesh] + meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping) + + + + - meshDict = {} - currentMesh = NMesh.GetRaw() - meshDict[objectName] = (currentMesh, VERT_USED_LIST[:]) # Mesh/meshDict[objectName][1] - currentMesh.verts.append(vertList[0]) - currentMesh.hasFaceUV(1) + + currentMesh.verts.append(vertList[0]) # So we can sync with OBJ indicies where 1 is the first item. + if len(uvMapList) > 1: + currentMesh.hasFaceUV(1) # Turn UV's on if we have ANY texture coords in this obj file. #==================================================================================# # Load all faces into objects, main loop # #==================================================================================# - lIdx = 0 - # Face and Object loading LOOP - while lIdx < len(fileLines): - l = fileLines[lIdx] - - # FACE - if l[0] == 'f': - # Make a face with the correct material. - f = NMesh.Face() + try: + lIdx = 0 + # Face and Object loading LOOP + while lIdx < len(fileLines): + l = fileLines[lIdx] - # Add material to mesh - if contextMeshMatIdx == -1: - tmpMatLs = currentMesh.materials - - if len(tmpMatLs) == MATLIMIT: - contextMeshMatIdx = 0 # Use first material - print 'material overflow, attempting to use > 16 materials. defaulting to first.' - else: - contextMeshMatIdx = len(tmpMatLs) - currentMesh.addMaterial(currentMat) - - # Set up vIdxLs : Verts - # Set up vtIdxLs : UV - # Start with a dummy objects so python accepts OBJs 1 is the first index. - vIdxLs = [] - vtIdxLs = [] - 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. - for v in l[1:]: - # OBJ files can have // or / to seperate vert/texVert/normal - # this is a bit of a pain but we must deal with it. - objVert = v.split('/') - - # Vert Index - OBJ supports negative index assignment (like python) + # FACE + if l[0] == 'f': + # Make a face with the correct material. - vIdxLs.append(int(objVert[0])) - if fHasUV: - # UV - if len(objVert) == 1: - #vtIdxLs.append(int(objVert[0])) # replace with below. - vtIdxLs.append(vIdxLs[-1]) # Sticky UV coords - elif objVert[1]: # != '' # Its possible that theres no texture vert just he vert and normal eg 1//2 - vtIdxLs.append(int(objVert[1])) # Seperate UV coords + # Add material to mesh + if contextMeshMatIdx == -1: + tmpMatLs = currentMesh.materials + + if len(tmpMatLs) == MATLIMIT: + contextMeshMatIdx = 0 # Use first material + print 'material overflow, attempting to use > 16 materials. defaulting to first.' else: - fHasUV = 0 - - # Dont add a UV to the face if its larger then the UV coord list - # The OBJ file would have to be corrupt or badly written for thi to happen - # but account for it anyway. - if len(vtIdxLs) > 0: - if vtIdxLs[-1] > len(uvMapList): + contextMeshMatIdx = len(tmpMatLs) + currentMaterialMeshMapping[currentMat.name] = contextMeshMatIdx + currentMesh.addMaterial(currentMat) + + # Set up vIdxLs : Verts + # Set up vtIdxLs : UV + # Start with a dummy objects so python accepts OBJs 1 is the first index. + vIdxLs = [] + vtIdxLs = [] + 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. + for v in l[1:]: + # OBJ files can have // or / to seperate vert/texVert/normal + # this is a bit of a pain but we must deal with it. + objVert = v.split('/') + + # Vert Index - OBJ supports negative index assignment (like python) + + vIdxLs.append(int(objVert[0])) + if fHasUV: + # UV + if len(objVert) == 1: + #vtIdxLs.append(int(objVert[0])) # replace with below. + vtIdxLs.append(vIdxLs[-1]) # Sticky UV coords + elif objVert[1]: # != '' # Its possible that theres no texture vert just he vert and normal eg 1//2 + vtIdxLs.append(int(objVert[1])) # Seperate UV coords + else: fHasUV = 0 - print 'badly written OBJ file, invalid references to UV Texture coordinates.' - - # Quads only, we could import quads using the method below but it polite to import a quad as a quad. - if len(vIdxLs) == 4: - for i in quadList: # quadList == [0,1,2,3] - if meshDict[objectName][1][vIdxLs[i]] == -1: - currentMesh.verts.append(vertList[vIdxLs[i]]) - f.v.append(currentMesh.verts[-1]) - meshDict[objectName][1][vIdxLs[i]] = len(currentMesh.verts)-1 - else: - f.v.append(currentMesh.verts[meshDict[objectName][1][vIdxLs[i]]]) + + # Dont add a UV to the face if its larger then the UV coord list + # The OBJ file would have to be corrupt or badly written for thi to happen + # but account for it anyway. + if len(vtIdxLs) > 0: + if vtIdxLs[-1] > len(uvMapList): + fHasUV = 0 + print 'badly written OBJ file, invalid references to UV Texture coordinates.' - # UV MAPPING - if fHasUV: - f.uv.extend([uvMapList[ vtIdxLs[0] ],uvMapList[ vtIdxLs[1] ],uvMapList[ vtIdxLs[2] ],uvMapList[ vtIdxLs[3] ]]) - #for i in [0,1,2,3]: - # f.uv.append( uvMapList[ vtIdxLs[i] ] ) - - if f.v > 0: - f.mat = contextMeshMatIdx - if currentImg != NULL_IMG: - f.image = currentImg - else: - f.mode &= TEX_OFF_FLAG - currentMesh.faces.append(f) # move the face onto the mesh - if len(f) > 0: - f.smooth = currentSmooth - - elif len(vIdxLs) >= 3: # This handles tri's and fans - for i in range(len(vIdxLs)-2): + # Quads only, we could import quads using the method below but it polite to import a quad as a quad. + if len(vIdxLs) == 4: + ''' f = NMesh.Face() + for i in quadList: # quadList == [0,1,2,3] + if currentUsedVertListSmoothGroup[vIdxLs[i]] == 0: + v = vertList[vIdxLs[i]] + currentMesh.verts.append(v) + f.append(v) + currentUsedVertListSmoothGroup[vIdxLs[i]] = len(currentMesh.verts)-1 + else: + f.v.append(currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i]]]) + ''' + if currentUsedVertListSmoothGroup[vIdxLs[0]] == 0: + faceQuadVList[0] = vertList[vIdxLs[0]] + currentUsedVertListSmoothGroup[vIdxLs[0]] = len(currentMesh.verts) + else: + faceQuadVList[0] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[0]]] - for ii in [0, i+1, i+2]: + if currentUsedVertListSmoothGroup[vIdxLs[1]] == 0: + faceQuadVList[1] = vertList[vIdxLs[1]] + currentUsedVertListSmoothGroup[vIdxLs[1]] = len(currentMesh.verts)+1 + else: + faceQuadVList[1] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[1]]] - if meshDict[objectName][1][vIdxLs[ii]] == -1: - currentMesh.verts.append(vertList[vIdxLs[ii]]) - f.v.append(currentMesh.verts[-1]) - meshDict[objectName][1][vIdxLs[ii]] = len(currentMesh.verts)-1 - else: - f.v.append(currentMesh.verts[meshDict[objectName][1][vIdxLs[ii]]]) - + if currentUsedVertListSmoothGroup[vIdxLs[2]] == 0: + faceQuadVList[2] = vertList[vIdxLs[2]] + currentUsedVertListSmoothGroup[vIdxLs[2]] = len(currentMesh.verts)+2 + else: + faceQuadVList[2] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[2]]] + + if currentUsedVertListSmoothGroup[vIdxLs[3]] == 0: + faceQuadVList[3] = vertList[vIdxLs[3]] + currentUsedVertListSmoothGroup[vIdxLs[3]] = len(currentMesh.verts)+3 + else: + faceQuadVList[3] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[3]]] + + currentMesh.verts.extend(faceQuadVList) + f = NMesh.Face(faceQuadVList) + # UV MAPPING if fHasUV: - f.uv.extend([uvMapList[ vtIdxLs[0] ], uvMapList[ vtIdxLs[i+1] ], uvMapList[ vtIdxLs[i+2] ]]) - - if f.v > 0: - f.mat = contextMeshMatIdx - if currentImg != NULL_IMG: + f.uv = [uvMapList[ vtIdxLs[0] ],uvMapList[ vtIdxLs[1] ],uvMapList[ vtIdxLs[2] ],uvMapList[ vtIdxLs[3] ]] + if currentImg: f.image = currentImg else: - f.mode |= TEX_OFF_FLAG + f.mode &= TEX_OFF_FLAG + + f.mat = contextMeshMatIdx + f.smooth = currentSmooth + currentMesh.faces.append(f) # move the face onto the mesh + + elif len(vIdxLs) >= 3: # This handles tri's and fans + for i in range(len(vIdxLs)-2): + ''' + f = NMesh.Face() + for ii in [0, i+1, i+2]: + if currentUsedVertListSmoothGroup[vIdxLs[ii]] == 0: + v = vertList[vIdxLs[ii]] + currentMesh.verts.append(v) + f.append(v) + currentUsedVertListSmoothGroup[vIdxLs[ii]] = len(currentMesh.verts)-1 + else: + f.v.append(currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[ii]]]) + ''' + + + if currentUsedVertListSmoothGroup[vIdxLs[0]] == 0: + faceTriVList[0] = vertList[vIdxLs[0]] + currentUsedVertListSmoothGroup[vIdxLs[0]] = len(currentMesh.verts) + else: + faceTriVList[0] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[0]]] + + if currentUsedVertListSmoothGroup[vIdxLs[i+1]] == 0: + faceTriVList[1] = vertList[vIdxLs[i+1]] + currentUsedVertListSmoothGroup[vIdxLs[i+1]] = len(currentMesh.verts)+1 + else: + faceTriVList[1] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i+1]]] + + if currentUsedVertListSmoothGroup[vIdxLs[i+2]] == 0: + faceTriVList[2] = vertList[vIdxLs[i+2]] + currentUsedVertListSmoothGroup[vIdxLs[i+2]] = len(currentMesh.verts)+2 + else: + faceTriVList[2] = currentMesh.verts[currentUsedVertListSmoothGroup[vIdxLs[i+2]]] + + currentMesh.verts.extend(faceTriVList) + f = NMesh.Face(faceTriVList) + + + # UV MAPPING + if fHasUV: + f.uv = [uvMapList[vtIdxLs[0]], uvMapList[vtIdxLs[i+1]], uvMapList[vtIdxLs[i+2]]] + if currentImg: + f.image = currentImg + else: + f.mode &= TEX_OFF_FLAG + + f.mat = contextMeshMatIdx + f.smooth = currentSmooth currentMesh.faces.append(f) # move the face onto the mesh - if len(f) > 0: - f.smooth = currentSmooth - - - # FACE SMOOTHING - elif l[0] == 's': - # No value? then turn on. - if len(l) == 1: - currentSmooth = 1 - else: - if l[1] == 'off': - currentSmooth = 0 - else: - currentSmooth = 1 - - # OBJECT / GROUP - elif l[0] == 'o' or l[0] == 'g': - # This makes sure that if an object and a group have the same name then - # they are not put into the same object. - - # Only make a new group.object name if the verts in the existing object have been used, this is obscure - # but some files face groups seperating verts and faces which results in silly things. (no groups have names.) - if len(l) > 1: - objectName = '_'.join(l[1:]) - else: # No name given - # Make a new empty name - if l[0] == 'g': # Make a blank group name - objectName = 'unnamed_grp_%d' % currentUnnamedGroupIdx - currentUnnamedGroupIdx +=1 - else: # is an object. - objectName = 'unnamed_ob_%d' % currentUnnamedObjectIdx - currentUnnamedObjectIdx +=1 - - - # If we havnt written to this mesh before then do so. - # if we have then we'll just keep appending to it, this is required for soem files. - # If we are new, or we are not yet in the list of added meshes - # then make us new mesh. - if len(l) == 1 or objectName not in meshDict.keys(): - currentMesh = NMesh.GetRaw() - meshDict[objectName] = (currentMesh, VERT_USED_LIST[:]) - currentMesh.hasFaceUV(1) - currentMesh.verts.append( vertList[0] ) - contextMeshMatIdx = -1 + # FACE SMOOTHING + elif l[0] == 's': + # No value? then turn on. + if len(l) == 1: + currentSmooth = True + currentSmoothGroup = '(null)' + try: + currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup] + except KeyError: + currentUsedVertListSmoothGroup = VERT_USED_LIST[:] + currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup + + else: + if l[1] == 'off': + currentSmooth = False + currentSmoothGroup = '(null)' + # We all have a null group so dont need to try + currentUsedVertListSmoothGroup = currentUsedVertList['(null)'] + else: + currentSmooth = True + currentSmoothGroup = '_'.join(l[1:]) + + # OBJECT / GROUP + elif l[0] == 'o' or l[0] == 'g': + + # Forget about the current image + currentImg = None + + # This makes sure that if an object and a group have the same name then + # they are not put into the same object. + + # Only make a new group.object name if the verts in the existing object have been used, this is obscure + # but some files face groups seperating verts and faces which results in silly things. (no groups have names.) + if len(l) > 1: + currentObjectName = '_'.join(l[1:]) + else: # No name given + # Make a new empty name + if l[0] == 'g': # Make a blank group name + currentObjectName = 'unnamed_grp_%d' % currentUnnamedGroupIdx + currentUnnamedGroupIdx +=1 + else: # is an object. + currentObjectName = 'unnamed_ob_%d' % currentUnnamedObjectIdx + currentUnnamedObjectIdx +=1 - else: - # Since we have this in Blender then we will check if the current Mesh has the material. - # set the contextMeshMatIdx to the meshs index but only if we have it. - currentMesh = meshDict[objectName] - contextMeshMatIdx = getMeshMaterialIndex(currentMesh, currentMat) - - - - # MATERIAL - elif l[0] == 'usemtl': - if len(l) == 1 or l[1] == NULL_MAT: - #~ currentMat = getMat(NULL_MAT) - newMatName = NULL_MAT - currentMat = nullMat - else: - #~ currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces - newMatName = '_'.join(l[1:]) + # If we havnt written to this mesh before then do so. + # if we have then we'll just keep appending to it, this is required for soem files. - try: # Add to material list if not there - currentMat = materiaDict[newMatName] - newMatName = currentMat.name # Make sure we are up to date, Blender might have incremented the name. + # If we are new, or we are not yet in the list of added meshes + # then make us new mesh. + if len(l) == 1 or currentObjectName not in meshDict.keys(): + currentMesh = NMesh.GetRaw() - # Since we have this in Blender then we will check if the current Mesh has the material. - matIdx = 0 - tmpMeshMaterials = currentMesh.materials - while matIdx < len(tmpMeshMaterials): - if tmpMeshMaterials[matIdx].name == newMatName: - contextMeshMatIdx = matIdx # The current mat index. - break - matIdx+=1 + currentUsedVertList = {} + + # Sg is a string + currentSmoothGroup = '(null)' + currentUsedVertListSmoothGroup = VERT_USED_LIST[:] + currentUsedVertList[currentSmoothGroup] = currentUsedVertListSmoothGroup + currentMaterialMeshMapping = {} + + meshDict[currentObjectName] = (currentMesh, currentUsedVertList, currentMaterialMeshMapping) + currentMesh.hasFaceUV(1) + currentMesh.verts.append( vertList[0] ) + contextMeshMatIdx = -1 + else: + # Since we have this in Blender then we will check if the current Mesh has the material. + # set the contextMeshMatIdx to the meshs index but only if we have it. + currentMesh, currentUsedVertList, currentMaterialMeshMapping = meshDict[currentObjectName] + #getMeshMaterialIndex(currentMesh, currentMat) + try: + contextMeshMatIdx = currentMaterialMeshMapping[currentMat.name] #getMeshMaterialIndex(currentMesh, currentMat) + except KeyError: + contextMeshMatIdx -1 - except KeyError: # Not added yet, add now. - currentMat = Material.New(newMatName) - materiaDict[newMatName] = currentMat - contextMeshMatIdx = -1 # Mesh cant possibly have the material. + # For new meshes switch smoothing groups to null + currentSmoothGroup = '(null)' + currentUsedVertListSmoothGroup = currentUsedVertList[currentSmoothGroup] - # IMAGE - elif l[0] == 'usemat' or l[0] == 'usemap': - if len(l) == 1 or l[1] == '(null)' or l[1] == 'off': - currentImg = NULL_IMG - else: - # Load an image. - newImgName = stripPath(' '.join(l[1:])) - - try: - # Assume its alredy set in the dict (may or maynot be loaded) - currentImg = imageDict[newImgName] + # MATERIAL + elif l[0] == 'usemtl': + if len(l) == 1 or l[1] == NULL_MAT: + currentMat = nullMat # We know we have a null mat. + else: + currentMat = materialDict['_'.join(l[1:])] + try: + contextMeshMatIdx = currentMaterialMeshMapping[currentMat.name] + except KeyError: + contextMeshMatIdx = -1 #getMeshMaterialIndex(currentMesh, currentMat) - except KeyError: # Not in dict, add for first time. - try: # Image has not been added, Try and load the image - currentImg = Image.Load( '%s%s' % (DIR, newImgName) ) # Use join in case of spaces - imageDict[newImgName] = currentImg - - except IOError: # Cant load, just set blank. - imageDict[newImgName] = NULL_IMG - currentImg = NULL_IMG - - # MATERIAL FILE - elif l[0] == 'mtllib': - mtl_fileName = ' '.join(l[1:]) # SHOULD SUPPORT MULTIPLE MTL? + # IMAGE + elif l[0] == 'usemat' or l[0] == 'usemap': + if len(l) == 1 or l[1] == '(null)' or l[1] == 'off': + currentImg = None + else: + # Load an image. + newImgName = stripPath(' '.join(l[1:])) # Use space since its a file name. + + try: + # Assume its alredy set in the dict (may or maynot be loaded) + currentImg = imageDict[newImgName] + + except KeyError: # Not in dict, add for first time. + try: # Image has not been added, Try and load the image + currentImg = Image.Load( '%s%s' % (DIR, newImgName) ) # Use join in case of spaces + imageDict[newImgName] = currentImg + + except IOError: # Cant load, just set blank. + imageDict[newImgName] = None + currentImg = None + + # MATERIAL FILE + elif l[0] == 'mtllib': + mtl_fileName = ' '.join(l[1:]) # SHOULD SUPPORT MULTIPLE MTL? + lIdx+=1 - lIdx+=1 - - - #==============================================# - # Write all meshs in the dictionary # - #==============================================# - for ob in Scene.GetCurrent().getChildren(): # Deselect all - ob.sel = 0 - - - # Applies material properties to materials alredy on the mesh as well as Textures. - if mtl_fileName != '': - load_mtl(DIR, mtl_fileName, meshDict) - - - importedObjects = [] - for mk in meshDict.keys(): - meshDict[mk][0].verts.pop(0) + # Applies material properties to materials alredy on the mesh as well as Textures. + if mtl_fileName: + load_mtl(DIR, mtl_fileName, meshDict, materialDict) - # Ignore no vert meshes. - if not meshDict[mk][0].verts: - continue - name = getUniqueName(mk) - ob = NMesh.PutRaw(meshDict[mk][0], name) - ob.name = name + importedObjects = [] + for mk in meshDict.keys(): + meshDict[mk][0].verts.pop(0) + + # Ignore no vert meshes. + if not meshDict[mk][0].verts: + continue + + name = getUniqueName(mk) + ob = NMesh.PutRaw(meshDict[mk][0], name) + ob.name = name + + importedObjects.append(ob) - importedObjects.append(ob) + # Select all imported objects. + for ob in importedObjects: + ob.sel = 1 - # Select all imported objects. - for ob in importedObjects: - ob.sel = 1 + print "obj import time: ", sys.time() - time1 + + except: + print Draw.PupMenu(ABORT_MENU) + return - print "obj import time: ", sys.time() - time1 -Window.FileSelector(load_obj, 'Import Wavefront OBJ') +def load_obj_callback(file): + # Try/Fails should realy account for these, but if somthing realy bad happens then Popup error. + try: + load_obj(file) + except: + print Draw.PupMenu(ABORT_MENU) +Window.FileSelector(load_obj_callback, 'Import Wavefront OBJ') # For testing compatibility ''' @@ -588,6 +703,9 @@ for obj in os.listdir('/obj/'): newScn = Scene.New(obj) newScn.makeCurrent() load_obj('/obj/' + obj) + +print "TOTAL IMPORT TIME: ", sys.time() - TIME ''' -#print "TOTAL IMPORT TIME: ", sys.time() - TIME -#load_obj('/obj/her.obj') +#load_obj('/obj/foot_bones.obj') +#load_obj('/obj/mba1.obj') +#load_obj('/obj/PixZSphere50.OBJ') |