#!BPY"""Name: 'Sims 2 smd file'Blender: 244Group: 'Import'Tooltip: 'imports a smd file from sims 2(doubt it will work on other smd's)'"""__author__ = "Bobcatben"__url__ = ["", ""]__version__ = "0.3"__bpydoc__ = """\"""#9/12/2007 version 0.3: reAdded importing of normals(results in some duplicate vertices's but fixes the normal problem, still recalculating them, but this keeps it from merging vertices's with different normals)from Blender import *from Blender.Mathutils import *from math import *def mat(x,y,z,rx,ry,rz): rotmat = RotationMatrix(rx,4,'x') * RotationMatrix(ry,4,'y') * RotationMatrix(rz,4,'z') transmat = TranslationMatrix(Vector(x,y,z)) mat2 = rotmat * transmat del rotmat del transmat return mat2class Bone: id = 0 name = "" parentid = 0 matrix = None def __init__(this,id,name,pid): this.id = id this.name = name this.parentid = piddef add(a, tup): if tup in a: return a.index(tup) else: a.append(tup) return len(a)-1def import_smd(path): editmode = Window.EditMode() if editmode: Window.EditMode(0) IMPORT_SKELETON = Draw.Create(1) IMPORT_MESH = Draw.Create(1) pup_block = [\ ('Import Options'),\ ('Mesh' ,IMPORT_MESH , 'Import the Mesh?'),\ ('Skeleton' ,IMPORT_SKELETON , 'Import the Skeleton?') ] if not Draw.PupBlock('Import...', pup_block): return import_mesh = IMPORT_MESH.val import_skeleton = IMPORT_SKELETON.val Window.WaitCursor(1) name = path.split('\\')[-1].split('/')[-1] file = open(path, 'r') scn = Scene.GetCurrent() Bones = [] faces = [] verts = [] Window.DrawProgressBar(0.0,'') lines = file.readlines() for i in range(0, len(lines)): line = lines[i] words = line.split() #do the nodes if line.startswith('nodes') and import_skeleton: Window.DrawProgressBar(0.0,'Reading Nodes') arm = Armature.New('Bones') arm.envelopes = False arm.makeEditable() armob = scn.objects.new(arm,"Bones") start = i + 1 for i in range(start, len(lines)): line = lines[i] words = line.split() if line.startswith('end'): break tmpbone = Armature.Editbone() bonename = words[1][1:-1] Bones.append(Bone(int(words[0]),bonename,int(words[2]))) if int(words[2]) > -1: tmpbone.parent = arm.bones[ Bones[int(words[2])].name ] arm.bones[bonename] = tmpbone #do the skeleton if line.startswith('skeleton') and import_skeleton: Window.DrawProgressBar(0.1,'Reading Skeleton') start = i + 1 for i in range(start, len(lines)): line = lines[i] words = line.split() if line.startswith('end'): break if len(words) <= 2: continue tx, ty, tz = float(words[1]), float(words[2]), float(words[3]) rx, ry, rz = degrees(float(words[4])), degrees(float(words[5])), degrees(float(words[6])) boneindex = int(words[0]) bone = arm.bones[Bones[boneindex].name] parentindex = Bones[boneindex].parentid matrix = mat(tx,ty,tz,rx,ry,rz) if(parentindex > -1): parent = arm.bones[Bones[parentindex].name] parentmatrix = Bones[parentindex].matrix matrix = matrix * parentmatrix myhead = Vector([0,0,0,1]) * matrix mytail = Vector([0,0.1,0,1]) * matrix myhead.resize3D() mytail.resize3D() bone.head = myhead bone.tail = mytail Bones[boneindex].matrix = matrix else: myhead = Vector([0,0,0,1]) * matrix mytail = Vector([0,0.1,0,1]) * matrix myhead.resize3D() mytail.resize3D() bone.head = myhead bone.tail = mytail Bones[boneindex].matrix = matrix #do the mesh itself(triangles) if line.startswith('triangles') and import_mesh: Window.DrawProgressBar(0.2,'Reading Mesh') start = i + 1 faceverts = [] facetex = [] for i in range(start, len(lines)): line = lines[i] words = line.split() if line.startswith('end'): break if len(words) < 3: continue #get the vertex data, excluding normals as they dont like to import correctly #so we will just have blender recalculate normals at the end, after we remove duplicate vertex's x, y, z, tx, ty = float(words[1]), float(words[2]), float(words[3]), float(words[7]), float(words[8]) nx, ny, nz = float(words[4]), float(words[5]), float(words[6]) tmp = [] if len(words) >= 10: for w in range(0,int(words[9])*2,2): tmp.append([ int(words[10+w]), float(words[11+w]) ]) faceverts.append(add(verts,[x, y, z,nx,ny,nz, tmp])+1) facetex.append([tx, ty]) #faces every 3 vertex's if len(faceverts) == 3: faces.append([faceverts,facetex]) facetex = [] faceverts = [] #now send them to blender. Window.DrawProgressBar(0.4,'Writing Vertices') mesh = Mesh.New('Imported Object') meshob = scn.objects.new(mesh, 'Imported Object') mesh.verts.extend([[0,0,0]]) for v in verts: mesh.verts.extend([[v[0],v[1],v[2]]]) mesh.verts[-1:][0].no[0] = v[3] mesh.verts[-1:][0].no[1] = v[4] mesh.verts[-1:][0].no[2] = v[5] Window.DrawProgressBar(0.6,'Writing Faces') for f in faces: mesh.faces.extend([f[0]],ignoreDups=True) mesh.faces[len(mesh.faces)-1].image = Image.GetCurrent() mesh.faces[len(mesh.faces)-1].uv = [Vector(f[1][0]),Vector(f[1][1]),Vector(f[1][2])] mesh.verts.delete([0]) mesh.calcNormals() file.close() if import_skeleton and import_mesh: Window.DrawProgressBar(0.9,'Creating vertex groups') for b in Bones: mesh.addVertGroup(b.name) Window.DrawProgressBar(0.95,'Weighting vertices') for vi in range(0, len(verts)): for weight in verts[vi][6]: mesh.assignVertsToGroup( Bones[weight[0]].name, [vi],weight[1],1) if import_skeleton: arm.update() if import_skeleton and import_mesh: armob.makeParentDeform([meshob], 0, 0) Window.DrawProgressBar(1.0,'Done') Window.WaitCursor(0) Window.RedrawAll()Window.FileSelector(import_smd, 'Import')
#!BPY"""Name: 'Sims 2 smd file'Blender: 244Group: 'Export'Tooltip: 'Exports a smd file tailored for the sims 2'"""__author__ = "Bobcatben"__url__ = ["", ""]__version__ = "0.5"__bpydoc__ = """\"""#Oct 27th 2007, V0.5: Added Normalization of bone weighting.#Sept 22nd 2007, V0.4: Added more error handlers.#Sept 20th 2007, Version 0.3: Added a check for vertex groups with no matching bones.from Blender import *from Blender.Mathutils import *from math import *armmat = Matrix()class Bone: id = 0 name = "" parentid = 0 matrix = None pos = Vector() rot = Euler() def __init__(this,id,name,pid,mat): this.id = id this.name = name this.parentid = pid this.matrix = mat * armmatdef findbone(name,bones): for b in bones: if b.name == name: return bdef recursebones(bone,bones,pid): thisbone = Bone(len(bones),bone.name,pid,bone.matrix['ARMATURESPACE']) bones.append(thisbone) for b in bone.children: if b.hasChildren(): recursebones(b,bones,thisbone.id) else: bones.append(Bone(len(bones),b.name,thisbone.id,b.matrix['ARMATURESPACE']))#rounds it to 6 decimal placesdef cleanvalue(value): if fabs( value ) < 1e-6: return 0 else: return round( value, 6 )def error(text): Draw.PupMenu("Error%t|"+text)#checks if the object has a child that is a meshdef hasmeshchild(obj): for o in Object.Get(): if o.getType() == 'Mesh' and o.parent == obj: return True return False#gets the first child object that is a meshdef getmeshchild(obj): for o in Object.Get(): if o.getType() == 'Mesh' and o.parent == obj: return o return Nonedef export_smd(path): global armmat editmode = Window.EditMode() if editmode: Window.EditMode(0) if not path.lower().endswith('.smd'): path += '.smd' name = path.split('\\')[-1].split('/')[-1] #step 1, find a armature with a attached mesh foundone = False for o in Object.Get(): if o.getType() == 'Armature' and hasmeshchild(o): #arm = Armature.Get(o.getName()) arm = o.getData() armmat = o.getMatrix().rotationPart() armmat.resize4x4() meshob = getmeshchild(o) mesh = meshob.getData(mesh=True) foundone = True break #if step 1 fails, find just a mesh. if not foundone: foundmesh = False for o in Object.Get(): if o.getType() == 'Mesh': mesh = o.getData(mesh=True) foundmesh = True break if not foundmesh: error("No Mesh or Armature") return #step 2, if theres bones, process if foundone: Bones = [] for b in arm.bones.values(): if not b.hasParent(): recursebones(b,Bones,-1) for b in Bones: if b.parentid > -1: inverseparent = Matrix(Bones[b.parentid].matrix) inverseparent.invert() mat = b.matrix * inverseparent del inverseparent else: mat = b.matrix b.pos = mat.translationPart() b.rot = mat.toEuler() del mat #step 2.5, if no bones, generate a dummy bone else: Bones = [Bone(0,'SmdMiscBone',-1,Matrix())] Bones[0].pos = Bones[0].matrix.translationPart() Bones[0].rot = Bones[0].matrix.toEuler() #step 3, write the beginning of the file file = open(path, 'w') file.write('version 1\n') #step 4, write the bone hierarchy file.write('nodes\n') for b in Bones: file.write("%d \"%s\" %d\n"%(b.id,b.name,b.parentid)) file.write('end\n') #step 5, write the skeleton data file.write('skeleton\n') file.write('time 0\n') for b in Bones: file.write("%d %f %f %f %f %f %f\n"%(b.id,cleanvalue(b.pos.x),cleanvalue(b.pos.y),cleanvalue(b.pos.z),cleanvalue(radians(b.rot.x)),cleanvalue(radians(b.rot.y)),cleanvalue(radians(b.rot.z)) )) file.write('end\n') #step 6, write the mesh file.write('triangles\n') for face in mesh.faces: file.write('map.bmp\n') vi = 0 if len(face.verts) != 3: if Draw.PupMenu("The mesh contains quads, The Sims 2 only supports triangles.%t|Convert to Triangles|Abort") == 1: mesh.quadToTriangle() else: file.close() return for v in face.verts: #write the vertex location file.write("0 %f %f %f"%( cleanvalue(v.co[0]),cleanvalue(v.co[1]),cleanvalue(v.co[2]) )) #write the vertex normal file.write(" %f %f %f"%( cleanvalue(v.no[0]),cleanvalue(v.no[1]),cleanvalue(v.no[2]) )) #write the uv coordinate try: file.write(" %f %f"%( face.uv[vi][0],face.uv[vi][1] )) except ValueError: error("Mesh has no texture") file.close() return vi+= 1 inf = mesh.getVertexInfluences(v.index) if len(inf) > 4: error("Too many vertex groups on a single vertex, %d (4 max)"%len(inf)) file.close() return file.write(" %d"%len(inf)) if len(inf) > 0: tweight = 0.0 mul = 1.0 for ww in inf: tweight += ww[1] if tweight != 1.0: mul = 1.0 / tweight for w in inf: thisbone = findbone(w[0],Bones) if thisbone != None: file.write(" %d %f"%( thisbone.id, w[1]*mul )) file.write('\n') else: file.write('\n') file.write('end\n') file.close() if editmode: Window.EditMode(1)Window.FileSelector(export_smd, 'Export')