- 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.
This commit is contained in:
Jiri Hnidek 2004-06-14 20:51:09 +00:00
parent f24be4c6ad
commit 317e067ecb

@ -31,11 +31,23 @@ Tooltip: 'Load a Wavefront OBJ File'
# ***** 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
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 #
#==============================================#
@ -48,38 +60,12 @@ def stripPath(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 #
#===============================#
@ -95,8 +81,9 @@ def join(joinList):
from Blender import *
def load_obj(file):
# This gets a mat or creates one of the requested name if none exist.
#==================================================================================#
# This gets a mat or creates one of the requested name if none exist. #
#==================================================================================#
def getMat(matName):
# Make a new mat
try:
@ -104,6 +91,83 @@ def load_obj(file):
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:
@ -125,6 +189,10 @@ def load_obj(file):
# 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
@ -140,7 +208,7 @@ def load_obj(file):
# Main loop
lIdx = 0
while lIdx < len(fileLines):
l = split(fileLines[lIdx], WHITESPACE)
l = fileLines[lIdx].split()
# Detect a line that will be idnored
if len(l) == 0:
@ -170,7 +238,8 @@ def load_obj(file):
vIdxLs = []
vtIdxLs = []
for v in l[1:]:
objVert = split( v, ['/'] )
#objVert = split( v, ['/'] )
objVert = v.split('/', -1)
# VERT INDEX
vIdxLs.append(eval(objVert[0]) -1)
@ -237,8 +306,15 @@ def load_obj(file):
else:
currentMat = getMat(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: