X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=blender%2Fio_mesh_mspgl%2Fexport_mspgl.py;fp=blender%2Fio_mesh_mspgl%2Fexport_mspgl.py;h=6de38f8722935d884f45c4fbc441bca1e28926f7;hb=5028e8accde81677fc4a50c771b955cf324851b2;hp=0000000000000000000000000000000000000000;hpb=cd460f42d4468b80d3929aad5b93674fa0b2897c;p=libs%2Fgl.git diff --git a/blender/io_mesh_mspgl/export_mspgl.py b/blender/io_mesh_mspgl/export_mspgl.py new file mode 100644 index 00000000..6de38f87 --- /dev/null +++ b/blender/io_mesh_mspgl/export_mspgl.py @@ -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 scorebest_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)