3 """ Registration info for Blender menus:
7 Submenu: 'All meshes...' all
8 Submenu: 'Only selected...' sel
9 Submenu: 'Configure +' config
10 Tip: 'Export to AC3D (.ac) format.'
13 # --------------------------------------------------------------------------
14 # AC3DExport version 2.32-1 Jan 21, 2004
15 # Program versions: Blender 2.32+ and AC3Db files (means version 0xb)
16 # --------------------------------------------------------------------------
17 # ***** BEGIN GPL LICENSE BLOCK *****
19 # Copyright (C) 2004: Willian P. Germano, wgermano@ig.com.br
21 # This program is free software; you can redistribute it and/or
22 # modify it under the terms of the GNU General Public License
23 # as published by the Free Software Foundation; either version 2
24 # of the License, or (at your option) any later version.
26 # This program is distributed in the hope that it will be useful,
27 # but WITHOUT ANY WARRANTY; without even the implied warranty of
28 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 # GNU General Public License for more details.
31 # You should have received a copy of the GNU General Public License
32 # along with this program; if not, write to the Free Software Foundation,
33 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 # ***** END GPL LICENCE BLOCK *****
36 # --------------------------------------------------------------------------
40 ARG = __script__['arg'] # user selected argument
42 HELPME = 0 # help window
49 # Looking for a saved key in Blender.Registry dict:
50 rd = Blender.Registry.GetKey('AC3DExport')
52 SKIP_DATA = rd['SKIP_DATA']
53 MIRCOL_AS_AMB = rd['MIRCOL_AS_AMB']
54 MIRCOL_AS_EMIS = rd['MIRCOL_AS_EMIS']
55 ADD_DEFAULT_MAT = rd['ADD_DEFAULT_MAT']
57 def update_RegistryInfo():
59 d['SKIP_DATA'] = SKIP_DATA
60 d['MIRCOL_AS_AMB'] = MIRCOL_AS_AMB
61 d['MIRCOL_AS_EMIS'] = MIRCOL_AS_EMIS
62 d['ADD_DEFAULT_MAT'] = ADD_DEFAULT_MAT
63 Blender.Registry.SetKey('AC3DExport', d)
65 # The default material to be used when necessary (see right above)
67 'MATERIAL "DefaultWhite" rgb 1 1 1 amb 1 1 1 emis 0 0 0 spec 0.5 0.5 0.5 shi 64 trans 0'
69 # This transformation aligns Blender and AC3D coordinate systems:
70 acmatrix = [[1,0,0,0],[0,0,-1,0],[0,1,0,0],[0,0,0,1]]
73 r = round(f,6) # precision set to 10e-06
79 def transform_verts(verts, m):
83 t[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]
84 t[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]
85 t[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2] + m[3][2]
89 def matrix_mul(m, n = acmatrix):
91 t = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
95 t[i][j] += m[i][k]*n[k][j]
104 def __init__(self, scene, filename):
106 global ARG, SKIP_DATA, ADD_DEFAULT_MAT, DEFAULT_MAT, errmsg
108 print 'Trying AC3DExport...'
119 if ARG == 'all': bl_objlist = scene.getChildren()
120 elif ARG == 'sel': bl_objlist = Blender.Object.GetSelected()
122 for obj in bl_objlist:
123 if obj.getType() != 'Mesh' and obj.getType() != 'Empty':
125 else: kids_dict[obj.name] = 0
126 if obj.getParent() == None:
127 objlist.append(obj.name)
129 bl_objlist2.append(obj)
131 bl_objlist = bl_objlist2[:]
132 world_kids = len(objlist)
135 for obj in bl_objlist:
137 dad = obj.getParent()
138 kids_dict[dad.name] += 1
139 while dad.name not in objlist:
141 dad = dad.getParent()
142 kids_dict[dad.name] += 1
143 objlist.insert(objlist.index(dad.name)+1, obj2.name)
144 bl_objlist2.remove(obj2)
146 for object in objlist:
147 obj = Blender.Object.Get(object)
150 if obj.getType() == 'Empty':
156 mesh = self.mesh = obj.getData()
157 self.MATERIAL(mesh.materials)
160 if not SKIP_DATA: self.data(mesh.name)
161 self.texture(mesh.faces)
162 self.numvert(mesh.verts, obj.getMatrix())
163 self.numsurf(mesh.faces, mesh.hasFaceUV())
165 self.kids(kids_dict[object])
167 if not self.mbuf or ADD_DEFAULT_MAT:
168 self.mbuf = DEFAULT_MAT + '\n' + self.mbuf
169 print "\nNo materials: a default (white) has been assigned.\n"
170 self.mbuf = self.mbuf + "%s\n%s %s\n" \
171 % ('OBJECT world', 'kids', world_kids)
172 buf = "%s\n%s%s" % (header, self.mbuf, self.buf)
174 if filename.find('.ac', -3) <= 0: filename += '.ac'
177 file = open(filename, 'w')
178 except IOError, (errno, strerror):
179 errmsg = "IOError #%s: %s" % (errno, strerror)
184 print "Done. Saved to %s\n" % filename
186 def MATERIAL(self, mat):
188 print "Notice -- object %s has no material linked to it:" % self.name
189 print "\tThe first entry in the .ac file will be used."
193 for m in xrange(len(mat)):
199 M = Blender.Material.Get(name)
200 material = 'MATERIAL "%s"' % name
201 mirCol = "%s %s %s" % (Round(M.mirCol[0]),
202 Round(M.mirCol[1]), Round(M.mirCol[2]))
203 rgb = "rgb %s %s %s" % (Round(M.R), Round(M.G), Round(M.B))
204 amb = "amb %s %s %s" % (Round(M.amb), Round(M.amb), Round(M.amb))
206 amb = "amb %s" % mirCol
209 emis = "emis %s" % mirCol
210 spec = "spec %s %s %s" % (Round(M.specCol[0]),
211 Round(M.specCol[1]), Round(M.specCol[2]))
213 trans = "trans %s" % (Round(1 - M.alpha))
214 mbuf = mbuf + "%s %s %s %s %s %s %s\n" \
215 % (material, rgb, amb, emis, spec, shi, trans)
217 self.mbuf = self.mbuf + mbuf
219 def OBJECT(self, type):
220 self.buf = self.buf + "OBJECT %s\n" % type
222 def name(self, name):
223 self.buf = self.buf + 'name "%s"\n' % name
225 def data(self, name):
226 self.buf = self.buf + 'data %s\n%s\n' % (len(name), name)
228 def texture(self, faces):
231 if f.image and f.image.name not in tex:
232 tex.append(f.image.name)
235 print "\nAC3Db format supports only one texture per object."
236 print "Object %s -- using only the first one: %s\n" % (self.obj.name, tex[0])
237 image = Blender.Image.Get(tex[0])
238 buf = 'texture "%s"\n' % image.filename
241 buf += 'texrep %s %s\n' % (xrep, yrep)
242 self.buf = self.buf + buf
244 def rot(self, matrix):
248 r = map(Round, matrix[i])
249 not_I += (r[0] != '0.0')+(r[1] != '0.0')+(r[2] != '0.0')
250 not_I -= (r[i] == '1.0')
252 rot = "%s %s" % (rot, r[j])
255 buf = 'rot %s\n' % rot
256 self.buf = self.buf + buf
259 loc = map(Round, loc)
260 if loc[0] or loc[1] or loc[2]:
261 buf = 'loc %s %s %s\n' % (loc[0], loc[1], loc[2])
262 self.buf = self.buf + buf
264 def numvert(self, verts, matrix):
265 buf = "numvert %s\n" % len(verts)
266 m = matrix_mul(matrix)
267 verts = transform_verts(verts, m)
270 buf = buf + "%s %s %s\n" % (v[0], v[1], v[2])
271 self.buf = self.buf + buf
273 def numsurf(self, faces, hasFaceUV):
275 global ADD_DEFAULT_MAT
277 buf = "numsurf %s\n" % len(faces)
282 objmats = self.mesh.materials
283 for i in range(len(objmats)):
284 objmats[i] = objmats[i].name
286 m_idx = f.materialIndex
288 m_idx = mlist.index(objmats[m_idx])
291 print "\nNotice: object " + self.obj.name + \
292 " has at least one material *index* assigned"
293 print "\tbut not defined (not linked to an existing material)."
294 print "\tThis can cause some of its faces to be exported with a wrong color."
295 print "\tYou can fix the problem in the Blender Edit Buttons Window (F9).\n"
299 flaglow = (refs == 2) << 1
300 two_side = f.mode & Blender.NMesh.FaceModes['TWOSIDE']
301 two_side = (two_side > 0) << 1
302 flaghigh = f.smooth | two_side
303 buf = buf + "SURF 0x%d%d\n" % (flaghigh, flaglow)
304 if ADD_DEFAULT_MAT and objmats: m_idx += 1
305 buf = buf + "mat %s\n" % m_idx
306 buf = buf + "refs %s\n" % refs
309 vindex = self.mesh.verts.index(vert)
314 buf = buf + "%s %s %s\n" % (vindex, u, v)
315 self.buf = self.buf + buf
317 def kids(self, kids = 0):
318 self.buf = self.buf + "kids %s\n" % kids
320 # End of Class AC3DExport
322 from Blender import Draw, BGL
325 global SKIP_DATA, MIRCOL_AS_AMB, MIRCOL_AS_EMIS, ADD_DEFAULT_MAT, HELPME
329 BGL.glClearColor(0.6,0.6,0.9,1)
330 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
332 BGL.glRasterPos2i(20, 270)
333 Draw.Text("AC3D Exporter")
334 BGL.glRasterPos2i(30, 250)
335 Draw.Text("AC3D is a simple, affordable commercial 3d modeller that can be found at www.ac3d.org .")
336 BGL.glRasterPos2i(30, 230)
337 Draw.Text("It uses a nice text file format (extension .ac) which supports uv-textured meshes")
338 BGL.glRasterPos2i(30, 210)
339 Draw.Text("with parenting (grouping) information.")
340 BGL.glRasterPos2i(30, 190)
341 Draw.Text("Notes: AC3D has a 'data' token that assigns a string to each mesh, useful for games,")
342 BGL.glRasterPos2i(67, 170)
343 Draw.Text("for example. You can use Blender's mesh datablock name for that.")
344 BGL.glRasterPos2i(67, 150)
345 Draw.Text("The .ac format is well supported by the PLib 3d gaming library. You can use this")
346 BGL.glRasterPos2i(67, 130)
347 Draw.Text("exporter to have your Blender models in games and other apps written with PLib.")
348 Draw.Button("Ok", 21, 285, 80, 100, 40, "Click to return to previous screen.")
350 BGL.glClearColor(0,0,1,1)
351 BGL.glClear(BGL.GL_COLOR_BUFFER_BIT)
353 BGL.glRasterPos2i(20, 150)
354 Draw.Text("AC3D Exporter")
355 Draw.Toggle("Default mat", 1, 15, 100, 90, 20, ADD_DEFAULT_MAT, "Objects without materials assigned get a default (white) one automatically.")
356 Draw.Toggle("Skip data", 2, 15, 80, 90, 20, SKIP_DATA, "Don't export mesh names as 'data' info.")
357 Draw.Toggle("Mir2Amb", 3, 15, 50, 90, 20, MIRCOL_AS_AMB, "Get AC3D's ambient RGB color for each object from its mirror color in Blender.")
358 Draw.Toggle("Mir2Emis", 4, 15, 30, 90, 20, MIRCOL_AS_EMIS, "Get AC3D's emissive RGB color for each object from its mirror color in Blender.")
359 Draw.Button("Export All...", 10, 140, 80, 110, 30, "Export all meshes to an AC3D file.")
360 Draw.Button("Export Selected...", 11, 140, 40, 110, 30, "Export selected meshes to an AC3D file.")
361 Draw.Button("HELP", 20, 285, 80, 100, 40, "Click for additional info.")
362 Draw.Button("EXIT", 22, 285, 30, 100, 40, "Click to leave.")
370 if evt == Draw.ESCKEY:
372 Draw.Register(gui, event, b_event)
376 if evt == Draw.ESCKEY:
377 update_RegistryInfo()
382 Draw.Register(gui, event, b_event)
385 global ARG, SKIP_DATA, MIRCOL_AS_AMB, MIRCOL_AS_EMIS, ADD_DEFAULT_MAT
389 ADD_DEFAULT_MAT = 1 - ADD_DEFAULT_MAT
392 SKIP_DATA = 1 - SKIP_DATA
395 MIRCOL_AS_AMB = 1 - MIRCOL_AS_AMB
398 MIRCOL_AS_EMIS = 1 - MIRCOL_AS_EMIS
402 Blender.Window.FileSelector(fs_callback, "AC3D Export")
405 Blender.Window.FileSelector(fs_callback, "AC3D Export")
409 elif evt == 21: # leave Help screen
411 Draw.Register(gui, event, b_event)
413 update_RegistryInfo()
416 Draw.Register(gui, event, b_event)
418 def fs_callback(filename):
419 scene = Blender.Scene.GetCurrent()
420 test = AC3DExport(scene, filename)
422 if __script__['arg'] == 'config':
423 Draw.Register(gui, event, b_event)
425 Blender.Window.FileSelector(fs_callback, "AC3D Export")