239 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!BPY
 | 
						|
 | 
						|
""" Registration info for Blender menus:
 | 
						|
Name: 'DirectX(.x)...'
 | 
						|
Blender: 244
 | 
						|
Group: 'Import'
 | 
						|
 | 
						|
Tip: 'Import from DirectX text file format format.'
 | 
						|
"""
 | 
						|
# DirectXImporter.py version 1.2
 | 
						|
# Copyright (C) 2005  Arben OMARI -- omariarben@everyday.com 
 | 
						|
#
 | 
						|
# This program is free software; you can redistribute it and/or modify
 | 
						|
# it under the terms of the GNU General Public License as published by
 | 
						|
# the Free Software Foundation; either version 2 of the License, or
 | 
						|
# (at your option) any later version.
 | 
						|
#
 | 
						|
# This program is distributed in the hope that it will be useful,
 | 
						|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
# GNU General Public License for more details.
 | 
						|
 | 
						|
# This script import meshes from DirectX text file format
 | 
						|
 | 
						|
# Grab the latest version here :www.omariben.too.it
 | 
						|
import bpy
 | 
						|
import Blender
 | 
						|
from Blender import Mesh,Object,Material,Texture,Image,Draw
 | 
						|
 | 
						|
 | 
						|
class xImport:
 | 
						|
	def __init__(self, filename):
 | 
						|
		global my_path
 | 
						|
		self.file = open(filename, "r")
 | 
						|
		my_path = Blender.sys.dirname(filename)
 | 
						|
 | 
						|
		# 
 | 
						|
		self.lines = [l_split for l in self.file.readlines() for l_split in (' '.join(l.split()),) if l_split]
 | 
						|
 | 
						|
	def Import(self):
 | 
						|
		lines = self.lines
 | 
						|
		print "importing into Blender ..."
 | 
						|
		scene  = bpy.data.scenes.active
 | 
						|
		
 | 
						|
		mesh_indicies = {} # the index of each 'Mesh' is used as the key for those meshes indicies
 | 
						|
		context_indicies = None # will raise an error if used!
 | 
						|
		
 | 
						|
		
 | 
						|
		#Get the line of Texture Coords
 | 
						|
		nr_uv_ind = 0
 | 
						|
 | 
						|
		#Get Materials
 | 
						|
		nr_fac_mat = 0
 | 
						|
		i = -1
 | 
						|
		mat_list = []
 | 
						|
		tex_list = []
 | 
						|
		mesh_line_indicies = []
 | 
						|
		for j, line in enumerate(lines):
 | 
						|
			l = line.strip()
 | 
						|
			words = line.split()
 | 
						|
			if words[0] == "Material" :
 | 
						|
				#context_indicies["Material"] = j
 | 
						|
				self.loadMaterials(j, mat_list, tex_list)
 | 
						|
			elif words[0] == "MeshTextureCoords" :
 | 
						|
				context_indicies["MeshTextureCoords"] = j
 | 
						|
				#nr_uv_ind = j
 | 
						|
			elif words[0] == "MeshMaterialList" :
 | 
						|
				context_indicies["MeshMaterialList"] = j+2
 | 
						|
				#nr_fac_mat = j + 2
 | 
						|
			elif words[0] == "Mesh": # Avoid a second loop
 | 
						|
				context_indicies = mesh_indicies[j] = {'MeshTextureCoords':0, 'MeshMaterialList':0}
 | 
						|
		
 | 
						|
		for mesh_index, value in mesh_indicies.iteritems():
 | 
						|
			mesh = Mesh.New()
 | 
						|
			self.loadVertices(mesh_index, mesh, value['MeshTextureCoords'], value['MeshMaterialList'], tex_list)
 | 
						|
			
 | 
						|
			mesh.materials = mat_list[:16]
 | 
						|
			if value['MeshMaterialList']:
 | 
						|
				self.loadMeshMaterials(value['MeshMaterialList'], mesh)
 | 
						|
			scene.objects.new(mesh)
 | 
						|
			
 | 
						|
		self.file.close()
 | 
						|
		print "... finished"
 | 
						|
 | 
						|
	#------------------------------------------------------------------------------
 | 
						|
	#        CREATE THE MESH
 | 
						|
	#------------------------------------------------------------------------------
 | 
						|
	def loadVertices(self, nr_vr_ind, mesh, nr_uv, nr_fac_mat, tex_list):
 | 
						|
		v_ind = nr_vr_ind + 1
 | 
						|
		lin = self.lines[v_ind]
 | 
						|
		if lin :
 | 
						|
			lin_c = self.CleanLine(lin)
 | 
						|
			nr_vert = int((lin_c.split()[0]))
 | 
						|
		else :
 | 
						|
			v_ind = nr_vr_ind + 2
 | 
						|
			lin = self.lines[v_ind]
 | 
						|
			lin_c = self.CleanLine(lin)
 | 
						|
			nr_vert = int((lin_c.split()[0]))
 | 
						|
 | 
						|
		#--------------------------------------------------
 | 
						|
		nr_fac_li = v_ind + nr_vert +1
 | 
						|
		lin_f = self.lines[nr_fac_li]
 | 
						|
		if lin_f :
 | 
						|
			lin_fc = self.CleanLine(lin_f)
 | 
						|
			nr_face = int((lin_fc.split()[0]))
 | 
						|
		else :
 | 
						|
			nr_fac_li = v_ind + nr_vert +1
 | 
						|
			lin_f = self.lines[nr_fac_li]
 | 
						|
			lin_fc = self.CleanLine(lin_f)
 | 
						|
			nr_face = int((lin_fc.split()[0]))
 | 
						|
 | 
						|
		#Get Coordinates
 | 
						|
		verts_list = [(0,0,0)] # WARNING - DUMMY VERT - solves EEKADOODLE ERROR
 | 
						|
		for l in xrange(v_ind + 1, (v_ind + nr_vert +1)):
 | 
						|
			line_v = self.lines[l]
 | 
						|
			lin_v = self.CleanLine(line_v)
 | 
						|
			words = lin_v.split()
 | 
						|
			if len(words)==3:
 | 
						|
				verts_list.append((float(words[0]),float(words[1]),float(words[2])))
 | 
						|
		
 | 
						|
		mesh.verts.extend(verts_list)
 | 
						|
		del verts_list
 | 
						|
		
 | 
						|
		face_list = []
 | 
						|
		#Make Faces
 | 
						|
		i = 0
 | 
						|
		mesh_verts = mesh.verts
 | 
						|
		for f in xrange(nr_fac_li + 1, (nr_fac_li + nr_face + 1)):
 | 
						|
			i += 1
 | 
						|
			line_f = self.lines[f]
 | 
						|
			lin_f = self.CleanLine(line_f)
 | 
						|
			
 | 
						|
			# +1 for dummy vert only!
 | 
						|
			words = lin_f.split()
 | 
						|
			if len(words) == 5:
 | 
						|
				face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3]), 1+int(words[4])))
 | 
						|
			elif len(words) == 4:
 | 
						|
				face_list.append((1+int(words[1]), 1+int(words[2]), 1+int(words[3])))
 | 
						|
		
 | 
						|
		mesh.faces.extend(face_list)
 | 
						|
		del face_list
 | 
						|
		
 | 
						|
		if nr_uv :
 | 
						|
			mesh.faceUV = True
 | 
						|
			for f in mesh.faces:
 | 
						|
				fuv = f.uv
 | 
						|
				for ii, v in enumerate(f):
 | 
						|
					# _u, _v = self.CleanLine(self.lines[nr_uv + 2 + v.index]).split()
 | 
						|
					
 | 
						|
					# Use a dummy vert
 | 
						|
					_u, _v = self.CleanLine(self.lines[nr_uv + 1 + v.index]).split()
 | 
						|
					
 | 
						|
					fuv[ii].x = float(_u)
 | 
						|
					fuv[ii].y = float(_v)
 | 
						|
			
 | 
						|
				if nr_fac_mat :
 | 
						|
					fac_line = self.lines[nr_fac_mat + i]
 | 
						|
					fixed_fac = self.CleanLine(fac_line)
 | 
						|
					w_tex = int(fixed_fac.split()[0])
 | 
						|
					f.image = tex_list[w_tex]
 | 
						|
					
 | 
						|
		# remove dummy vert
 | 
						|
		mesh.verts.delete([0,])
 | 
						|
		
 | 
						|
	def CleanLine(self,line):
 | 
						|
		return line.replace(\
 | 
						|
			";", " ").replace(\
 | 
						|
			'"', ' ').replace(\
 | 
						|
			"{", " ").replace(\
 | 
						|
			"}", " ").replace(\
 | 
						|
			",", " ").replace(\
 | 
						|
			"'", " ")
 | 
						|
 | 
						|
	#------------------------------------------------------------------
 | 
						|
	# CREATE MATERIALS
 | 
						|
	#------------------------------------------------------------------
 | 
						|
	def loadMaterials(self, nr_mat, mat_list, tex_list):
 | 
						|
		
 | 
						|
		def load_image(name):
 | 
						|
			try:
 | 
						|
				return Image.Load(Blender.sys.join(my_path,name))
 | 
						|
			except:
 | 
						|
				return None
 | 
						|
		
 | 
						|
		mat = bpy.data.materials.new()
 | 
						|
		line = self.lines[nr_mat + 1]
 | 
						|
		fixed_line = self.CleanLine(line)
 | 
						|
		words = fixed_line.split()
 | 
						|
		mat.rgbCol = [float(words[0]),float(words[1]),float(words[2])]
 | 
						|
		mat.setAlpha(float(words[3]))
 | 
						|
		mat_list.append(mat)
 | 
						|
		l = self.lines[nr_mat + 5]
 | 
						|
		fix_3_line = self.CleanLine(l)
 | 
						|
		tex_n = fix_3_line.split()
 | 
						|
		
 | 
						|
		if tex_n and tex_n[0] == "TextureFilename" :
 | 
						|
 | 
						|
			if len(tex_n) > 1:
 | 
						|
				tex_list.append(load_image(tex_n[1]))
 | 
						|
 | 
						|
			if len(tex_n) <= 1 :
 | 
						|
 | 
						|
				l_succ = self.lines[nr_mat + 6]
 | 
						|
				fix_3_succ = self.CleanLine(l_succ)
 | 
						|
				tex_n_succ = fix_3_succ.split()
 | 
						|
				tex_list.append(load_image(tex_n_succ[0]))
 | 
						|
		else :
 | 
						|
			tex_list.append(None) # no texture for this index
 | 
						|
 | 
						|
		return mat_list, tex_list
 | 
						|
	#------------------------------------------------------------------
 | 
						|
	# SET MATERIALS
 | 
						|
	#------------------------------------------------------------------
 | 
						|
	def loadMeshMaterials(self, nr_fc_mat, mesh):
 | 
						|
		for face in mesh.faces:
 | 
						|
			nr_fc_mat += 1
 | 
						|
			line = self.lines[nr_fc_mat]
 | 
						|
			fixed_line = self.CleanLine(line)
 | 
						|
			wrd = fixed_line.split()
 | 
						|
			mat_idx = int(wrd[0])
 | 
						|
			face.mat = mat_idx
 | 
						|
 | 
						|
#------------------------------------------------------------------
 | 
						|
#  MAIN
 | 
						|
#------------------------------------------------------------------
 | 
						|
def my_callback(filename):
 | 
						|
	if not filename.lower().endswith('.x'): print "Not an .x file" 
 | 
						|
	ximport = xImport(filename)
 | 
						|
	ximport.Import()
 | 
						|
 | 
						|
arg = __script__['arg']
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
	Blender.Window.FileSelector(my_callback, "Import DirectX", "*.x")
 | 
						|
 | 
						|
#my_callback('/fe/x/directxterrain.x')
 | 
						|
#my_callback('/fe/x/Male_Normal_MAX.X')
 | 
						|
#my_callback('/fe/x/male_ms3d.x')
 |