Integrated Freestyle to rendering pipeline
[blender.git] / release / scripts / export_mdd.py
1 #!BPY
2
3 """
4  Name: 'Vertex Keyframe Animation (.mdd)...'
5  Blender: 242
6  Group: 'Export'
7  Tooltip: 'Animated mesh to MDD vertex keyframe file.'
8 """
9
10 __author__ = "Bill L.Nieuwendorp"
11 __bpydoc__ = """\
12 This script Exports Lightwaves MotionDesigner format.
13
14 The .mdd format has become quite a popular Pipeline format<br>
15 for moving animations from package to package.
16
17 Be sure not to use modifiers that change the number or order of verts in the mesh
18 """
19 #Please send any fixes,updates,bugs to Slow67_at_Gmail.com or cbarton_at_metavr.com
20 #Bill Niewuendorp
21 # ***** BEGIN GPL LICENSE BLOCK *****
22 #
23 # This program is free software; you can redistribute it and/or
24 # modify it under the terms of the GNU General Public License
25 # as published by the Free Software Foundation; either version 2
26 # of the License, or (at your option) any later version.
27 #
28 # This program is distributed in the hope that it will be useful,
29 # but WITHOUT ANY WARRANTY; without even the implied warranty of
30 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31 # GNU General Public License for more details.
32 #
33 # You should have received a copy of the GNU General Public License
34 # along with this program; if not, write to the Free Software Foundation,
35 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
36 #
37 # ***** END GPL LICENCE BLOCK *****
38
39 import bpy
40 import Blender
41 from Blender import *
42 import BPyMessages
43 try:
44         from struct import pack
45 except:
46         pack = None
47
48         
49 def zero_file(filepath):
50         '''
51         If a file fails, this replaces it with 1 char, better not remove it?
52         '''
53         file = open(filepath, 'w')
54         file.write('\n') # aparently macosx needs some data in a blank file?
55         file.close()
56
57
58 def check_vertcount(mesh,vertcount):
59         '''
60         check and make sure the vertcount is consistent throghout the frame range
61         '''
62         if len(mesh.verts) != vertcount:
63                 Blender.Draw.PupMenu('Error%t|Number of verts has changed during animation|cannot export')
64                 f.close()
65                 zero_file(filepath)
66                 return
67         
68         
69 def mdd_export(filepath, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
70         
71         Window.EditMode(0)
72         Blender.Window.WaitCursor(1)
73         mesh_orig = Mesh.New()
74         mesh_orig.getFromObject(ob.name)
75         
76         #Flip y and z
77         '''
78         mat = Mathutils.Matrix()
79         mat[2][2] = -1
80         rotmat = Mathutils.RotationMatrix(90, 4, 'x')
81         mat_flip = mat*rotmat
82         '''
83         # Above results in this matrix
84         mat_flip= Mathutils.Matrix(\
85         [1.0, 0.0, 0.0, 0.0],\
86         [0.0, 0.0, 1.0, 0.0],\
87         [0.0, 1.0, 0.0, 0.0],\
88         [0.0, 0.0, 0.0, 1.0],\
89         )
90         
91         me_tmp = Mesh.New() # container mesh
92
93         numverts = len(mesh_orig.verts)
94         numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
95         PREF_FPS= float(PREF_FPS)
96         f = open(filepath, 'wb') #no Errors yet:Safe to create file
97         
98         # Write the header
99         f.write(pack(">2i", numframes, numverts))
100         
101         # Write the frame times (should we use the time IPO??)
102         f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in xrange(numframes)]) ) # seconds
103         
104         #rest frame needed to keep frames in sync
105         Blender.Set('curframe', PREF_STARTFRAME)
106         me_tmp.getFromObject(ob.name)
107         check_vertcount(me_tmp,numverts)
108         me_tmp.transform(ob.matrixWorld * mat_flip)
109         f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co]))
110         me_tmp.verts= None
111                 
112         for frame in xrange(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
113                 Blender.Set('curframe', frame)
114                 
115                 me_tmp.getFromObject(ob.name)
116                 
117                 check_vertcount(me_tmp,numverts)
118                 
119                 me_tmp.transform(ob.matrixWorld * mat_flip)
120                 
121                 # Write the vertex data
122                 f.write(pack(">%df" % (numverts*3), *[axis for v in me_tmp.verts for axis in v.co]))
123         
124         me_tmp.verts= None
125         f.close()
126         
127         print'MDD Exported: %s frames:%d\n'% (filepath, numframes-1)  
128         Blender.Window.WaitCursor(0)
129
130
131 def mdd_export_ui(filepath):
132         # Dont overwrite
133         if not BPyMessages.Warning_SaveOver(filepath):
134                 return
135         
136         scn= bpy.data.scenes.active
137         ob_act= scn.objects.active
138         if not ob_act or ob_act.type != 'Mesh':
139                 BPyMessages.Error_NoMeshActive()
140         
141         ctx = scn.getRenderingContext()
142         orig_frame = Blender.Get('curframe')
143         PREF_STARTFRAME= Blender.Draw.Create(int(ctx.startFrame()))
144         PREF_ENDFRAME= Blender.Draw.Create(int(ctx.endFrame()))
145         PREF_FPS= Blender.Draw.Create(ctx.fps)
146
147         block = [\
148         ("Start Frame: ", PREF_STARTFRAME, 1, 30000, "Start Bake from what frame?: Default 1"),\
149         ("End Frame: ", PREF_ENDFRAME, 1, 30000, "End Bake on what Frame?"),\
150         ("FPS: ", PREF_FPS, 1, 100, "Frames per second")\
151         ]
152         
153         if not Blender.Draw.PupBlock("Export MDD", block):
154                 return
155         
156         PREF_STARTFRAME, PREF_ENDFRAME=\
157                 min(PREF_STARTFRAME.val, PREF_ENDFRAME.val),\
158                 max(PREF_STARTFRAME.val, PREF_ENDFRAME.val)
159         
160         print (filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val)
161         mdd_export(filepath, ob_act, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS.val)
162         Blender.Set('curframe', orig_frame)
163         
164 if __name__=='__main__':
165         if not pack:
166                 Draw.PupMenu('Error%t|This script requires a full python install')
167         
168         Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))