Revision: 14454
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14454
Author:   campbellbarton
Date:     2008-04-17 22:15:37 +0200 (Thu, 17 Apr 2008)

Log Message:
-----------
milkshape3d model importer, can import a textured model with materials and 
animation

Added Paths:
-----------
    trunk/blender/release/scripts/ms3d_import.py

Added: trunk/blender/release/scripts/ms3d_import.py
===================================================================
--- trunk/blender/release/scripts/ms3d_import.py                                
(rev 0)
+++ trunk/blender/release/scripts/ms3d_import.py        2008-04-17 20:15:37 UTC 
(rev 14454)
@@ -0,0 +1,381 @@
+#!BPY
+""" 
+Name: 'MilkShape3D (.ms3d)...'
+Blender: 245
+Group: 'Import'
+Tooltip: 'Import from MilkShape3D file format (.ms3d)'
+"""
+# 
+# Author: Markus Ilmola
+# Email: [EMAIL PROTECTED]
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+
+# import needed stuff
+import os.path
+import math
+from math import *
+import struct
+import Blender
+from Blender import Mathutils
+from Blender.Mathutils import *
+
+
+# trims a string by removing ending 0 and everything after it
+def uku(s):
+       try:
+               return s[:s.index('\0')]
+       except:
+               return s
+
+
+# Converts ms3d euler angles to a rotation matrix
+def RM(a):
+       sy = sin(a[2])
+       cy = cos(a[2])
+       sp = sin(a[1])
+       cp = cos(a[1])
+       sr = sin(a[0])
+       cr = cos(a[0])
+       return Matrix([cp*cy, sr*sp*cy+cr*-sy, cr*sp*cy+-sr*-sy],[cp*sy, 
sr*sp*sy+cr*cy, cr*sp*sy+-sr*cy], [-sp, sr*cp, cr*cp])
+
+
+# Converts ms3d euler angles to a quaternion
+def RQ(a):
+       angle = a[2] * 0.5;
+       sy = sin(angle);
+       cy = cos(angle);
+       angle = a[1] * 0.5;
+       sp = sin(angle);
+       cp = cos(angle);
+       angle = a[0] * 0.5;
+       sr = sin(angle);
+       cr = cos(angle);
+       return Quaternion(cr*cp*cy+sr*sp*sy, sr*cp*cy-cr*sp*sy, 
cr*sp*cy+sr*cp*sy, cr*cp*sy-sr*sp*cy)
+
+
+# takes a texture filename and tries to load it
+def loadImage(path, filename):
+       image = None
+       try:
+               image = Blender.Image.Load(os.path.abspath(filename))
+       except IOError:
+               print "Warning: Failed to load image: " + filename + ". Trying 
short path instead...\n"
+               try:
+                       image = Blender.Image.Load(os.path.dirname(path) + "/" 
+ os.path.basename(filename))
+               except IOError:
+                       print "Warning: Failed to load image: " + 
os.path.basename(filename) + "!\n"
+       return image
+
+
+# imports a ms3d file to the current scene
+def import_ms3d(path):
+       # get scene
+       scn = Blender.Scene.GetCurrent()
+       if scn == None:
+               return "No scene to import to!"
+
+       # open the file
+       try:
+               file = open(path, 'rb')
+       except IOError:
+               return "Failed to open the file!"
+
+       # read id
+       id = file.read(10)
+       if id!="MS3D000000":
+               return "The file is not a MS3D file!"
+
+       # read version
+       version = struct.unpack("i", file.read(4))[0]
+       if version!=4:
+               return "The file has invalid version!"
+
+       # Create the mesh
+       scn.objects.selected = []
+       mesh = Blender.Mesh.New("MilkShape3D Mesh")
+       meshOb = scn.objects.new(mesh)
+
+       # read the number of vertices
+       numVertices = struct.unpack("H", file.read(2))[0]
+
+       # read vertices
+       coords = []
+       boneIds = []
+       for i in xrange(numVertices):
+               # skip flags
+               file.read(1)
+
+               # read coords
+               coords.append(struct.unpack("fff", file.read(3*4)))
+
+               # read bone ids 
+               boneIds.append(struct.unpack("B", file.read(1))[0])
+
+               # skip refcount         
+               file.read(1)
+
+       # add the vertices to the mesh
+       mesh.verts.extend(coords)
+
+       # read number of triangles
+       numTriangles = struct.unpack("H", file.read(2))[0]
+       
+       # read triangles
+       faces = []
+       uvs = []
+       for i in xrange(numTriangles):
+               # skip flags
+               file.read(2)
+
+               # read indices (faces)
+               faces.append(struct.unpack("HHH", file.read(3*2)))
+
+               # read normals
+               normals = struct.unpack("fffffffff", file.read(3*3*4))
+
+               # read texture coordinates
+               s = struct.unpack("fff", file.read(3*4))
+               t = struct.unpack("fff", file.read(3*4))
+
+               # store texture coordinates
+               uvs.append([[s[0], 1-t[0]], [s[1], 1-t[1]], [s[2], 1-t[2]]])
+               
+               if faces[-1][2] == 0: # Cant have zero at the third index
+                       faces[-1] = faces[-1][1], faces[-1][2], faces[-1][0]
+                       uvs[-1] = uvs[-1][1], uvs[-1][2], uvs[-1][0]
+               
+               # skip smooth group
+               file.read(1)
+
+               # skip group
+               file.read(1)
+
+       # add the faces to the mesh
+       mesh.faces.extend(faces)
+
+       # set texture coordinates
+       for i in xrange(numTriangles):
+               mesh.faces[i].uv = [Vector(uvs[i][0]), Vector(uvs[i][1]), 
Vector(uvs[i][2])]
+
+       # read number of groups
+       numGroups = struct.unpack("H", file.read(2))[0]
+
+       # read groups
+       for i in xrange(numGroups):
+               # skip flags
+               file.read(1)
+
+               # skip name
+               file.read(32)
+
+               # read the number of triangles in the group
+               numGroupTriangles = struct.unpack("H", file.read(2))[0]
+
+               # read the group triangles
+               if numGroupTriangles > 0:
+                       triangleIndices = struct.unpack(str(numGroupTriangles) 
+ "H", file.read(2*numGroupTriangles));
+
+               # read material
+               material = struct.unpack("B", file.read(1))[0]
+               for j in xrange(numGroupTriangles):
+                       mesh.faces[triangleIndices[j]].mat = material
+
+       # read the number of materials
+       numMaterials = struct.unpack("H", file.read(2))[0]
+
+       # read materials
+       for i in xrange(numMaterials):
+               # read name
+               name = uku(file.read(32))
+
+               # create the material
+               mat = Blender.Material.New(name)
+               mesh.materials += [mat]
+
+               # read ambient color
+               ambient = struct.unpack("ffff", file.read(4*4))[0:3]
+               mat.setAmb((ambient[0]+ambient[1]+ambient[2])/3)
+
+               # read diffuse color
+               diffuse = struct.unpack("ffff", file.read(4*4))[0:3]
+               mat.setRGBCol(diffuse)
+
+               # read specular color
+               specular = struct.unpack("ffff", file.read(4*4))[0:3]
+               mat.setSpecCol(specular)
+
+               # read emissive color
+               emissive = struct.unpack("ffff", file.read(4*4))[0:3]
+               mat.setEmit((emissive[0]+emissive[1]+emissive[2])/3)
+
+               # read shininess
+               shininess = struct.unpack("f", file.read(4))[0]
+               print "Shininess: " + str(shininess)
+
+               # read transparency             
+               transparency = struct.unpack("f", file.read(4))[0]
+               mat.setAlpha(transparency)
+               if transparency < 1:
+                        mat.mode |= Blender.Material.Modes.ZTRANSP
+
+               # read mode
+               mode = struct.unpack("B", file.read(1))[0]
+
+               # read texturemap
+               texturemap = uku(file.read(128))
+               if len(texturemap)>0:
+                       colorTexture = Blender.Texture.New(name + "_texture")
+                       colorTexture.setType('Image')
+                       colorTexture.setImage(loadImage(path, texturemap))
+                       mat.setTexture(0, colorTexture, 
Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL)
+
+               # read alphamap
+               alphamap = uku(file.read(128))
+               if len(alphamap)>0:
+                       alphaTexture = Blender.Texture.New(name + "_alpha")
+                       alphaTexture.setType('Image') 
+                       alphaTexture.setImage(loadImage(path, alphamap))
+                       mat.setTexture(1, alphaTexture, 
Blender.Texture.TexCo.UV, Blender.Texture.MapTo.ALPHA)          
+
+       # read animation
+       fps = struct.unpack("f", file.read(4))[0]
+       time = struct.unpack("f", file.read(4))[0]
+       frames = struct.unpack("i", file.read(4))[0]
+
+       # read the number of joints
+       numJoints = struct.unpack("H", file.read(2))[0]
+
+       # create the armature
+       armature = 0
+       armOb = 0
+       if numJoints > 0:
+               armOb = Blender.Object.New('Armature', "MilkShape3D Skeleton")
+               armature = Blender.Armature.New("MilkShape3D Skeleton")
+               armature.drawType = Blender.Armature.STICK
+               armOb.link(armature)
+               scn.objects.link(armOb)
+               armOb.makeParentDeform([meshOb])
+               armature.makeEditable()
+
+       # read joints
+       rotKeys = {}
+       posKeys = {}
+       for i in xrange(numJoints):
+               # skip flags
+               file.read(1)
+
+               # read name
+               name = uku(file.read(32))
+
+               # create the bone
+               bone = Blender.Armature.Editbone()
+               armature.bones[name] = bone
+
+               # read parent
+               parent = uku(file.read(32))
+               if len(parent)>0:
+                       bone.parent = armature.bones[parent]
+
+               # read orientation
+               rot = struct.unpack("fff", file.read(3*4))
+
+               # read position
+               pos = struct.unpack("fff", file.read(3*4))
+
+               # set head
+               if bone.hasParent():
+                       bone.head = bone.parent.matrix * Vector(pos) + 
bone.parent.head
+                       bone.matrix = bone.parent.matrix * RM(rot)
+               else:
+                       bone.head = Vector(pos)
+                       bone.matrix = RM(rot)
+
+               # set tail
+               bvec = bone.tail - bone.head
+               bvec.normalize()
+               bone.tail = bone.head + 0.01 * bvec
+
+               # Create vertex group for this bone
+               mesh.addVertGroup(name)
+               vgroup = []
+               for index, v in enumerate(boneIds):
+                       if v==i:
+                               vgroup.append(index)
+               mesh.assignVertsToGroup(name, vgroup, 1.0, 1)
+       
+               # read the number of rotation keys
+               numKeyFramesRot = struct.unpack("H", file.read(2))[0]
+                       
+               # read the number of postions keys
+               numKeyFramesPos = struct.unpack("H", file.read(2))[0]
+
+               # read rotation keys
+               rotKeys[name] = []              
+               for j in xrange(numKeyFramesRot):
+                       # read time
+                       time = fps * struct.unpack("f", file.read(4))[0]
+                       # read data
+                       rotKeys[name].append([time, struct.unpack("fff", 
file.read(3*4))])
+
+               # read position keys
+               posKeys[name] = []
+               for j in xrange(numKeyFramesPos):
+                       # read time
+                       time = fps * struct.unpack("f", file.read(4))[0]
+                       # read data
+                       posKeys[name].append([time, struct.unpack("fff", 
file.read(3*4))])
+       
+       # create action and pose
+       action = 0
+       pose = 0
+       if armature!=0:
+               armature.update()
+               pose = armOb.getPose()
+               action = armOb.getAction()
+               if not action:
+                       action = Blender.Armature.NLA.NewAction()
+                       action.setActive(armOb)
+
+       # create animation key frames
+       for name, pbone in pose.bones.items():
+               # create position keys
+               for key in posKeys[name]:
+                       pbone.loc = Vector(key[1])
+                       pbone.insertKey(armOb, int(key[0]), 
Blender.Object.Pose.LOC, True)
+
+               # create rotation keys
+               for key in rotKeys[name]:
+                       pbone.quat = RQ(key[1])
+                       pbone.insertKey(armOb, int(key[0]), 
Blender.Object.Pose.ROT, True)
+       
+       Blender.Redraw()
+       
+       # close the file
+       file.close()
+
+       # succes return empty error string
+       return ""
+
+
+# load the model
+def fileCallback(filename):
+       error = import_ms3d(filename)
+       if error!="":
+               Blender.Draw.PupMenu("An error occured during import: " + error 
+ "|Not all data might have been imported succesfully.", 2)
+
+Blender.Window.FileSelector(fileCallback, 'Import')
+


_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to