Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/obj_import.py')
-rw-r--r--release/scripts/obj_import.py570
1 files changed, 304 insertions, 266 deletions
diff --git a/release/scripts/obj_import.py b/release/scripts/obj_import.py
index e19c52b7be1..236b9705d33 100644
--- a/release/scripts/obj_import.py
+++ b/release/scripts/obj_import.py
@@ -53,19 +53,18 @@ def pathName(path,name):
# 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
+ 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) ]
+ prefixDelimiter = '.'
+ return name[ : name.find(prefixDelimiter) ]
from Blender import *
@@ -74,27 +73,27 @@ 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)
+ # Make a new mat
+ try:
+ return Material.Get(matName)
+ except:
+ return Material.New(matName)
#==================================================================================#
# This function sets textures defined in .mtl file #
#==================================================================================#
def getImg(img_fileName):
- for i in Image.Get():
- if i.filename == img_fileName:
- return i
+ for i in Image.Get():
+ if i.filename == img_fileName:
+ return i
- # if we are this far it means the image hasnt been loaded.
- try:
- return Image.Load(img_fileName)
- except:
- print "unable to open", img_fileName
- return
+ # if we are this far it means the image hasnt been loaded.
+ try:
+ return Image.Load(img_fileName)
+ except:
+ print "unable to open", img_fileName
+ return
@@ -102,270 +101,309 @@ def getImg(img_fileName):
# This function sets textures defined in .mtl file #
#==================================================================================#
def load_mat_image(mat, img_fileName, type, mesh):
- try:
- image = Image.Load(img_fileName)
- except:
- print "unable to open", img_fileName
- return
+ try:
+ image = Image.Load(img_fileName)
+ except:
+ print "unable to open", img_fileName
+ return
- texture = Texture.New(type)
- texture.setType('Image')
- texture.image = image
+ texture = Texture.New(type)
+ texture.setType('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':
- for f in mesh.faces:
- if mesh.materials[f.mat].name == mat.name:
-
- # the inline usemat command overides the material Image
- if not f.image:
- f.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':
+ for f in mesh.faces:
+ if mesh.materials[f.mat].name == mat.name:
+
+ # the inline usemat command overides the material Image
+ if not f.image:
+ 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)
+ # 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
+ # Remove ./
+ if mtl_file[:2] == './':
+ mtl_file= mtl_file[2:]
+
+ 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()
+ 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.setHardness( int((eval(l[1])*0.51)) )
- 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_mat_image(currentMat, img_fileName, 'Ka', mesh)
- elif l[0] == 'map_Ks':
- img_fileName = dir + l[1]
- load_mat_image(currentMat, img_fileName, 'Ks', mesh)
- elif l[0] == 'map_Kd':
- img_fileName = dir + l[1]
- load_mat_image(currentMat, img_fileName, 'Kd', mesh)
- lIdx+=1
+ # 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.setHardness( int((eval(l[1])*0.51)) )
+ 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_mat_image(currentMat, img_fileName, 'Ka', mesh)
+ elif l[0] == 'map_Ks':
+ img_fileName = dir + l[1]
+ load_mat_image(currentMat, img_fileName, 'Ks', mesh)
+ elif l[0] == 'map_Kd':
+ img_fileName = dir + l[1]
+ load_mat_image(currentMat, img_fileName, 'Kd', 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
-
- if mIdx == len(mesh.materials):
- mesh.addMaterial(mat)
-
- f.mat = mIdx
+ 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
-
- # 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.
- currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.
+
+ mIdx = 0
+ for m in mesh.materials:
+ if m.getName() == mat.getName():
+ break
+ mIdx+=1
+
+ 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) )
+
+ mtl_fileName = ''
+
+ DIR = pathName(file, stripPath(file))
- smooth = 0
+ fileLines = open(file, 'r').readlines()
+
+ mesh = NMesh.GetRaw() # new empty mesh
+
+ objectName = 'mesh' # If we cant get one, use this
+
+ 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)] # store tuple uv pairs here
+
+ # Here we store a boolean list of which verts are used or not
+ # no we know weather to add them to the current mesh
+ # This is an issue with global vertex indicies being translated to per mesh indicies
+ # 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.
+ usedList = [-1]
+
+ nullMat = getMat(NULL_MAT)
+
+ currentMat = nullMat # Use this mat.
+ currentImg = NULL_IMG # Null image is a string, otherwise this should be set to an image object.
- # 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]) ) )
-
- 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
- vIdxLs = []
- vtIdxLs = []
- 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.
- # Well try // first and if that has a len of 1 then we'll try /
- objVert = v.split('//', -1)
- if len(objVert) == 1:
- objVert = objVert[0].split('/', -1)
-
- # VERT INDEX
- vIdxLs.append(eval(objVert[0]) -1)
- # UV
- if len(objVert) == 1:
- 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
- if len(vIdxLs) == 4:
- f.v.append(mesh.verts[vIdxLs[0]])
- f.v.append(mesh.verts[vIdxLs[1]])
- f.v.append(mesh.verts[vIdxLs[2]])
- f.v.append(mesh.verts[vIdxLs[3]])
- # SMOTH FACE
- f.smooth = smooth
- # UV MAPPING
- if uvMapList:
- if vtIdxLs[0] < len(uvMapList):
- f.uv.append( uvMapList[ vtIdxLs[0] ] )
- if vtIdxLs[1] < len(uvMapList):
- f.uv.append( uvMapList[ vtIdxLs[1] ] )
- if vtIdxLs[2] < len(uvMapList):
- f.uv.append( uvMapList[ vtIdxLs[2] ] )
- if vtIdxLs[3] < len(uvMapList):
- f.uv.append( uvMapList[ vtIdxLs[3] ] )
-
- mesh.faces.append(f) # move the face onto the mesh
- # Apply the current image to the face
- if currentImg != NULL_IMG:
- mesh.faces[-1].image = currentImg
+ # 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
+ vertList.append( NMesh.Vert(eval(l[1]), eval(l[2]), eval(l[3]) ) )
+ usedList.append(-1) # Ad the moment this vert is not used by any mesh.
+
+ 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 len(vIdxLs) >= 3: # This handles tri's and fans
- for i in range(len(vIdxLs)-2):
- f = NMesh.Face()
- mesh, f = applyMat(mesh, f, currentMat)
- f.v.append(mesh.verts[vIdxLs[0]])
- f.v.append(mesh.verts[vIdxLs[i+1]])
- f.v.append(mesh.verts[vIdxLs[i+2]])
- # SMOTH FACE
- f.smooth = smooth
- # UV MAPPING
- if uvMapList:
- if vtIdxLs[0] < len(uvMapList):
- f.uv.append( uvMapList[ vtIdxLs[0] ] )
- if vtIdxLs[1] < len(uvMapList):
- 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
- # Apply the current image to the face
- if currentImg != NULL_IMG:
- mesh.faces[-1].image = currentImg
-
-
- # is o the only vert/face delimeter?
- # if not we could be screwed.
- elif l[0] == 'o':
- # Some material stuff
- if mtl_fileName != '':
- load_mtl(DIR, mtl_fileName, mesh)
+ 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
+ # 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('/', -1)
- # Make sure the objects is worth puttong
- if len(mesh.verts) > 0:
- 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
- uvMapList = []
-
- # setting smooth surface on or off
- elif l[0] == 's':
- if l[1] == 'off':
- smooth = 0
- else:
- smooth = 1
-
- elif l[0] == 'usemtl':
- if l[1] == '(null)':
- currentMat = getMat(NULL_MAT)
- else:
- currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces
+ # Vert Index - OBJ supports negative index assignment (like python)
+
+ vIdxLs.append(eval(objVert[0]))
+ if fHasUV:
+ # UV
+ if len(objVert) == 1:
+ vtIdxLs.append(eval(objVert[0])) # Sticky UV coords
+ elif objVert[1] != '': # Its possible that theres no texture vert just he vert and normal eg 1//2
+ vtIdxLs.append(eval(objVert[1])) # Seperate UV coords
+ 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 vtIdxLs[-1] > len(uvMapList):
+ 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 [0,1,2,3]:
+ if usedList[vIdxLs[i]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i]]])
+
+ # UV MAPPING
+ if fHasUV:
+ for i in [0,1,2,3]:
+ f.uv.append( uvMapList[ vtIdxLs[i] ] )
+ mesh.faces.append(f) # move the face onto the mesh
+ # Apply the current image to the face
+ if currentImg != NULL_IMG:
+ mesh.faces[-1].image = currentImg
+
+ elif len(vIdxLs) >= 3: # This handles tri's and fans
+ for i in range(len(vIdxLs)-2):
+ f = NMesh.Face()
+ mesh, f = applyMat(mesh, f, currentMat)
+
+ if usedList[vIdxLs[0]] == -1:
+ mesh.verts.append(vertList[vIdxLs[0]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[0]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[0]]])
+
+ if usedList[vIdxLs[i+1]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i+1]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i+1]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i+1]]])
+
+ if usedList[vIdxLs[i+2]] == -1:
+ mesh.verts.append(vertList[vIdxLs[i+2]])
+ f.v.append(mesh.verts[-1])
+ usedList[vIdxLs[i+2]] = len(mesh.verts)-1
+ else:
+ f.v.append(mesh.verts[usedList[vIdxLs[i+2]]])
+
+ # UV MAPPING
+ if fHasUV:
+ f.uv.append( uvMapList[ vtIdxLs[0] ] )
+ f.uv.append( uvMapList[ vtIdxLs[i+1] ] )
+ f.uv.append( uvMapList[ vtIdxLs[i+2] ] )
+ mesh.faces.append(f) # move the face onto the mesh
+
+ # Apply the current image to the face
+ if currentImg != NULL_IMG:
+ mesh.faces[-1].image = currentImg
+
+ # Object / Group
+ elif l[0] == 'o' or l[0] == 'g':
+
+ # Reset the used list
+ ulIdx = 0
+ while ulIdx < len(usedList):
+ usedList[ulIdx] = -1
+ ulIdx +=1
+
+ # Some material stuff
+ if mtl_fileName != '':
+ load_mtl(DIR, mtl_fileName, mesh)
+
+ # Make sure the objects is worth putting
+ if len(mesh.verts) > 1:
+ mesh.verts.remove(mesh.verts[0])
+ ob = NMesh.PutRaw(mesh, fileName + '_' + objectName)
+ if ob != None: # Name the object too.
+ ob.name = fileName + '_' + objectName
- elif l[0] == 'usemat':
- if l[1] == '(null)':
- currentImg = NULL_IMG
- else:
- currentImg = getImg(DIR + ' '.join(l[1:])) # Use join in case of spaces
-
-
- elif l[0] == 'mtllib':
- mtl_fileName = l[1]
-
- lIdx+=1
+ # Make new mesh
+ mesh = NMesh.GetRaw()
+ # This dummy vert makes life a whole lot easier-
+ # pythons index system then aligns with objs, remove later
+ mesh.verts.append( NMesh.Vert(0, 0, 0) )
+
+ # New mesh name
+ objectName = '_'.join(l[1:]) # Use join in case of spaces
+
+
+ elif l[0] == 'usemtl':
+ if l[1] == '(null)':
+ currentMat = getMat(NULL_MAT)
+ else:
+ currentMat = getMat(' '.join(l[1:])) # Use join in case of spaces
+
+ elif l[0] == 'usemat':
+ if l[1] == '(null)':
+ currentImg = NULL_IMG
+ else:
+ currentImg = getImg(DIR + ' '.join(l[1:])) # Use join in case of spaces
+
+
+ elif l[0] == 'mtllib':
+ mtl_fileName = l[1]
+
+ lIdx+=1
- # 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)
+ # 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) > 1:
+ mesh.verts.remove(mesh.verts[0])
+ ob = NMesh.PutRaw(mesh, fileName + '_' + objectName)
+ if ob != None: # Name the object too.
+ ob.name = fileName + '_' + objectName
-Window.FileSelector(load_obj, 'Import OBJ')
+Window.FileSelector(load_obj, 'Import Wavefront OBJ')