Scripts:
- Jean-Michel Soler probably lost some hours of sleep since Sunday,
  but he managed to send me the updated path import scripts a few
  hours ago.  My tests with Inkscape .svg and .ps and Gimp worked fine.
  He also tested a lot and sent me info about what is already
  supported.  I'll send Ton a doc about bundled scripts including this
  info.  Importers: .ai, .svg, .eps/.ps, Gimp 1-1.2.5 / 2.0.

- Jean-Michel also contributed his Texture Baker script.

- Campbell Barton contributed two new scripts: a mesh cleaner and a
  vloop skinning / lofting script.  He also sent updates to his obj
  import / export ones.

- A Vanpoucke (xand) contributed his Axis Orientation Copy script.

And that makes 8 last minute additions.  Thanks a lot to the authors
and special thanks to JMS and Campbell for their hard work : ).

BPython:

- tiny addition (I'm forced to call it a showstopper bug ;) so JMS's
path import scripts (that actually convert to obj and make Blender
load the .obj curves) can use Blender.Load() and not rename G.sce,
the default filename.  Blender.Load(filename, 1) doesn't update G.sce.
Nothing should break because of this, Load(filename) still works fine.

- Made Blender complain again if script is for a newer Blender version than the one running it.
This commit is contained in:
2004-08-04 06:16:46 +00:00
parent 54e1f40024
commit 452c8cf838
15 changed files with 3294 additions and 406 deletions

View File

@@ -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.
smooth = 0
# 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
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)
# 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
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
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))
# 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)
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.
Window.FileSelector(load_obj, 'Import OBJ')
# 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 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)
# 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
# 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) > 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 Wavefront OBJ')