cleanup and some speedups with assigning materials

This commit is contained in:
Campbell Barton 2006-08-25 18:05:05 +00:00
parent 69836ce9bc
commit e10613c7f7

@ -8,7 +8,7 @@ Tooltip: 'Import from 3DS file format (.3ds)'
__author__= ['Bob Holcomb', 'Richard L?rk?ng', 'Damien McGinnes', 'Campbell Barton'] __author__= ['Bob Holcomb', 'Richard L?rk?ng', 'Damien McGinnes', 'Campbell Barton']
__url__= ('blender', 'elysiun', 'http://www.gametutorials.com') __url__= ('blender', 'elysiun', 'http://www.gametutorials.com')
__version__= '0.96' __version__= '0.98'
__bpydoc__= '''\ __bpydoc__= '''\
3ds Importer 3ds Importer
@ -18,6 +18,10 @@ This script imports a 3ds file and the materials into Blender for editing.
Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen). Loader is based on 3ds loader from www.gametutorials.com (Thanks DigiBen).
0.98 by Campbell Barton<br>
- import faces and verts to lists instead of a mesh, convert to a mesh later
- use new index mapping feature of mesh to re-map faces that were not added.
0.97 by Campbell Barton<br> 0.97 by Campbell Barton<br>
- Strip material names of spaces - Strip material names of spaces
- Added import as instance to import the 3ds into its own - Added import as instance to import the 3ds into its own
@ -296,7 +300,7 @@ def process_next_chunk(file, previous_chunk, importedObjects):
contextObName= None contextObName= None
contextLamp= [None, None] # object, Data contextLamp= [None, None] # object, Data
contextMaterial= None contextMaterial= None
contextMatrix= Blender.Mathutils.Matrix(); contextMatrix.identity() # contextMatrix= Blender.Mathutils.Matrix(); contextMatrix.identity()
contextMesh_vertls= None contextMesh_vertls= None
contextMesh_facels= None contextMesh_facels= None
contextMeshMaterials= {} # matname:[face_idxs] contextMeshMaterials= {} # matname:[face_idxs]
@ -317,17 +321,8 @@ def process_next_chunk(file, previous_chunk, importedObjects):
def putContextMesh(myContextMesh_vertls, myContextMesh_facels, myContextMeshMaterials): def putContextMesh(myContextMesh_vertls, myContextMesh_facels, myContextMeshMaterials):
####contextMesh.transform(contextMatrix.copy().invert()) ####contextMesh.transform(contextMatrix.copy().invert())
# Copy UV's to mesh materialFaces= set() # faces that have a material. Can optimize?
"""
if contextMeshUV:
myContextMesh.faceUV= 1
for f in myContextMesh.faces:
# v.index-1 because of the DUMMYVERT
f.uv= [contextMeshUV[v.index-1] for v in f]
"""
materialFaces= set() # faces that have a material. Can optimize
allFaces= set(range(len( myContextMesh_facels )))
# Now make copies with assigned materils. # Now make copies with assigned materils.
def makeMeshMaterialCopy(matName, faces): def makeMeshMaterialCopy(matName, faces):
@ -357,25 +352,19 @@ def process_next_chunk(file, previous_chunk, importedObjects):
##bmesh = Mesh.New(contextMesh.name) ##bmesh = Mesh.New(contextMesh.name)
bmesh = Mesh.New() bmesh = Mesh.New()
if matName != None: if matName == None:
bmat = MATDICT[matName][1]
try:
img= TEXTURE_DICT[bmat.name]
except:
img= None
bmesh.materials= [bmat]
else:
img= None img= None
else:
bmat = MATDICT[matName][1]
bmesh.materials= [bmat]
try: img= TEXTURE_DICT[bmat.name]
except: img= None
bmesh.verts.extend( [Vector()] ) bmesh.verts.extend( [Vector()] )
bmesh.verts.extend( [myContextMesh_vertls[i] for i in vertsToUse] ) bmesh.verts.extend( [myContextMesh_vertls[i] for i in vertsToUse] )
# +1 because of DUMMYVERT # +1 because of DUMMYVERT
###bmesh.faces.extend( [ [ bmesh.verts[ myVertMapping[v.index]+1] for v in myContextMesh.faces[fIdx].v] for fIdx in faces ] )
face_mapping= bmesh.faces.extend( [ [ bmesh.verts[ myVertMapping[vindex]+1] for vindex in myContextMesh_facels[fIdx]] for fIdx in faces ], indexList=True ) face_mapping= bmesh.faces.extend( [ [ bmesh.verts[ myVertMapping[vindex]+1] for vindex in myContextMesh_facels[fIdx]] for fIdx in faces ], indexList=True )
print len(face_mapping), len(faces)
if len(face_mapping) == len(faces):
print face_mapping
if contextMeshUV or img: if contextMeshUV or img:
bmesh.faceUV= 1 bmesh.faceUV= 1
@ -393,7 +382,7 @@ def process_next_chunk(file, previous_chunk, importedObjects):
if img: if img:
targetFace.image= img targetFace.image= img
tempName= contextObName + '_' + str(matName) # str because we may be None tempName= '%s_%s' % (contextObName, matName) # matName may be None.
bmesh.name= tempName bmesh.name= tempName
ob = Object.New('Mesh', tempName) ob = Object.New('Mesh', tempName)
ob.link(bmesh) ob.link(bmesh)
@ -406,9 +395,8 @@ def process_next_chunk(file, previous_chunk, importedObjects):
if len(materialFaces)!=len(myContextMesh_facels): if len(materialFaces)!=len(myContextMesh_facels):
# Invert material faces. # Invert material faces.
makeMeshMaterialCopy(None, allFaces - materialFaces) makeMeshMaterialCopy(None, set(range(len( myContextMesh_facels ))) - materialFaces)
#raise 'Some UnMaterialed faces', len(contextMesh.faces) #raise 'Some UnMaterialed faces', len(contextMesh.faces)
#a spare chunk #a spare chunk
new_chunk= chunk() new_chunk= chunk()
@ -428,7 +416,7 @@ def process_next_chunk(file, previous_chunk, importedObjects):
#read in the version of the file #read in the version of the file
#it's an unsigned short (H) #it's an unsigned short (H)
temp_data= file.read(calcsize('I')) temp_data= file.read(calcsize('I'))
version,= unpack('<I', temp_data) version = unpack('<I', temp_data)[0]
new_chunk.bytes_read+= 4 #read the 4 bytes for the version number new_chunk.bytes_read+= 4 #read the 4 bytes for the version number
#this loader works with version 3 and below, but may not with 4 and above #this loader works with version 3 and below, but may not with 4 and above
if (version>3): if (version>3):
@ -598,7 +586,7 @@ def process_next_chunk(file, previous_chunk, importedObjects):
contextLamp[0].setLocation(x,y,z) contextLamp[0].setLocation(x,y,z)
# Reset matrix # Reset matrix
contextMatrix= Mathutils.Matrix(); contextMatrix.identity() ####contextMatrix= Mathutils.Matrix(); contextMatrix.identity()
#print contextLamp.name, #print contextLamp.name,
@ -607,14 +595,13 @@ def process_next_chunk(file, previous_chunk, importedObjects):
if contextMesh_facels != None: # Write context mesh if we have one. if contextMesh_facels != None: # Write context mesh if we have one.
putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials) putContextMesh(contextMesh_vertls, contextMesh_facels, contextMeshMaterials)
#contextMesh= Mesh.New() contextMesh_vertls= []; contextMesh_facels= []
contextMesh_vertls= []
contextMesh_facels= []
contextMeshMaterials= {} # matname:[face_idxs] contextMeshMaterials= {} # matname:[face_idxs]
contextMeshUV= None contextMeshUV= None
#contextMesh.vertexUV= 1 # Make sticky coords. #contextMesh.vertexUV= 1 # Make sticky coords.
# Reset matrix # Reset matrix
contextMatrix= Blender.Mathutils.Matrix(); contextMatrix.identity() ####contextMatrix= Blender.Mathutils.Matrix(); contextMatrix.identity()
elif (new_chunk.ID==OBJECT_VERTICES): elif (new_chunk.ID==OBJECT_VERTICES):
''' '''
@ -622,25 +609,12 @@ def process_next_chunk(file, previous_chunk, importedObjects):
''' '''
# print 'elif (new_chunk.ID==OBJECT_VERTICES):' # print 'elif (new_chunk.ID==OBJECT_VERTICES):'
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_verts,=unpack('<H', temp_data) num_verts=unpack('<H', temp_data)[0]
new_chunk.bytes_read+=2 new_chunk.bytes_read+=2
# print 'number of verts: ', num_verts # print 'number of verts: ', num_verts
def getvert(): def getvert():
temp_data= unpack('<3f', file.read(STRUCT_SIZE_3FLOAT)) temp_data= unpack('<3f', file.read(STRUCT_SIZE_3FLOAT))
# Set the bounds if user selected
if BOUNDS_3DS:
# xmin, ymin,zmin, xmax,ymax, zmax
if temp_data[0] < BOUNDS_3DS[0]: BOUNDS_3DS[0]= temp_data[0]
if temp_data[1] < BOUNDS_3DS[1]: BOUNDS_3DS[1]= temp_data[1]
if temp_data[2] < BOUNDS_3DS[2]: BOUNDS_3DS[2]= temp_data[2]
if temp_data[0] > BOUNDS_3DS[3]: BOUNDS_3DS[3]= temp_data[0]
if temp_data[1] > BOUNDS_3DS[4]: BOUNDS_3DS[4]= temp_data[1]
if temp_data[2] > BOUNDS_3DS[5]: BOUNDS_3DS[5]= temp_data[2]
new_chunk.bytes_read += STRUCT_SIZE_3FLOAT #12: 3 floats x 4 bytes each new_chunk.bytes_read += STRUCT_SIZE_3FLOAT #12: 3 floats x 4 bytes each
return temp_data return temp_data
@ -652,7 +626,7 @@ def process_next_chunk(file, previous_chunk, importedObjects):
elif (new_chunk.ID==OBJECT_FACES): elif (new_chunk.ID==OBJECT_FACES):
# print 'elif (new_chunk.ID==OBJECT_FACES):' # print 'elif (new_chunk.ID==OBJECT_FACES):'
temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT) temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_faces,= unpack('<H', temp_data) num_faces= unpack('<H', temp_data)[0]
new_chunk.bytes_read+= 2 new_chunk.bytes_read+= 2
#print 'number of faces: ', num_faces #print 'number of faces: ', num_faces
@ -661,9 +635,6 @@ def process_next_chunk(file, previous_chunk, importedObjects):
temp_data= file.read(STRUCT_SIZE_4UNSIGNED_SHORT) temp_data= file.read(STRUCT_SIZE_4UNSIGNED_SHORT)
new_chunk.bytes_read+= STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each new_chunk.bytes_read+= STRUCT_SIZE_4UNSIGNED_SHORT #4 short ints x 2 bytes each
v1,v2,v3,dummy= unpack('<4H', temp_data) v1,v2,v3,dummy= unpack('<4H', temp_data)
##if v1==v2 or v1==v3 or v2==v3:
## return None
# DUMMYVERT! - remove +1 when blenders internals are fixed,
return v1, v2, v3 return v1, v2, v3
contextMesh_facels= [ getface() for i in xrange(num_faces) ] contextMesh_facels= [ getface() for i in xrange(num_faces) ]
@ -674,35 +645,22 @@ def process_next_chunk(file, previous_chunk, importedObjects):
material_name= read_string(file) material_name= read_string(file)
new_chunk.bytes_read += len(material_name)+1 # remove 1 null character. new_chunk.bytes_read += len(material_name)+1 # remove 1 null character.
tempMatFaceIndexList = contextMeshMaterials[material_name]= set()
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_faces_using_mat,= unpack('<H', temp_data) num_faces_using_mat = unpack('<H', temp_data)[0]
new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT new_chunk.bytes_read += STRUCT_SIZE_UNSIGNED_SHORT
#list of faces using mat def getmat():
for face_counter in xrange(num_faces_using_mat):
temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT) temp_data= file.read(STRUCT_SIZE_UNSIGNED_SHORT)
new_chunk.bytes_read+= STRUCT_SIZE_UNSIGNED_SHORT new_chunk.bytes_read+= STRUCT_SIZE_UNSIGNED_SHORT
faceIndex,= unpack('<H', temp_data) return unpack('<H', temp_data)[0]
# We dont have to use context face mapping. contextMeshMaterials[material_name]= [ getmat() for i in xrange(num_faces_using_mat) ]
#if contextFaceMapping:
# meshFaceIndex= contextFaceMapping[faceIndex]
#else:
meshFaceIndex= faceIndex
if meshFaceIndex != None:
tempMatFaceIndexList.add(meshFaceIndex)
####tempMatFaceIndexList.sort()
del tempMatFaceIndexList
#look up the material in all the materials #look up the material in all the materials
elif (new_chunk.ID==OBJECT_UV): elif (new_chunk.ID==OBJECT_UV):
# print 'elif (new_chunk.ID==OBJECT_UV):'
temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT) temp_data=file.read(STRUCT_SIZE_UNSIGNED_SHORT)
num_uv,=unpack('<H', temp_data) num_uv=unpack('<H', temp_data)[0]
new_chunk.bytes_read+= 2 new_chunk.bytes_read+= 2
def getuv(): def getuv():
@ -713,19 +671,18 @@ def process_next_chunk(file, previous_chunk, importedObjects):
contextMeshUV= [ getuv() for i in xrange(num_uv) ] contextMeshUV= [ getuv() for i in xrange(num_uv) ]
elif (new_chunk.ID== OBJECT_TRANS_MATRIX): elif (new_chunk.ID== OBJECT_TRANS_MATRIX):
# print 'elif (new_chunk.ID== OBJECT_TRANS_MATRIX):'
temp_data=file.read(STRUCT_SIZE_4x3MAT) temp_data=file.read(STRUCT_SIZE_4x3MAT)
data= list( unpack('<ffffffffffff', temp_data) ) data= list( unpack('<ffffffffffff', temp_data) )
new_chunk.bytes_read += STRUCT_SIZE_4x3MAT new_chunk.bytes_read += STRUCT_SIZE_4x3MAT
contextMatrix= Blender.Mathutils.Matrix(\ """contextMatrix= Blender.Mathutils.Matrix(\
data[:3] + [0],\ data[:3] + [0],\
data[3:6] + [0],\ data[3:6] + [0],\
data[6:9] + [0],\ data[6:9] + [0],\
data[9:] + [1]) data[9:] + [1])
"""
elif (new_chunk.ID==MAT_MAP_FILENAME): elif (new_chunk.ID==MAT_MAP_FILENAME):
raise 'Hello--'
texture_name=read_string(file) texture_name=read_string(file)
try: try:
TEXTURE_DICT[contextMaterial.name] TEXTURE_DICT[contextMaterial.name]
@ -835,9 +792,21 @@ def load_3ds(filename, PREF_UI= True):
ob.sel= 1 ob.sel= 1
if IMPORT_CONSTRAIN_BOUNDS!=0.0: if IMPORT_CONSTRAIN_BOUNDS!=0.0:
# Set bounds from objecyt bounding box
for ob in importedObjects:
if ob.type=='Mesh':
ob.makeDisplayList() # Why dosnt this update the bounds?
for v in ob.getBoundBox():
for i in (0,1,2):
if v[i] < BOUNDS_3DS[i]:
BOUNDS_3DS[i]= v[i] # min
if v[i] > BOUNDS_3DS[i+3]:
BOUNDS_3DS[i+3]= v[i] # min
# Get the max axis x/y/z # Get the max axis x/y/z
max_axis= max(BOUNDS_3DS[3]-BOUNDS_3DS[0], BOUNDS_3DS[4]-BOUNDS_3DS[1], BOUNDS_3DS[5]-BOUNDS_3DS[2]) max_axis= max(BOUNDS_3DS[3]-BOUNDS_3DS[0], BOUNDS_3DS[4]-BOUNDS_3DS[1], BOUNDS_3DS[5]-BOUNDS_3DS[2])
print max_axis
if max_axis < 1<<30: # Should never be false but just make sure. if max_axis < 1<<30: # Should never be false but just make sure.
# Get a new scale factor if set as an option # Get a new scale factor if set as an option
@ -882,7 +851,7 @@ else:
return False return False
for i, _3ds in enumerate(lines): for i, _3ds in enumerate(lines):
if between(i, 1, 40): if between(i, 1,200):
_3ds= _3ds[:-1] _3ds= _3ds[:-1]
print 'Importing', _3ds, '\nNUMBER', i, 'of', len(lines) print 'Importing', _3ds, '\nNUMBER', i, 'of', len(lines)
_3ds_file= _3ds.split('/')[-1].split('\\')[-1] _3ds_file= _3ds.split('/')[-1].split('\\')[-1]