Sims 2 Bodyshop Meshing with Blender 3D v2.49b: Tutorials #1 & 2 (9/11/12)

<< < (8/8)

Tenshii~Akari:
Absolutely no idea.   :'(  I've been trying to figure this out for the longest time now, but I think I've only narrowed it down to the way Bobcatben has it written in his code.  (I'm too scared to edit and try it out, though.)  From the Import script:


#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)

So... I haven't gotten the gist of Python scripts.  Hopefully someone out there knows how to read/code them and figure out a way to import the normals without recalculating them.    

ETA:  Here are how the actual scripts look like, if anyone is interested:

Code: (import_smd.py)

#!BPY

"""
Name: 'Sims 2 smd file'
Blender: 244
Group: '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 mat2

class Bone:
id = 0
name = ""
parentid = 0
matrix = None
def __init__(this,id,name,pid):
this.id = id
this.name = name
this.parentid = pid

def add(a, tup):
if tup in a:
return a.index(tup)
else:
a.append(tup)
return len(a)-1

def 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')

Code: (export_smd.py)

#!BPY

"""
Name: 'Sims 2 smd file'
Blender: 244
Group: '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 * armmat

def findbone(name,bones):
    for b in bones:
        if b.name == name:
            return b

def 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 places
def 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 mesh
def 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 mesh
def getmeshchild(obj):
    for o in Object.Get():
        if o.getType() == 'Mesh' and o.parent == obj:
            return o
    return None

def 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')
   

ETA2:  There is a button for Auto Smoothing in Blender's Mesh Panel, but that's turned off by default.  (If it's a light-green color, it's off)

Navigation

[0] Message Index

[*] Previous page