Final merge of HEAD (bf-blender) into the orange branch.
[blender.git] / release / scripts / videoscape_export.py
1 #!BPY
2
3 """
4 Name: 'VideoScape with Vertex Colors (.obj)...'
5 Blender: 232
6 Group: 'Export'
7 Tooltip: 'Export selected mesh to VideoScape File Format (.obj)'
8 """
9
10 __author__ = "Anthony D'Agostino (Scorpius)"
11 __url__ = ("blender", "elysiun",
12 "Author's homepage, http://www.redrival.com/scorpius")
13 __version__ = "Part of IOSuite 0.5"
14
15 __bpydoc__ = """\
16 This script exports meshes (including vertex colors) to VideoScape File Format.
17
18 The VideoScape file format is a simple format that is natively supported
19 in Blender. I wrote this module because Blender's internal exporter
20 doesn't export vertex colors correctly. Check the source for a *fast* algorithm for
21 averaging vertex colors.
22
23 Usage:<br>
24         Select meshes to be exported and run this script from "File->Export" menu.
25
26 Supported:<br>
27         Exports meshes only. Hint: use ALT-C to convert non-mesh objects,
28 and CTRL-ALT-A if you have "dupliverts" objects.
29
30 Notes:<br>
31         Before exporting, the mesh must have vertex colors. Here's how to assign them:
32
33 1. Use radiosity!
34
35 2. Set up lights and materials, select a mesh, switch the drawing mode
36 to "textured," press the VKEY.
37
38 3. Press the VKEY and paint manually.
39
40 4. Use a custom script to calculate and apply simple diffuse shading and
41 specular highlights to the vertex colors.
42
43 5. The Videoscape format also allows vertex colors to be specified.
44 """
45
46
47 # $Id$
48 #
49 # +---------------------------------------------------------+
50 # | Copyright (c) 2001 Anthony D'Agostino                   |
51 # | http://www.redrival.com/scorpius                        |
52 # | scorpius@netzero.com                                    |
53 # | June 5, 2001                                            |
54 # | Released under the Blender Artistic Licence (BAL)       |
55 # | Import Export Suite v0.5                                |
56 # +---------------------------------------------------------+
57 # | Write Videoscape File Format (*.obj NOT WAVEFRONT OBJ)  |
58 # +---------------------------------------------------------+
59
60 import Blender, meshtools
61 #import time
62
63 # =====================================
64 # ====== Write VideoScape Format ======
65 # =====================================
66 def write(filename):
67         #start = time.clock()
68         file = open(filename, "wb")
69
70         objects = Blender.Object.GetSelected()
71         objname = objects[0].name
72         meshname = objects[0].data.name
73         mesh = Blender.NMesh.GetRaw(meshname)
74         obj = Blender.Object.Get(objname)
75
76         if not meshtools.has_vertex_colors(mesh):
77                 message = "Please assign vertex colors before exporting.\n"
78                 message += objname + " object was not saved."
79                 meshtools.print_boxed(message)
80                 return
81
82         vcols = average_vertexcolors(mesh)
83
84         # === Write Videoscape Header ===
85         file.write("GOUR\n")
86         file.write("%d\n" % len(mesh.verts))
87
88         # === Write Vertex List & Vertex Colors ===
89         for i in range(len(mesh.verts)):
90                 if not i%100 and meshtools.show_progress:
91                         Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Writing Verts")
92                 file.write("% f % f % f 0x" % tuple(mesh.verts[i].co))
93                 for j in range(len(vcols[i])):
94                         file.write("%02X" % vcols[i][j])
95                 file.write("\n")
96
97         # === Write Face List ===
98         for i in range(len(mesh.faces)):
99                 if not i%100 and meshtools.show_progress:
100                         Blender.Window.DrawProgressBar(float(i)/len(mesh.faces), "Writing Faces")
101                 file.write("%d " % len(mesh.faces[i].v)) # numfaceverts
102                 for j in range(len(mesh.faces[i].v)):
103                         file.write("%d " % mesh.faces[i].v[j].index)
104                 file.write("\n")
105
106         Blender.Window.DrawProgressBar(1.0, '')    # clear progressbar
107         file.close()
108         #end = time.clock()
109         #seconds = " in %.2f %s" % (end-start, "seconds")
110         message = "Successfully exported " + Blender.sys.basename(filename)# + seconds
111         meshtools.print_boxed(message)
112
113 # ===========================================
114 # === Vector Operations for Vertex Colors ===
115 # ===========================================
116 vcolor_add = lambda u, v: [u[0]+v[0], u[1]+v[1], u[2]+v[2], u[3]+v[3]]
117 vcolor_div = lambda u, s: [u[0]/s, u[1]/s, u[2]/s, u[3]/s]
118
119 # ========================================
120 # === Average All Vertex Colors (Fast) ===
121 # ========================================
122 def average_vertexcolors(mesh, debug=0):
123         vertexcolors = {}
124         for i in range(len(mesh.faces)):        # get all vcolors that share this vertex
125                 if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Finding Shared VColors")
126                 for j in range(len(mesh.faces[i].v)):
127                         index = mesh.faces[i].v[j].index
128                         color = mesh.faces[i].col[j]
129                         r,g,b,a = color.r, color.g, color.b, color.a
130                         vertexcolors.setdefault(index, []).append([r,g,b,a])
131         if debug: print 'before'; vcprint(vertexcolors)
132
133         for i in range(len(vertexcolors)):      # average them
134                 if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
135                 vcolor = [0,0,0,0]      # rgba
136                 for j in range(len(vertexcolors[i])):
137                         vcolor = vcolor_add(vcolor, vertexcolors[i][j])
138                 shared = len(vertexcolors[i])
139                 vertexcolors[i] = vcolor_div(vcolor, shared)
140         if debug: print 'after'; vcprint(vertexcolors)
141         return vertexcolors
142
143 # ========================================
144 # === Average all Vertex Colors Slow 1 ===
145 # ========================================
146 def average_vertexcolors_slow_1(mesh, debug=0):
147         vertexcolors = []
148         i = 0
149         for vertex in mesh.verts:
150                 if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
151                 i += 1
152                 vcolor = [0,0,0,0]      # rgba
153                 shared = 0
154                 for face in mesh.faces:
155                         if vertex in face.v:
156                                 index = face.v.index(vertex)
157                                 color = face.col[index]
158                                 r,g,b,a = color.r, color.g, color.b, color.a
159                                 vcolor = vcolor_add(vcolor, [r,g,b,a])
160                                 shared += 1
161                 if not shared: print "Error, vertex %d is not shared." % i; shared += 1
162                 vertexcolors.append(vcolor_div(vcolor, shared))
163         if debug: print 'after'; vcprint(vertexcolors)
164         return vertexcolors
165
166 # ========================================
167 # === Average all Vertex Colors Slow 2 ===
168 # ========================================
169 def average_vertexcolors_slow_2(mesh, debug=0):
170         vertexcolors = []
171         for i in range(len(mesh.verts)):
172                 if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
173                 vcolor = [0,0,0,0]      # rgba
174                 shared = 0
175                 for j in range(len(mesh.faces)):
176                         if mesh.verts[i] in mesh.faces[j].v:
177                                 index = mesh.faces[j].v.index(mesh.verts[i])
178                                 color = mesh.faces[j].col[index]
179                                 r,g,b,a = color.r, color.g, color.b, color.a
180                                 vcolor = vcolor_add(vcolor, [r,g,b,a])
181                                 shared += 1
182                 vertexcolors.append(vcolor_div(vcolor, shared))
183         if debug: print 'after'; vcprint(vertexcolors)
184         return vertexcolors
185
186 # ========================================
187 # === Average all Vertex Colors Slow 3 ===
188 # ========================================
189 def average_vertexcolors_slow_3(mesh, debug=0):
190         vertexcolors = []
191         for i in range(len(mesh.verts)):
192                 if not i%100 and meshtools.show_progress: Blender.Window.DrawProgressBar(float(i)/len(mesh.verts), "Averaging Vertex Colors")
193                 vcolor = [0,0,0,0]      # rgba
194                 shared = 0
195                 for j in range(len(mesh.faces)):
196                         if len(mesh.faces[j].v) == 4:
197                                 v1,v2,v3,v4 = mesh.faces[j].v
198                                 faceverts = v1.index, v2.index, v3.index, v4.index
199                         else:
200                                 v1,v2,v3 = mesh.faces[j].v
201                                 faceverts = v1.index, v2.index, v3.index
202
203                         if i in faceverts:
204                                 index = mesh.faces[j].v.index(mesh.verts[i])
205                                 color = mesh.faces[j].col[index]
206                                 r,g,b,a = color.r, color.g, color.b, color.a
207                                 vcolor = vcolor_add(vcolor, [r,g,b,a])
208                                 shared += 1
209                 vertexcolors.append(vcolor_div(vcolor, shared))
210         if debug: print 'after'; vcprint(vertexcolors)
211         return vertexcolors
212
213 def fs_callback(filename):
214         if filename.find('.obj', -4) <= 0: filename += '.VIDEOSCAPE.obj'
215         write(filename)
216
217 Blender.Window.FileSelector(fs_callback, "Export VideoScape")
218
219
220 # filename = "VIDEOSCAPE_" + objname + ".obj"
221 # filename = 'nul'
222 # file = open(filename, "wb")
223 # debug = 0
224 # time_functions = 1
225 # time_loop = 0
226 #
227 # if time_functions:
228 #         funcs = [ average_vertexcolors,
229 #                               average_vertexcolors_slow_1,
230 #                               average_vertexcolors_slow_2,
231 #                               average_vertexcolors_slow_3 ]
232 #
233 #         print
234 #         for func in funcs:
235 #                 start = time.clock()
236 #                 vcols = func(mesh, debug)
237 #                 end = time.clock()
238 #                 seconds = "in %.2f %s" % (end-start, "seconds")
239 #                 print func.__name__, "finished in", seconds
240 #
241 # elif time_loop:
242 #         total = 0
243 #         loops = 6
244 #         for i in range(loops):
245 #                 start = time.clock()
246 #                 vcols = average_vertexcolors(mesh, debug)
247 #                 end = time.clock()
248 #                 total += (end-start)
249 #         print "Total: %5.2f Avg: %.2f " % (total, total/loops)
250 # else:
251 #         start = time.clock()
252 #         vcols = average_vertexcolors(mesh, debug)
253
254 # # =====================================
255 # # === Print Vertex Colors for Debug ===
256 # # =====================================
257 # def vcprint(data):
258 #         print type(data)
259 #         for i in range(len(data)):
260 #                 print "%2d" % i,
261 #                 for j in range(len(data[i])):
262 #                         try:
263 #                                 print "[%3d %3d %3d %3d]" % tuple(data[i][j]),  # before
264 #                         except:
265 #                                 print "[%3d]" % data[i][j],                     # after
266 #                 print
267 #         print
268 #