use f.area where possible over python function and use len(mface) over len(mface.v)
[blender.git] / release / scripts / nendo_export.py
1 #!BPY
2
3 """
4 Name: 'Nendo (.ndo)...'
5 Blender: 232
6 Group: 'Export'
7 Tooltip: 'Export selected mesh to Nendo File Format (*.ndo)'
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 to Nendo file format.
17
18 Nendo is (was) a commercial polygon modeler that has about half of the
19 features found in Wings. The .ndo file format is a simple, uncompressed,
20 memory dump of structures that represent the mesh objects, uv coords,
21 and image textures.
22
23 Usage:<br>
24         Select meshes to be exported and run this script from "File->Export" menu.
25
26 Supported:<br>
27         1. Exports meshes only. Hint: use ALT-C to convert non-mesh objects,
28 and CTRL-ALT-A if you have "dupliverts" objects.<br>
29         2. Exports Vertex Colors & Radiosity Solutions.
30
31 Missing:<br>
32         Materials and UV Coordinates info will be ignored.
33
34 Known issues:<br>
35         Exports only well-behaved and topologically correct meshes (i.e,
36 closed meshes, manifolds, meshes imported from wings, etc). The mesh
37 cannot have duplicate vertices, missing faces (holes), open edges, etc.<br>
38         PowerUser Hint: In editmode, if CTRL-ALT-SHIFT-M results in a selection,
39 then your mesh is not a manifold and most likely will not export.
40
41 Notes:<br>
42         Blender & Wings can read/write ndo files with a maximum of 65,535 edges.
43 Nendo can read/write ndo files with a maximum of 32,767 edges.<br>
44         If you have a very large mesh that you want to import into nendo, modify
45 the 'write_edge_table' function to use a signed integer (i.e., ">h") for the 'len(edge_table)'
46 field.
47 """
48
49 # $Id$
50 #
51 # +---------------------------------------------------------+
52 # | Copyright (c) 2001 Anthony D'Agostino                   |
53 # | http://www.redrival.com/scorpius                        |
54 # | scorpius@netzero.com                                    |
55 # | September 25, 2001                                      |
56 # | Read and write Nendo File Format (*.nendo)              |
57 # +---------------------------------------------------------+
58
59 # ***** BEGIN GPL LICENSE BLOCK *****
60 #
61 # This program is free software; you can redistribute it and/or
62 # modify it under the terms of the GNU General Public License
63 # as published by the Free Software Foundation; either version 2
64 # of the License, or (at your option) any later version.
65 #
66 # This program is distributed in the hope that it will be useful,
67 # but WITHOUT ANY WARRANTY; without even the implied warranty of
68 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
69 # GNU General Public License for more details.
70 #
71 # You should have received a copy of the GNU General Public License
72 # along with this program; if not, write to the Free Software Foundation,
73 # Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
74 #
75 # ***** END GPL LICENCE BLOCK *****
76
77 import Blender, meshtools
78 import struct, time, sys, os
79
80 # ==============================
81 # === Write Nendo 1.1 Format ===
82 # ==============================
83 def write(filename):
84         start = time.clock()
85
86         objects = Blender.Object.GetSelected()
87         objname = objects[0].name
88         meshname = objects[0].data.name
89         mesh = Blender.NMesh.GetRaw(meshname)
90         obj = Blender.Object.Get(objname)
91
92         numedges = len(mesh.verts)+len(mesh.faces)-2
93         maxedges = (2**16)-1    # Blender & Wings can read more edges
94         #maxedges = 32767               # Nendo can't
95         if numedges > maxedges:
96                 message = objname + " can't be exported to Nendo format (too many edges)."
97                 Blender.Draw.PupMenu("Nendo Export Error%t|"+message)
98                 return
99
100         edge_table = meshtools.generate_edgetable(mesh)
101
102         try:
103                 edge_table = meshtools.generate_edgetable(mesh)
104                 assert len(edge_table) <= maxedges
105         except:
106                 edge_table = {}
107                 message = "Unable to generate Edge Table for the object named " + meshname
108                 meshtools.print_boxed(message)
109                 Blender.Draw.PupMenu("Edge Table Error%t|"+message)
110                 Blender.Window.DrawProgressBar(1.0, "")    # clear progressbar
111                 return
112
113         file = open(filename, "wb")
114         write_header(file)
115         write_object_flags(file, objname)
116         write_edge_table(file, edge_table)
117         write_face_table(file, edge_table)
118         write_vert_table(file, edge_table, mesh)
119         write_texture(file)
120         file.close()
121
122         Blender.Window.DrawProgressBar(1.0, "")    # clear progressbar
123         print '\a\r',
124         end = time.clock()
125         seconds = " in %.2f %s" % (end-start, "seconds")
126         message = "Successfully exported " + os.path.basename(filename) + seconds
127         meshtools.print_boxed(message)
128
129 # ====================
130 # === Write Header ===
131 # ====================
132 def write_header(file):
133         file.write("nendo 1.1")
134         file.write("\0\0")
135         file.write("\1") # numobjects
136
137 # ==========================
138 # === Write Object Flags ===
139 # ==========================
140 def write_object_flags(file, objname):
141         file.write("\1") # good flag
142         file.write(struct.pack(">H", len(objname)))
143         file.write(objname)
144         file.write("\1"*4)
145         data = struct.pack(">18f",0,0,0,1,1,1,1,1,1,1,1,1,0.2,0.2,0.2,1,100,1)
146         data = "<<<< Nendo Export Script for Blender -- (c) 2004 Anthony D'Agostino >>>>"
147         file.write(data)
148
149 # ========================
150 # === Write Edge Table ===
151 # ========================
152 def write_edge_table(file, edge_table):
153         "+--------------------------------------+"
154         "| Wings: Sv Ev | Lf Rf | Lp Ls | Rp Rs |"
155         "| Nendo: Ev Sv | Lf Rf | Ls Rs | Rp Lp |"
156         "+--------------------------------------+"
157         #$print "edge_table"; pprint.pprint(edge_table)
158         file.write(struct.pack(">H", len(edge_table)))
159         keys = edge_table.keys()
160         keys.sort()
161         for key in keys:
162                 file.write(struct.pack(">2H", key[0], key[1]))                          # Ev Sv
163                 file.write(struct.pack(">2H", edge_table[key][0], edge_table[key][1]))  # Lf Rf
164                 file.write(struct.pack(">2H", edge_table[key][3], edge_table[key][5]))  # Ls Rs
165                 file.write(struct.pack(">2H", edge_table[key][4], edge_table[key][2]))  # Rp Lp
166                 file.write(struct.pack(">1B", 0))                                       # Hard flag
167                 try:
168                         r1,g1,b1 = map(lambda x:x*255, edge_table[key][8])
169                         r2,g2,b2 = map(lambda x:x*255, edge_table[key][7])
170                 except:
171                         r1,g1,b1 = map(lambda x:x*255, [0.9,0.8,0.7])
172                         r2,g2,b2 = r1,g1,b1
173                 file.write(struct.pack(">8B", r1,g1,b1,0,r2,g2,b2,0))
174
175 # ========================
176 # === Write Face Table ===
177 # ========================
178 def write_face_table(file, edge_table):
179         face_table = build_face_table(edge_table)
180         #$print "face_table"; pprint.pprint(face_table)
181         file.write(struct.pack(">H", len(face_table)))
182         keys = face_table.keys()
183         keys.sort()
184         for key in keys:
185                 file.write(struct.pack(">1H", face_table[key]))
186
187 # ========================
188 # === Write Vert Table ===
189 # ========================
190 def write_vert_table(file, edge_table, mesh):
191         vert_table = build_vert_table(edge_table)
192         #$print "vert_table"; pprint.pprint(vert_table)
193         file.write(struct.pack(">H", len(vert_table)))
194         keys = vert_table.keys()
195         keys.sort()
196         for key in keys:
197                 vertex = mesh.verts[key].co
198                 x,y,z = map(lambda x:x*10, vertex) # scale
199                 idx = vert_table[key]
200                 #$print "%i % f % f % f" % (idx, x, y, z)
201                 file.write(struct.pack(">1H3f", idx, x, z, -y))
202
203 # =====================
204 # === Write Texture ===
205 # =====================
206 def write_texture(file):
207         file.write("\0"*5)
208
209 # ========================
210 # === Build Vert Table ===
211 # ========================
212 def build_vert_table(edge_table): # For Nendo
213         vert_table = {}
214         for key in edge_table.keys():
215                 i = edge_table[key][6]
216                 Sv = key[0]
217                 Ev = key[1]
218                 vert_table[Sv] = i
219                 vert_table[Ev] = i
220         return vert_table
221
222 # ========================
223 # === Build Face Table ===
224 # ========================
225 def build_face_table(edge_table): # For Nendo
226         face_table = {}
227         for key in edge_table.keys():
228                 i = edge_table[key][6]
229                 Lf = edge_table[key][0]
230                 Rf = edge_table[key][1]
231                 face_table[Lf] = i
232                 face_table[Rf] = i
233         return face_table
234
235 def fs_callback(filename):
236         if filename.find('.ndo', -4) <= 0: filename += '.ndo'
237         write(filename)
238
239 Blender.Window.FileSelector(fs_callback, "Export Nendo")