]> git.tdb.fi Git - libs/gl.git/blobdiff - blender/io_mesh_mspgl/export_mspgl.py
Add a Blender 2.5 port of the exporter
[libs/gl.git] / blender / io_mesh_mspgl / export_mspgl.py
diff --git a/blender/io_mesh_mspgl/export_mspgl.py b/blender/io_mesh_mspgl/export_mspgl.py
new file mode 100644 (file)
index 0000000..6de38f8
--- /dev/null
@@ -0,0 +1,353 @@
+# $Id: mesh_export.py 137 2010-12-05 19:22:35Z tdb $
+
+import bpy
+
+class VertexCache:
+       def __init__(self, size):
+               self.size = size
+               self.slots = [-1]*self.size
+
+       def fetch(self, v):
+               hit = v.index in self.slots
+               if hit:
+                       self.slots.remove(v.index)
+               self.slots.append(v.index)
+               if not hit:
+                       del self.slots[0]
+               return hit
+
+       def fetch_strip(self, strip):
+               hits = 0
+               for v in strip:
+                       if self.fetch(v):
+                               hits += 1
+               return hits
+
+       def test_strip(self, strip):
+               hits = 0
+               for i in range(len(strip)):
+                       if i>=self.size:
+                               break
+                       if strip[i].index in self.slots[i:]:
+                               hits += 1
+               return hits
+
+
+class OutFile:
+       def __init__(self, fn):
+               if fn==None:
+                       self.file = sys.stdout
+               else:
+                       self.file = open(fn, "w")
+               self.indent = 0
+
+       def make(self, kwd, *params):
+               pstr = ""
+               for p in params:
+                       if type(p)==float:
+                               pstr += " %.6g"%p
+                       else:
+                               pstr += " %s"%p
+               return "%s%s"%(kwd, pstr)
+
+       def write(self, kwd, *params):
+               self.file.write("%s%s;\n"%('\t'*self.indent, self.make(kwd, *params)))
+
+       def begin(self, kwd, *params):
+               i = '\t'*self.indent
+               self.file.write("%s%s\n%s{\n"%(i, self.make(kwd, *params), i))
+               self.indent += 1
+
+       def end(self):
+               self.indent -= 1
+               self.file.write("%s};\n"%('\t'*self.indent))
+
+
+class Exporter:
+       def __init__(self):
+               self.use_strips = True
+               self.use_degen_tris = True
+               self.max_strip_len = 1024
+               self.optimize_cache = False
+               self.cache_size = 64
+               self.export_lines = True
+               self.tbn_vecs = False
+               self.compound = False
+               self.object = False
+               self.material_tex = False
+
+       def stripify(self, mesh, progress = None):
+               for f in mesh.faces:
+                       f.flag = False
+
+               faces_done = 0
+               strips = []
+               loose = []
+
+               cache = None
+               if self.optimize_cache:
+                       cache = VertexCache(self.cache_size)
+
+               island = []
+               island_strips = []
+               while 1:
+                       if not island:
+                               queue = []
+                               for f in mesh.faces:
+                                       if not f.flag:
+                                               f.flag = True
+                                               queue.append(f)
+                                               break
+
+                               if not queue:
+                                       break
+
+                               while queue:
+                                       f = queue[0]
+                                       del queue[0]
+                                       island.append(f)
+
+                                       for e in f.edges:
+                                               other = e.other_face(f)
+                                               if other and not other.flag:
+                                                       other.flag = True
+                                                       queue.append(other)
+
+                               for f in island:
+                                       f.flag = False
+
+                       best = 5
+                       face = None
+                       for f in island:
+                               if f.flag:
+                                       continue
+                               score = 0
+                               for e in f.edges:
+                                       other = e.other_face(f)
+                                       if other and not other.flag:
+                                               score += 1
+                               if score>0 and score<best:
+                                       face = f
+                                       best = score
+
+                       if not face:
+                               while island_strips:
+                                       best = 0
+                                       if cache:
+                                               best_hits = 0
+                                               for i in range(len(island_strips)):
+                                                       hits = cache.test_strip(island_strips[i])
+                                                       if hits>best_hits:
+                                                               best = i
+                                                               best_hits = hits
+
+                                       s = island_strips[best]
+                                       del island_strips[best]
+                                       strips.append(s)
+
+                                       if cache:
+                                               cache.fetch_strip(s)
+
+                               faces_done += len(island)
+                               if progress:
+                                       progress.set_progress(float(faces_done)/len(mesh.faces))
+
+                               loose += [f for f in island if not f.flag]
+                               for f in island:
+                                       f.flag = True
+
+                               island = []
+                               island_strips = []
+                               continue
+
+                       strip = mesh.create_strip(face, self.max_strip_len)
+                       if strip:
+                               island_strips.append(strip)
+
+               if cache:
+                       cache = VertexCache(self.cache_size)
+                       total_hits = 0
+
+               if self.use_degen_tris and strips:
+                       big_strip = []
+
+                       for s in strips:
+                               if big_strip:
+                                       glue = [big_strip[-1], s[0]]
+                                       if len(big_strip)%2:
+                                               glue += [s[0]]
+
+                                       big_strip += glue
+                                       if cache:
+                                               total_hits += cache.fetch_strip(glue)
+
+                               big_strip += s
+                               if cache:
+                                       total_hits += cache.fetch_strip(s)
+
+                       for f in loose:
+                               if len(big_strip)%2:
+                                       order = (-1, -2, 0, 1)
+                               else:
+                                       order = (0, 1, -1, -2)
+                               vertices = [f.vertices[i] for i in order[:len(f.vertices)]]
+
+                               if big_strip:
+                                       glue = [big_strip[-1], vertices[0]]
+                                       big_strip += glue
+                                       if cache:
+                                               total_hits += cache.fetch_strip(glue)
+
+                               big_strip += vertices
+                               if cache:
+                                       total_hits += cache.fetch_strip(vertices)
+
+                       strips = [big_strip]
+                       loose = []
+
+               return strips, loose
+
+       def export(self, context, fn):
+               if self.compound:
+                       objs = context.selected_objects
+               else:
+                       objs = [context.active_object]
+
+               if not objs:
+                       raise Exception("Nothing to export")
+               for o in objs:
+                       if o.type!="MESH":
+                               raise Exception("Can only export Mesh data")
+
+               from .mesh import Mesh
+               from .util import Progress
+
+               progress = Progress()
+               progress.set_task("Preparing", 0.0, 0.0)
+
+               mesh = None
+               bmeshes = []
+               for o in objs:
+                       bmesh = o.create_mesh(context.scene, True, "PREVIEW")
+                       bmeshes.append(bmesh)
+                       if not mesh:
+                               mesh = Mesh(bmesh)
+                       else:
+                               mesh.splice(Mesh(bmesh))
+
+               progress.set_task("Smoothing", 0.05, 0.35)
+               mesh.split_smooth()
+
+               mesh.compute_normals()
+
+               if self.material_tex:
+                       mesh.generate_material_uv()
+
+               if mesh.has_uv:
+                       progress.set_task("Splitting UVs", 0.35, 0.65)
+                       mesh.split_uv()
+
+                       mesh.compute_uv()
+                       if self.tbn_vecs:
+                               mesh.compute_tbn()
+
+               strips = []
+               loose = mesh.faces
+               if self.use_strips:
+                       progress.set_task("Creating strips", 0.65, 0.95)
+                       strips, loose = self.stripify(mesh, progress)
+
+               progress.set_task("Writing file", 0.95, 1.0)
+
+               out_file = OutFile(fn)
+               if self.object:
+                       out_file.begin("mesh")
+
+               fmt = "NORMAL3"
+               if mesh.has_uv:
+                       fmt += "_TEXCOORD2"
+                       if self.tbn_vecs:
+                               fmt += "_ATTRIB33_ATTRIB34"
+               fmt += "_VERTEX3"
+               out_file.begin("vertices", fmt)
+               normal = None
+               uv = None
+               tan = None
+               bino = None
+               for v in mesh.vertices:
+                       if v.normal!=normal:
+                               out_file.write("normal3", *v.normal)
+                               normal = v.normal
+                       if v.uv!=uv:
+                               out_file.write("texcoord2", *v.uv)
+                               uv = v.uv
+                       if v.tan!=tan:
+                               out_file.write("attrib3", 3, *v.tan)
+                               tan = v.tan
+                       if v.bino!=bino:
+                               out_file.write("attrib3", 4, *v.bino)
+                               bino = v.bino
+                       out_file.write("vertex3", *v.co)
+               out_file.end()
+               for s in strips:
+                       out_file.begin("batch", "TRIANGLE_STRIP")
+                       indices = []
+                       n = 0
+                       for v in s:
+                               indices.append(v.index)
+                               if len(indices)>=32:
+                                       out_file.write("indices", *indices)
+                                       indices = []
+                       if indices:
+                               out_file.write("indices", *indices)
+                       out_file.end()
+
+               if loose:
+                       out_file.begin("batch", "TRIANGLES")
+                       for f in loose:
+                               for i in range(2, len(f.vertices)):
+                                       out_file.write("indices", f.vertices[0].index, f.vertices[i-1].index, f.vertices[i].index)
+                       out_file.end()
+
+               if self.export_lines and mesh.lines:
+                       out_file.write("batch", "LINES")
+                       for l in mesh.lines:
+                               out_file.write("indices", l.vertices[0].index, l.vertices[1].index)
+                       out_file.end()
+
+               if self.object:
+                       out_file.end()
+                       out_file.begin("technique")
+                       out_file.begin("pass", '""')
+                       if self.material_tex:
+                               out_file.begin("material")
+                               out_file.write("diffuse", 1.0, 1.0, 1.0, 1.0)
+                               out_file.end()
+                               out_file.begin("texunit", 0)
+                               out_file.begin("texture2d")
+                               out_file.write("min_filter", "NEAREST")
+                               out_file.write("mag_filter", "NEAREST")
+                               out_file.write("storage", "RGB", len(mesh.materials), 1)
+                               texdata = '"'
+                               for m in mesh.materials:
+                                       color = [int(c*255) for c in m.diffuse_color]
+                                       texdata += "\\x%02X\\x%02X\\x%02X"%tuple(color)
+                               texdata += '"'
+                               out_file.write("raw_data", texdata)
+                               out_file.end()
+                               out_file.end()
+                       elif mesh.materials:
+                               m = mesh.materials[0]
+                               out_file.begin("material")
+                               out_file.write("diffuse", m.R, m.G, m.B, 1.0)
+                               out_file.write("ambient", m.R*m.amb, m.G*m.amb, m.B*m.amb, 1.0)
+                               out_file.write("specular", m.specR*m.spec, m.specG*m.spec, m.specB*m.spec, 1.0)
+                               out_file.write("shininess", m.hard);
+                               out_file.end()
+                       out_file.end()
+                       out_file.end()
+
+               progress.set_task("Done", 1.0, 1.0)
+
+               for m in bmeshes:
+                       bpy.data.meshes.remove(m)