3DS MAX (ASE) Import Script

This script imports an ASE files exported from 3ds max

Currently I can import

Mesh, UV Texture info, Vertex colours

At the moment I am looking to import materials

Feedback would be good

ASE IMPORT SCRIPT

ASCII SCENE From 3DS MAX

TODO MAterials

Vertex Colours

Bring references to uvmapped images in.

file = open(’/home/projects/3DS_import/test3.ase’, ‘r’)

import Blender
from Blender import NMesh, Material
import string

global wordnum
wordnum = 0 # An index for the file.

CONSTANTS

VERT_STEPPING = 5
FACE_STEPPING = 18
VERTCOL_STEPPING = 5
CFACE_STEPPING = 5
TVERT_STEPPING = 5
TFACE_STEPPING = 5
DEF_MESH_SMOOTH = 0 # Mesh smoothing if unspecified. Could hardcode this one.

Scales all the verts down (Seems to import too big)

MAIN_SCALE = 0.1

fileData = file.read()

words = string.split(fileData) # Split big text file into a list where each list idem is a word.

#########################################################################

Get value returns the vartables after the keyword you are looking for

This can be a list of variables,

#########################################################################
def getValue(keyword): # Used to find the name of the mesh , may replace with seek.
valuenum = wordnum # We use value num to look through the values without adjusting wordnum
while words[valuenum] != keyword: # Seek to the position of the valuename
valuenum +=1

	if valuenum+1 >= len(words): # Dont loop for ever if the value is does nor exist
		print "Could not find value ", keyword
		return "NONE"

# Gather the value
valuenum += 1# We don't want the valueName/keyWord so skip it to record the value(s)
value = [] # We will add the values to this list and return them
while words[valuenum][0] != "*": # Any word with * in front of it is a keyword. Add values until we hit a keyword 
	value.append(words[valuenum])
	valuenum +=1 # go to the next value
	if valuenum >= len(words): break

# If value was a string then remove the quotation marks
if value[0][0] == '"' and value[-1][-1] == '"':
	value[0] = value[0][1:]
	value[-1] = value[-1][0:-1]
	print value, "value"
return value

################################################################

Seek moves the through the ‘words’ list to the keyword you

are seeking. Returns 1 if the keyword is found and 0 if not.

the wordnum is onlu changed if the keyword is found.

################################################################
def seek(keyword, limit): # seek will not look past the limit word (so as not to get properties from other mesh’s)
global wordnum
seeknum = wordnum
while seeknum < len(words):
if words[seeknum] == limit and seeknum != wordnum:
print “breaking seek(keyword, limit) could not find”, keyword
break

	if words[seeknum] == keyword:
		wordnum = seeknum
		return 1
	
	seeknum += 1

# if keyword not found we will end up here and return 0.
return 0

###################################################

Make any changes to ase list for easier reading

###################################################
print “Making changes to ASE file before passing!”

Smoothing make sure that each face has smoothing data

while wordnum < len(words):
if words[wordnum] == “*MESH_SMOOTHING” and words[wordnum+1] == “*MESH_MTLID”:
words.insert(wordnum+1, DEF_MESH_SMOOTH)
wordnum +=1
wordnum +=1
wordnum = 0

###############################

Load materials and UV image

###############################
if seek(’*MATERIAL_COUNT’, ‘*GEOMOBJECT’):
matTotal = eval( words[wordnum+1] )
print “Importing”, matTotal, “Materials”
for matIndex in range(matTotal): # Loop the materials, if none will not loop at all.

	if seek('*MATERIAL_NAME', '}'): 
		newMat = Material.New(string.join( getValue('*MATERIAL_NAME') ))
	else:
		print "*BUG* CANT FIND MATERIAL NAME", matIndex

	if seek('*MATERIAL_AMBIENT', '}'): 
		#Material.New(string.join( getValue("*NODE_NAME") ))
		print "FIXME Not using Ambient"
	else:
		print "*BUG* CANT FIND MATERIAL_AMBIENT NAME", matIndex

	
	if seek('*MATERIAL_DIFFUSE', '}'): # Diffuse colour
		newVal = getValue("*MATERIAL_DIFFUSE")
		newMat.rgbCol = (eval(newVal[0]), eval(newVal[1]),eval(newVal[2]))
	else:
		print "*BUG* CANT FIND MATERIAL_DIFFUSE NAME", matIndex

	if seek('*MATERIAL_SPECULAR', '}'): # Specular RGB
		newVal = getValue("*MATERIAL_SPECULAR")
		newMat.specCol = (eval(newVal[0]), eval(newVal[1]),eval(newVal[2]))
	else:
		print "*BUG* CANT FIND MATERIAL_SPECULAR NAME", matIndex

	if seek('*MATERIAL_SHINE', '}'): # 3ds's Shine = Blender's Hardness
		newMat.hard = eval(getValue('*MATERIAL_SHINE')[0])
	else:
		print "*BUG* CANT FIND *MATERIAL_SHINE NAME", matIndex


	if seek('*MATERIAL_SHINESTRENGTH', '}'): # 3ds's Shinestrength = Blender's Specularity
		newMat.spec = eval(getValue('*MATERIAL_SHINESTRENGTH')[0])
	else:
		print "*BUG* CANT FIND *MATERIAL_SHINESTRENGTH NAME", matIndex

	if seek('*MATERIAL_TRANSPARENCY', '}'):
		newMat.alpha = eval(getValue('*MATERIAL_TRANSPARENCY')[0])
	else:
		print "*BUG* CANT FIND *MATERIAL_TRANSPARENCY' NAME", matIndex
	
	# Load UV Bitmap
	if seek('*BITMAP', '*MATERIAL_NAME'):
		#newMat.fixmebitmap = string.join(getValue('*BITMAP'))
		print "BITMAP FIXME, CINT LINK BITMAP TO UV"
	else:
		print "*BUG* CANT FIND *BITMAP' NAME", matIndex

MAIN LOOP

print “Starting main loop”
while wordnum < len(words):

# Check waether to start a new mesh
if words[wordnum] == '*GEOMOBJECT': # Don't use seek here
	newMesh = NMesh.GetRaw()
		


	######################################
	# Find geometry node and gather info #
	######################################
	newMeshName = string.join(  getValue("*NODE_NAME")  )
	print "Importing mesh", newMeshName

	


	##########################
	# Find verts in geometry #
	##########################
	seek('*MESH_VERTEX', '*GEOMOBJECT')
	#Now we have found a vert, loop through them
	while words[wordnum] == '*MESH_VERTEX':
		
		# Add vert to mesh			
		newVert = NMesh.Vert(MAIN_SCALE * eval(words[wordnum+2]), MAIN_SCALE * eval(words[wordnum+3]), MAIN_SCALE * eval(words[wordnum+4]))	
		newMesh.verts.append(newVert)
		
		# Jump to next vert
		wordnum += VERT_STEPPING
	
	# Clean up
	newVert = None


	##########################
	# Find Faces in geometry #
	##########################
	seek('*MESH_FACE', '*GEOMOBJECT')
	#Now we have found a vert, loop through them
	while words[wordnum] == '*MESH_FACE':
		# Add vert to mesh			
		newFace = NMesh.Face()
		newFace.v.append(newMesh.verts[eval(words[wordnum+3])])
		newFace.v.append(newMesh.verts[eval(words[wordnum+5])])
		newFace.v.append(newMesh.verts[eval(words[wordnum+7])])

		newMesh.faces.append(newFace)
		
		##################################################
		## Smoothing looks bad, need control over angles #
		##################################################
		## Set face smoothing - Blender only supports on or off
		## 3dsmax gives us a variable number. So just turn smoothing on if it
		# is a non zero value.						
		#if words[wordnum+15] != "0": # Add face smoothing
		#	newMesh.faces[-1].smooth = 1
		## END BAD SMOOTHING

		# Jump to next vert
		wordnum += FACE_STEPPING

	# Clean up
	newFace = None

	############################
	# Chech for vertex colours #
	############################
	if seek('*MESH_VERTCOL', '*GEOMOBJECT'): # Only look for texture verts if needed.	
		print "HAS VERTCOL"
		##############################
		# Make a list of vert colors #
		##############################			
		vertColList = []
		while words[wordnum] == '*MESH_VERTCOL':
			
			vertColList.append(( eval(words[wordnum+2]),  eval(words[wordnum+3]),  eval(words[wordnum+4]) ))	
			wordnum += VERTCOL_STEPPING
			
	
	#################################################
	# Add the vert colours to the faces of the mesh #
	#################################################
	if seek('*MESH_CFACE', '*GEOMOBJECT'): # Only look for texture verts if needed.
	
		#Now we have found a vert, loop through them
		while words[wordnum] == '*MESH_CFACE':
			newFaceIndex = eval(words[wordnum+1]) 
			# ADD UV vert coords to faces.

			newMesh.faces[newFaceIndex].uv = [(0,0), (0,0), (0,0)]
			
			vcol1 = NMesh.Col(vertColList[eval(words[wordnum+2])][0]*255, vertColList[eval(words[wordnum+2])][1]*255, vertColList[eval(words[wordnum+2])][2]*255, 255)
			vcol2 = NMesh.Col(vertColList[eval(words[wordnum+3])][0]*255, vertColList[eval(words[wordnum+3])][1]*255, vertColList[eval(words[wordnum+3])][2]*255, 255)
			vcol3 = NMesh.Col(vertColList[eval(words[wordnum+4])][0]*255, vertColList[eval(words[wordnum+4])][1]*255, vertColList[eval(words[wordnum+4])][2]*255, 255)
			
			newMesh.faces[newFaceIndex].col = [vcol1, vcol2, vcol3] # Assign colours to face
			#newMesh.faces[newFaceIndex].uv = []

			wordnum += CFACE_STEPPING
	
		# Clean up
		vcol1 = vcol2 = vcol3 = None




	if seek('*MESH_TVERT', '*GEOMOBJECT'): # Only look for texture verts if needed.	
		################################
		# Make a list of vert textures #
		################################
		TVertList = []
		
		#Now we have found a vert, loop through them
		while words[wordnum] == '*MESH_TVERT':
			
			# ADD UV CO-ORDS to List					
			newTVert = [eval(words[wordnum+2]), eval(words[wordnum+3]), eval(words[wordnum+4])]
		
			TVertList.append(newTVert) # Add new texture vert to the texture vert list
			
			# Jump to next tvert
			wordnum += TVERT_STEPPING
	
		# Clean up
		newTVert = None

		
		############################################
		# Apply vert Texture co-ords to face verts # 
		############################################
		seek('*MESH_TFACE', '*GEOMOBJECT')
	
		#Now we have found a vert, loop through them
		while words[wordnum] == '*MESH_TFACE':
		
			# ADD UV vert coords to faces.
		
			uv1 = (TVertList[eval(words[wordnum+2])][0], TVertList[eval(words[wordnum+2])][1])
			uv2 = (TVertList[eval(words[wordnum+3])][0], TVertList[eval(words[wordnum+3])][1])
			uv3 = (TVertList[eval(words[wordnum+4])][0], TVertList[eval(words[wordnum+4])][1])
			
		
			newFaceIndex = eval(words[wordnum+1]) 

			newMesh.faces[newFaceIndex].uv = [uv1, uv2, uv3]
		
			wordnum += TFACE_STEPPING
	
		# Clean up
		newTVert = None

	######################
	# ENDIF  anyTexVerts #
	######################


	# Write the mesh to the current scene
	NMesh.PutRaw(newMesh, newMeshName)
	
	


# Increment linenumber
wordnum +=1

print “finished”

sick

None of you indentation is in there cbarton. Could you possibly post the py file instead as I could go through it line by line and guess at which lines were supposed to be indented for grouping but why would I when you already have it done :slight_smile:

I’d like to try your script out though…

that or use the


tags

Martin

OOOOps

Here is a new version that also imports materials (Can’t work out some issues)



# ASE IMPORT SCRIPT
# ASCII SCENE From 3DS MAX
# TODO MAterials
# Vertex Colours
# Bring references to uvmapped images in.

file = open('/home/projects/3DS_import/test5.ase', 'r')

 
import Blender
from Blender import NMesh, Material
import string

global wordnum
wordnum = 0 # An index for the file.


# CONSTANTS
VERT_STEPPING = 5
FACE_STEPPING = 18
VERTCOL_STEPPING = 5
CFACE_STEPPING = 5
TVERT_STEPPING = 5
TFACE_STEPPING = 5
DEF_MESH_SMOOTH = 0 # Mesh smoothing if unspecified. Could hardcode this one.

# Scales all the verts down (Seems to import too big)
MAIN_SCALE = 0.1


fileData = file.read()


words = string.split(fileData) # Split big text file into a list where each list idem is a word.

#########################################################################
# Get value returns the vartables after the keyword you are looking for #
# This can be a list of variables,                                      #
######################################################################### 
def getValue(keyword): # Used to find the name of the mesh , may replace with seek.
	valuenum = wordnum # We use value num to look through the values without adjusting wordnum	
	while words[valuenum] != keyword: # Seek to the position of the valuename
		valuenum +=1

		if valuenum+1 &gt;= len(words): # Dont loop for ever if the value is does nor exist
			print "Could not find value ", keyword
			return "NONE"

	# Gather the value
	valuenum += 1# We don't want the valueName/keyWord so skip it to record the value(s)
	value = [] # We will add the values to this list and return them
	while words[valuenum][0] != "*": # Any word with * in front of it is a keyword. Add values until we hit a keyword 
		value.append(words[valuenum])
		valuenum +=1 # go to the next value
		if valuenum &gt;= len(words): break
	
	# If value was a string then remove the quotation marks
	if value[0][0] == '"' and value[-1][-1] == '"':
		value[0] = value[0][1:]
		value[-1] = value[-1][0:-1]
		print value, "value"
	return value


################################################################
# Seek moves the through the 'words' list  to the keyword you  #
# are seeking. Returns 1 if the keyword is found and 0 if not. #
# the wordnum is onlu changed if the keyword is found.         #
################################################################
def seek(keyword, limit): # seek will not look past the limit word (so as not to get properties from other mesh's)
	global wordnum
	seeknum = wordnum
	while seeknum &lt; len(words):
		if words[seeknum] == limit and seeknum != wordnum:
			print "breaking seek(keyword, limit) could not find", keyword
			break
		
		if words[seeknum] == keyword:
			wordnum = seeknum
			return 1
		
		seeknum += 1

	# if keyword not found we will end up here and return 0.
	return 0


###################################################
# Make any changes to ase list for easier reading #
###################################################
print "Making changes to ASE file before passing!"
# Smoothing make sure that each face has smoothing data
while wordnum &lt; len(words):
	if words[wordnum] == "*MESH_SMOOTHING" and words[wordnum+1] == "*MESH_MTLID":	
		words.insert(wordnum+1, DEF_MESH_SMOOTH)
		wordnum +=1 
	wordnum +=1 
wordnum = 0


###############################
# Load materials and UV image #
###############################
if seek('*MATERIAL_COUNT', '*GEOMOBJECT'):
	matTotal = eval( words[wordnum+1] )
	matList = [] # This list is used to store materials before applying to the mesh.
	print "Importing", matTotal, "Materials"
	for matIndex in range(matTotal): # Loop the materials, if none will not loop at all.
		print 'loading material', matIndex		

		if seek('*MATERIAL_NAME', '*MATERIAL_CLASS'): 
			newMat = Material.New(string.join( getValue('*MATERIAL_NAME') ))
		else:
			print "*BUG* CANT FIND MATERIAL NAME", matIndex
			#print catch a problem
			
		if seek('*MATERIAL_AMBIENT', '}'): 
			#Material.New(string.join( getValue("*NODE_NAME") ))
			print "FIXME Not using Ambient"
		else:
			print "*BUG* CANT FIND MATERIAL_AMBIENT NAME", matIndex

		
		if seek('*MATERIAL_DIFFUSE', '}'): # Diffuse colour
			newVal = getValue("*MATERIAL_DIFFUSE")
			newMat.rgbCol = (eval(newVal[0]), eval(newVal[1]),eval(newVal[2]))
		else:
			print "*BUG* CANT FIND MATERIAL_DIFFUSE NAME", matIndex

		if seek('*MATERIAL_SPECULAR', '}'): # Specular RGB
			newVal = getValue("*MATERIAL_SPECULAR")
			newMat.specCol = (eval(newVal[0]), eval(newVal[1]),eval(newVal[2]))
		else:
			print "*BUG* CANT FIND MATERIAL_SPECULAR NAME", matIndex

		if seek('*MATERIAL_SHINE', '}'): # 3ds's Shine/gloss = Blender's Hardness
			newMat.hard = eval(getValue('*MATERIAL_SHINE')[0]) * 255
		else:
			print "*BUG* CANT FIND *MATERIAL_SHINE NAME", matIndex


		if seek('*MATERIAL_SHINESTRENGTH', '}'): # 3ds's Shinestrength = Blender's Specularity
			newMat.spec = eval(getValue('*MATERIAL_SHINESTRENGTH')[0]) / 5 #from 0-9.999 to 0-2.0
		else:
			print "*BUG* CANT FIND *MATERIAL_SHINESTRENGTH NAME", matIndex

		if seek('*MATERIAL_TRANSPARENCY', '}'):
			newMat.alpha = 1.0 - eval(getValue('*MATERIAL_TRANSPARENCY')[0]) # 3ds and blender take opposing ideas of alpha 
		else:
			print "*BUG* CANT FIND *MATERIAL_TRANSPARENCY' NAME", matIndex
		
		# Load UV Bitmap
		if seek('*BITMAP', '*MATERIAL_NAME'):
			#newMat.fixmebitmap = string.join(getValue('*BITMAP'))
			print "BITMAP FIXME, CINT LINK BITMAP TO UV"
		else:
			print "*BUG* CANT FIND *BITMAP' NUMBER", matIndex
		
		# Add the new material to the list
		matList.append(newMat) 
print 'Total materials loaded =', len(matList)

print matList


# MAIN LOOP
print "Starting main loop"
while wordnum &lt; len(words):
	
	# Check waether to start a new mesh
	if words[wordnum] == '*GEOMOBJECT': # Don't use seek here
		newMesh = NMesh.GetRaw()
			


		######################################
		# Find geometry node and gather info #
		######################################
		newMeshName = string.join(  getValue("*NODE_NAME")  )
		print "Importing mesh", newMeshName

		


		##########################
		# Find verts in geometry #
		##########################
		seek('*MESH_VERTEX', '*GEOMOBJECT')
		#Now we have found a vert, loop through them
		while words[wordnum] == '*MESH_VERTEX':
			
			# Add vert to mesh			
			newVert = NMesh.Vert(MAIN_SCALE * eval(words[wordnum+2]), MAIN_SCALE * eval(words[wordnum+3]), MAIN_SCALE * eval(words[wordnum+4]))	
			newMesh.verts.append(newVert)
			
			# Jump to next vert
			wordnum += VERT_STEPPING
		
		# Clean up
		newVert = None


		##########################
		# Find Faces in geometry #
		##########################
		seek('*MESH_FACE', '*GEOMOBJECT')
		
		########################################
		# Search through the faces to find all #
		# the materials that this mesh uses    #
		########################################
		tmpwordnum = wordnum
		while words[tmpwordnum] == '*MESH_FACE':
			# Here we store a list of material indicies that we will use to add these materials to the mesh.
			newMeshMatIndexList = []
			newMat = eval(words[tmpwordnum+17])
			if newMat not in newMeshMatIndexList: # OK, we might not already have the material... so add it.
				newMeshMatIndexList.append(newMat)

			tmpwordnum += FACE_STEPPING
		tmpwordnum = newMat = None 

		#################################
		# Add the materials to the mesh # 
		#################################
		for mat in newMeshMatIndexList:
			print "poop"
			#newMesh.addMaterial(matList[0])  #.append(matList[mat])
		mat = None



		while words[wordnum] == '*MESH_FACE':
			# Add vert to mesh			
			newFace = NMesh.Face()
			newFace.v.append(newMesh.verts[eval(words[wordnum+3])])
			newFace.v.append(newMesh.verts[eval(words[wordnum+5])])
			newFace.v.append(newMesh.verts[eval(words[wordnum+7])])
			newMesh.faces.append(newFace)

			#################################
			# Set the material of this mesh #
			#################################
			newMesh.faces[-1].materialIndex = eval(words[wordnum+17]) # FIXME, USING AN ABSOLUTE MAT REFERENCE, THIS WILL NOT WORK PROPERLA.
			


			##################################################
			## Smoothing looks bad, need control over angles #
			##################################################
			## Set face smoothing - Blender only supports on or off
			## 3dsmax gives us a variable number. So just turn smoothing on if it
			# is a non zero value.						
			#if words[wordnum+15] != "0": # Add face smoothing
			#	newMesh.faces[-1].smooth = 1
			## END BAD SMOOTHING

			# Jump to next vert
			wordnum += FACE_STEPPING

		# Clean up
		newFace = None

		############################
		# Chech for vertex colours #
		############################
		if seek('*MESH_VERTCOL', '*GEOMOBJECT'): # Only look for texture verts if needed.	
			print "HAS VERTCOL"
			##############################
			# Make a list of vert colors #
			##############################			
			vertColList = []
			while words[wordnum] == '*MESH_VERTCOL':
				
				vertColList.append(( eval(words[wordnum+2]),  eval(words[wordnum+3]),  eval(words[wordnum+4]) ))	
				wordnum += VERTCOL_STEPPING
				
		
		#################################################
		# Add the vert colours to the faces of the mesh #
		#################################################
		if seek('*MESH_CFACE', '*GEOMOBJECT'): # Only look for texture verts if needed.
		
			#Now we have found a vert, loop through them
			while words[wordnum] == '*MESH_CFACE':
				newFaceIndex = eval(words[wordnum+1]) 
				# ADD UV vert coords to faces.

				newMesh.faces[newFaceIndex].uv = [(0,0), (0,0), (0,0)]
				
				vcol1 = NMesh.Col(vertColList[eval(words[wordnum+2])][0]*255, vertColList[eval(words[wordnum+2])][1]*255, vertColList[eval(words[wordnum+2])][2]*255, 255)
				vcol2 = NMesh.Col(vertColList[eval(words[wordnum+3])][0]*255, vertColList[eval(words[wordnum+3])][1]*255, vertColList[eval(words[wordnum+3])][2]*255, 255)
				vcol3 = NMesh.Col(vertColList[eval(words[wordnum+4])][0]*255, vertColList[eval(words[wordnum+4])][1]*255, vertColList[eval(words[wordnum+4])][2]*255, 255)
				
				newMesh.faces[newFaceIndex].col = [vcol1, vcol2, vcol3] # Assign colours to face
				#newMesh.faces[newFaceIndex].uv = []

				wordnum += CFACE_STEPPING
		
			# Clean up
			vcol1 = vcol2 = vcol3 = None




		if seek('*MESH_TVERT', '*GEOMOBJECT'): # Only look for texture verts if needed.	
			################################
			# Make a list of vert textures #
			################################
			TVertList = []
			
			#Now we have found a vert, loop through them
			while words[wordnum] == '*MESH_TVERT':
				
				# ADD UV CO-ORDS to List					
				newTVert = [eval(words[wordnum+2]), eval(words[wordnum+3]), eval(words[wordnum+4])]
			
				TVertList.append(newTVert) # Add new texture vert to the texture vert list
				
				# Jump to next tvert
				wordnum += TVERT_STEPPING
		
			# Clean up
			newTVert = None
	
			
			############################################
			# Apply vert Texture co-ords to face verts # 
			############################################
			seek('*MESH_TFACE', '*GEOMOBJECT')
		
			#Now we have found a vert, loop through them
			while words[wordnum] == '*MESH_TFACE':
			
				# ADD UV vert coords to faces.
			
				uv1 = (TVertList[eval(words[wordnum+2])][0], TVertList[eval(words[wordnum+2])][1])
				uv2 = (TVertList[eval(words[wordnum+3])][0], TVertList[eval(words[wordnum+3])][1])
				uv3 = (TVertList[eval(words[wordnum+4])][0], TVertList[eval(words[wordnum+4])][1])
				
			
				newFaceIndex = eval(words[wordnum+1]) 
	
				newMesh.faces[newFaceIndex].uv = [uv1, uv2, uv3]
			
				wordnum += TFACE_STEPPING
		
			# Clean up
			newTVert = None

		######################
		# ENDIF  anyTexVerts #
		######################


		# Write the mesh to the current scene
		NMesh.PutRaw(newMesh, newMeshName)
		
		


	# Increment linenumber
	wordnum +=1


print "finished"