diff options
author | Jiri Hnidek <jiri.hnidek@tul.cz> | 2004-06-15 00:51:09 +0400 |
---|---|---|
committer | Jiri Hnidek <jiri.hnidek@tul.cz> | 2004-06-15 00:51:09 +0400 |
commit | 317e067ecb91c2127c12cee3808a5bb2402b82e4 (patch) | |
tree | 6a487191cad5b1d45fe494ca2b5023e1dec69f1b /release | |
parent | f24be4c6ade18276a1210afac44c66b9329afe20 (diff) |
- Campbell Barton's (AKA Ideasman) obj importer script (some split improvements)
- I added support of material and texture import (.mtl files) Textures are assigned to faces and materials too.
Diffstat (limited to 'release')
-rw-r--r-- | release/scripts/obj_import.py | 418 |
1 files changed, 247 insertions, 171 deletions
diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py index 412a5d285a9..41daba823f8 100644 --- a/release/scripts/obj_import.py +++ b/release/scripts/obj_import.py @@ -1,176 +1,245 @@ -#!BPY - -""" -Name: 'Wavefront (.obj)...' -Blender: 232 -Group: 'Import' -Tooltip: 'Load a Wavefront OBJ File' - """ +#!BPY + +""" +Name: 'Wavefront (.obj)...' +Blender: 232 +Group: 'Import' +Tooltip: 'Load a Wavefront OBJ File' +""" # $Id$ # -# -------------------------------------------------------------------------- -# OBJ Import v0.9 by Campbell Barton (AKA Ideasman) -# -------------------------------------------------------------------------- -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# ***** END GPL LICENCE BLOCK ***** -# -------------------------------------------------------------------------- - -WHITESPACE = [' ', '\n', '\r', '\t', '\f', '\v'] # used for the split function. -NULL_MAT = '(null)' # Name for mesh's that have no mat set. - -MATLIMIT = 16 - -#==============================================# -# Strips the slashes from the back of a string # -#==============================================# -def stripPath(path): - for CH in range(len(path), 0, -1): - if path[CH-1] == "/" or path[CH-1] == "\\": - path = path[CH:] - break - return path - -#====================================================# -# Strips the prefix off the name before writing # -#====================================================# -def stripName(name): # name is a string - prefixDelimiter = '.' - return name[ : name.find(prefixDelimiter) ] - -#================================================================# -# Replace module deps 'string' for join and split # # -# - Split splits a string into a list, and join does the reverse # -#================================================================# -def split(splitString, WHITESPACE): - splitList = [] - charIndex = 0 - while charIndex < len(splitString): - # Skip white space - while charIndex < len(splitString): - if splitString[charIndex] in WHITESPACE: - charIndex += 1 - else: - break - - # Gather text that is not white space and append to splitList - startWordCharIndex = charIndex - while charIndex < len(splitString): - if splitString[charIndex] in WHITESPACE: break - charIndex += 1 - - # Now we have the first and last chars we can append the word to the list - if charIndex != startWordCharIndex: - splitList.append(splitString[startWordCharIndex:charIndex]) - - return splitList - -#===============================# -# Join list items into a string # -#===============================# -def join(joinList): - joinedString = "" - for listItem in joinList: - joinedString = joinedString + ' ' + str(listItem) - - # Remove the first space - joinedString = joinedString[1:] - return joinedString - - -from Blender import * - -def load_obj(file): - # This gets a mat or creates one of the requested name if none exist. - def getMat(matName): - # Make a new mat - try: - return Material.Get(matName) - except: - return Material.New(matName) - - def applyMat(mesh, f, mat): - # Check weather the 16 mat limit has been met. - if len( mesh.materials ) >= MATLIMIT: - print 'Warning, max material limit reached, using an existing material' - return mesh, f +# -------------------------------------------------------------------------- +# OBJ Import v0.9 by Campbell Barton (AKA Ideasman) +# -------------------------------------------------------------------------- +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# ***** END GPL LICENCE BLOCK ***** +# -------------------------------------------------------------------------- + +NULL_MAT = '(null)' # Name for mesh's that have no mat set. + +MATLIMIT = 16 + +DIR = '' + +#==============================================# +# Return directory, where is file # +#==============================================# +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 + +#==============================================# +# Strips the slashes from the back of a string # +#==============================================# +def stripPath(path): + for CH in range(len(path), 0, -1): + if path[CH-1] == "/" or path[CH-1] == "\\": + path = path[CH:] + break + return path + +#====================================================# +# Strips the prefix off the name before writing # + +#====================================================# +def stripName(name): # name is a string + prefixDelimiter = '.' + return name[ : name.find(prefixDelimiter) ] + +#===============================# +# Join list items into a string # +#===============================# +def join(joinList): + joinedString = "" + for listItem in joinList: + joinedString = joinedString + ' ' + str(listItem) + + # Remove the first space + joinedString = joinedString[1:] + return joinedString + + +from Blender import * + +#==================================================================================# +# This gets a mat or creates one of the requested name if none exist. # +#==================================================================================# +def getMat(matName): + # Make a new mat + try: + return Material.Get(matName) + except: + return Material.New(matName) + +#==================================================================================# +# This function sets textures defined in .mtl file # +#==================================================================================# +def load_image(mat, img_fileName, type, mesh): + try: + image = Image.Load(img_fileName) + except: + print "unable to open", img_fileName + return + + texture = Texture.New(type) + texture.setType('Image') + texture.image = image + + # adds textures to faces (Textured/Alt-Z mode) + for f in mesh.faces: + if mesh.materials[f.mat].name == mat.name: + f.image = image + + # adds textures for materials (rendering) + if type == 'Ka': + mat.setTexture(0, texture, Texture.TexCo.UV, Texture.MapTo.CMIR) + if type == 'Kd': + mat.setTexture(1, texture, Texture.TexCo.UV, Texture.MapTo.COL) + if type == 'Ks': + mat.setTexture(2, texture, Texture.TexCo.UV, Texture.MapTo.SPEC) + +#==================================================================================# +# This function loads materials from .mtl file (have to be defined in obj file) # +#==================================================================================# +def load_mtl(dir, mtl_file, mesh): + mtl_fileName = dir + mtl_file + try: + fileLines= open(mtl_fileName, 'r').readlines() + except: + print "unable to open", 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:])) + elif l[0] == 'Ka': + currentMat.setMirCol(eval(l[1]), eval(l[2]), eval(l[3])) + elif l[0] == 'Kd': + currentMat.setRGBCol(eval(l[1]), eval(l[2]), eval(l[3])) + elif l[0] == 'Ks': + currentMat.setSpecCol(eval(l[1]), eval(l[2]), eval(l[3])) + elif l[0] == 'Ns': + currentMat.setEmit(eval(l[1])/100.0) + elif l[0] == 'd': + currentMat.setAlpha(eval(l[1])) + elif l[0] == 'Tr': + currentMat.setAlpha(eval(l[1])) + elif l[0] == 'map_Ka': + img_fileName = dir + l[1] + load_image(currentMat, img_fileName, 'Ka', mesh) + elif l[0] == 'map_Kd': + img_fileName = dir + l[1] + load_image(currentMat, img_fileName, 'Kd', mesh) + elif l[0] == 'map_Ks': + img_fileName = dir + l[1] + load_image(currentMat, img_fileName, 'Ks', mesh) + + lIdx+=1 + +#==================================================================================# +# This loads data from .obj file # +#==================================================================================# +def load_obj(file): + def applyMat(mesh, f, mat): + # Check weather the 16 mat limit has been met. + if len( mesh.materials ) >= MATLIMIT: + print 'Warning, max material limit reached, using an existing material' + return mesh, f - mIdx = 0 - for m in mesh.materials: - if m.getName() == mat.getName(): - break - mIdx+=1 + mIdx = 0 + for m in mesh.materials: + if m.getName() == mat.getName(): + break + mIdx+=1 - if mIdx == len(mesh.materials): - mesh.addMaterial(mat) + if mIdx == len(mesh.materials): + mesh.addMaterial(mat) - f.mat = mIdx - return mesh, f - - # Get the file name with no path or .obj - fileName = stripName( stripPath(file) ) - - fileLines = open(file, 'r').readlines() - - mesh = NMesh.GetRaw() # new empty mesh - - objectName = 'mesh' # If we cant get one, use this - - uvMapList = [] # store tuple uv pairs here - - nullMat = getMat(NULL_MAT) - - currentMat = nullMat # Use this mat. - - # Main loop - lIdx = 0 - while lIdx < len(fileLines): - l = split(fileLines[lIdx], WHITESPACE) + f.mat = mIdx + return mesh, f + + # Get the file name with no path or .obj + fileName = stripName( stripPath(file) ) + + mtl_fileName = '' + + DIR = pathName(file, stripPath(file)) + + fileLines = open(file, 'r').readlines() + + mesh = NMesh.GetRaw() # new empty mesh + + objectName = 'mesh' # If we cant get one, use this + + uvMapList = [] # store tuple uv pairs here + + nullMat = getMat(NULL_MAT) + + currentMat = nullMat # Use this mat. + + # Main loop + lIdx = 0 + while lIdx < len(fileLines): + l = fileLines[lIdx].split() - # Detect a line that will be idnored - if len(l) == 0: - pass - elif l[0] == '#' or len(l) == 0: - pass - # VERTEX - elif l[0] == 'v': - # This is a new vert, make a new mesh - mesh.verts.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) ) - + # Detect a line that will be idnored + if len(l) == 0: + pass + elif l[0] == '#' or len(l) == 0: + pass + # VERTEX + elif l[0] == 'v': + # This is a new vert, make a new mesh + mesh.verts.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) ) + elif l[0] == 'vn': pass - + elif l[0] == 'vt': # This is a new vert, make a new mesh uvMapList.append( (eval(l[1]), eval(l[2])) ) - - elif l[0] == 'f': - - # Make a face with the correct material. - f = NMesh.Face() - mesh, f = applyMat(mesh, f, currentMat) - - # Set up vIdxLs : Verts - # Set up vtIdxLs : UV + + elif l[0] == 'f': + + # Make a face with the correct material. + f = NMesh.Face() + mesh, f = applyMat(mesh, f, currentMat) + + # Set up vIdxLs : Verts + # Set up vtIdxLs : UV vIdxLs = [] vtIdxLs = [] - for v in l[1:]: - objVert = split( v, ['/'] ) + for v in l[1:]: + #objVert = split( v, ['/'] ) + objVert = v.split('/', -1) # VERT INDEX vIdxLs.append(eval(objVert[0]) -1) @@ -179,8 +248,8 @@ def load_obj(file): vtIdxLs.append(eval(objVert[0]) -1) # Sticky UV coords else: vtIdxLs.append(eval(objVert[1]) -1) # Seperate UV coords - - # Quads only, we could import quads using the method below but it polite to import a quad as a quad.f + + # Quads only, we could import quads using the method below but it polite to import a quad as a quad.f if len(vIdxLs) == 4: f.v.append(mesh.verts[vIdxLs[0]]) f.v.append(mesh.verts[vIdxLs[1]]) @@ -213,7 +282,7 @@ def load_obj(file): f.uv.append( uvMapList[ vtIdxLs[i+1] ] ) if vtIdxLs[2] < len(uvMapList): f.uv.append( uvMapList[ vtIdxLs[i+2] ] ) - + mesh.faces.append(f) # move the face onto the mesh # is o the only vert/face delimeter? @@ -224,11 +293,11 @@ def load_obj(file): NMesh.PutRaw(mesh, fileName + '_' + objectName) # Make new mesh mesh = NMesh.GetRaw() - + # New mesh name objectName = join(l[1:]) # Use join in case of spaces - - # New texture list + + # New texture list uvMapList = [] elif l[0] == 'usemtl': @@ -236,12 +305,19 @@ def load_obj(file): currentMat = getMat(NULL_MAT) else: currentMat = getMat(join(l[1:])) # Use join in case of spaces + + elif l[0] == 'mtllib': + mtl_fileName = l[1] - lIdx+=1 + lIdx+=1 - # We need to do this to put the last object. - # All other objects will be put alredy - if len(mesh.verts) > 0: - NMesh.PutRaw(mesh, fileName + '_' + objectName) + # Some material stuff + if mtl_fileName != '': + load_mtl(DIR, mtl_fileName, mesh) + + # We need to do this to put the last object. + # All other objects will be put alredy + if len(mesh.verts) > 0: + NMesh.PutRaw(mesh, fileName + '_' + objectName) -Window.FileSelector(load_obj, 'Import OBJ') +Window.FileSelector(load_obj, 'Import OBJ') |