]> git.tdb.fi Git - libs/gl.git/commitdiff
Add $Id$ to tag.*
authorMikko Rasa <tdb@tdb.fi>
Thu, 27 Dec 2007 17:12:27 +0000 (17:12 +0000)
committerMikko Rasa <tdb@tdb.fi>
Thu, 27 Dec 2007 17:12:27 +0000 (17:12 +0000)
Fix some memory leaks
Compiler shader programs in finish() instead of ~Loader() since it may throw
Blender exporter: Rewrite the smoothing algorithm to handle certain cases correctly

mesh_export.py
source/objectinstance.h
source/program.cpp
source/program.h
source/programdata.cpp
source/tag.cpp
source/tag.h

index dd8e5414e95ab3dcb3531eb968aec7d96c5f215e..eecd5a69835595faaa99c876c88be666c0a18cbf 100644 (file)
@@ -12,6 +12,10 @@ import math
 import bpy
 import Blender
 
+def make_edge_key(i1, i2):
+       return (min(i1, i2), max(i1, i2))
+
+
 class Edge:
        def __init__(self, me):
                if me.__class__==Edge:
@@ -25,13 +29,16 @@ class Edge:
        def __getattr__(self, attr):
                return getattr(self._medge, attr)
 
+       def __cmp__(self, other):
+               return self is other
+
        def check_smooth(self, limit):
                if len(self.faces)!=2:
                        return
 
                d=Blender.Mathutils.DotVecs(self.faces[0].no, self.faces[1].no)
                if (d>limit and self.faces[0].smooth and self.faces[1].smooth) or d>0.999:
-                       self.smooth=1
+                       self.smooth=True
 
        def other_face(self, f):
                if f.index==self.faces[0].index:
@@ -53,15 +60,24 @@ class Vertex:
                        self.uv=None
                self.orig_index=self._mvert.index
                self.flag=False
+               self.faces=[]
 
        def __getattr__(self, attr):
                return getattr(self._mvert, attr)
 
+       def __cmp__(self, other):
+               return cmp(self.index, other.index)
+
+       def __str__(self):
+               return "<Vert %d (%.4f, %.4f, %.4f) (%.4f, %.4f, %.4f)>"%(self.index, self.co[0], self.co[1], self.co[2], self.no[0], self.no[1], self.no[2])
+       
+       __repr__=__str__
+
 
 class Face:
        def __init__(self, mf):
                self._mface=mf
-               self.smooth_group=None
+               #self.smooth_group=None
                self.edges=[]
                self.verts=[v for v in mf.verts]
                self.flag=False
@@ -69,6 +85,14 @@ class Face:
        def __getattr__(self, attr):
                return getattr(self._mface, attr)
 
+       def __cmp__(self, other):
+               return cmp(self.index, other.index)
+
+       def __str__(self):
+               return "<Face %d (%s)>"%(self.index, " ".join([str(v.index) for v in self.verts]))
+       
+       __repr__=__str__
+
        def get_vertices_from(self, reverse, *vt):
                verts=self.verts[:]
                if reverse:
@@ -81,10 +105,9 @@ class Face:
                                return verts[i:]+verts[:i]
 
        def get_edge(self, v1, v2):     
-               i1=v1.index
-               i2=v2.index
+               key=make_edge_key(v1.index, v2.index)
                for e in self.edges:
-                       if (e.v1.index==i1 or e.v1.index==i2) and (e.v2.index==i1 or e.v2.index==i2):
+                       if e.key==key:
                                return e
 
 
@@ -162,6 +185,172 @@ class SmoothGroup:
                                e.faces.append(f)
 
 
+class Mesh:
+       def __init__(self, m):
+               self._mesh=m
+               self.verts=[Vertex(v) for v in m.verts]
+               self.faces=[Face(f) for f in m.faces]
+
+               for f in self.faces:
+                       for i in range(len(f.verts)):
+                               f.verts[i]=self.verts[f.verts[i].index]
+                               f.verts[i].faces.append(f)
+
+               self.edges=dict([(e.key, Edge(e)) for e in m.edges])
+               for f in self.faces:
+                       for k in f.edge_keys:
+                               e=self.edges[k]
+                               e.faces.append(self.faces[f.index])
+                               f.edges.append(e)
+
+               smooth_limit=math.cos(m.degr*math.pi/180)
+               for e in self.edges.itervalues():
+                       e.v1=self.verts[e.v1.index]
+                       e.v2=self.verts[e.v2.index]
+                       e.check_smooth(smooth_limit)
+
+       def __getattr__(self, attr):
+               return getattr(self._mesh, attr)
+
+       def split_vertices(self, debug=False):
+               groups=[]
+               for v in self.verts:
+                       for f in v.faces:
+                               f.flag=False
+
+                       vg=[]
+                       for f in v.faces:
+                               if not f.flag:
+                                       vg.append(self.find_group(v, f))
+
+                       groups.append(vg)
+
+               for i in range(len(self.verts)):
+                       if len(groups[i])==1:
+                               continue
+
+                       if debug:
+                               print "Vertex %s has %d groups"%(self.verts[i], len(groups[i]))
+
+                       for g in groups[i][1:]:
+                               v=Vertex(self.verts[i])
+                               v.index=len(self.verts)
+                               self.verts.append(v)
+
+                               if debug:
+                                       print "  -> %d"%v.index
+
+                               for f in g:
+                                       for j in range(len(f.edges)):
+                                               e=f.edges[j]
+
+                                               if e.v1!=self.verts[i] and e.v2!=self.verts[i]:
+                                                       continue
+
+                                               if debug:
+                                                       print "  Splitting edge %s with faces %s"%(e.key, e.faces)
+
+                                               old=e
+                                               if not e.smooth:
+                                                       if len(e.faces)>=2:
+                                                               k=e.faces.index(f)
+                                                               e.faces.remove(f)
+                                                               e=Edge(e)
+                                                               f.edges[j]=e
+                                                               e.faces.append(f)
+                                                       else:
+                                                               del self.edges[e.key]
+
+                                               if e.v1==self.verts[i]:
+                                                       e.v1=v
+                                               elif e.v2==self.verts[i]:
+                                                       e.v2=v
+
+                                               e.key=make_edge_key(e.v1.index, e.v2.index)
+                                               if not e.smooth:
+                                                       self.edges[e.key]=e
+
+                                       self.verts[i].faces.remove(f)
+                                       f.verts[f.verts.index(self.verts[i])]=v
+                                       v.faces.append(f)
+
+       def find_group(self, vert, face):
+               face_indices=[f.index for f in vert.faces]
+
+               face.flag=True
+               queue=[face]
+
+               for f in queue:
+                       for e in f.edges:
+                               other=e.other_face(f)
+                               if not other or other.index not in face_indices:
+                                       continue
+
+                               if e.smooth:
+                                       if not other.flag:
+                                               other.flag=True
+                                               queue.append(other)
+
+               return queue
+
+       def compute_normals(self):
+               for v in self.verts:
+                       if not v.faces:
+                               print "WTF?  Vertex %s without faces?"%v
+                       v.no=Blender.Mathutils.Vector()
+                       for f in v.faces:
+                               v.no+=f.no
+                       v.no.normalize()
+
+       def create_strip(self, face, reverse, debug):
+               edge=None
+               for e in face.edges:
+                       other=e.other_face(face)
+                       if other and not other.flag:
+                               edge=e
+                               break
+
+               if not edge:
+                       return None
+
+               if debug:
+                       print "Starting strip from %s, edge %s, reverse=%s"%([v.index for v in face.verts], (edge.v1.index, edge.v2.index), reverse)
+
+               verts=face.get_vertices_from(reverse, edge.v1, edge.v2)
+               if len(verts)==3:
+                       result=[verts[-1], verts[0]]
+               else:
+                       result=[verts[-2], verts[-1]]
+
+               while 1:
+                       verts=face.get_vertices_from(reverse, *result[-2:])
+                       k=len(result)%2
+                       if debug:
+                               print "  Adding %s"%face
+
+                       face.flag=True
+                       if len(verts)==4 and not k:
+                               result.append(verts[3])
+                       result.append(verts[2])
+                       if len(verts)==4 and k:
+                               result.append(verts[3])
+
+                       edge=face.get_edge(*result[-2:])
+
+                       if debug:
+                               print "  Next edge is %s"%(edge.key, )
+
+                       next=edge.other_face(face)
+                       if not next or next.flag:
+                               break
+                       face=next
+
+               if debug:
+                       print "  %s"%[v.index for v in result]
+
+               return result
+
+
 class Exporter:
        def __init__(self, fn):
                self.filename=fn
@@ -174,8 +363,9 @@ class Exporter:
                self.optimize_locality=True
                self.debug=False
                self.strip_debug=False
+               self.smooth_debug=False
 
-       def find_smooth_group(self, face, sg):
+       """def find_smooth_group(self, face, sg):
                face.smooth_group=sg
                sg.faces.append(face)
                queue=[face]
@@ -187,13 +377,13 @@ class Exporter:
                                        if other and not other.smooth_group:
                                                other.smooth_group=sg
                                                sg.faces.append(other)
-                                               queue.append(other)
+                                               queue.append(other)"""
 
-       def create_strip(self, face, reverse):
+       """def create_strip(self, face, reverse):
                edge=None
                for e in face.edges:
                        other=e.other_face(face)
-                       if other and other.smooth_group.index==face.smooth_group.index and not other.flag:
+                       if other and "other.smooth_group.index==face.smooth_group.index" and not other.flag:
                                edge=e
                                break
 
@@ -201,7 +391,7 @@ class Exporter:
                        return None
 
                if self.strip_debug:
-                       print "Starting strip from %s, edge %s, reverse=%s"%([v.index for v in face.verts], (edge.v1.index, edge.v2.index), reverse)
+                       print "Starting strip from %s, edge %s, reverse=%s"%([v.index for v in face.verts], edge.key, reverse)
 
                verts=face.get_vertices_from(reverse, edge.v1, edge.v2)
                if len(verts)==3:
@@ -228,14 +418,14 @@ class Exporter:
                                print "  Next edge is %s"%((edge.v1.index, edge.v2.index), )
 
                        next=edge.other_face(face)
-                       if not next or next.smooth_group.index!=face.smooth_group.index or next.flag:
+                       if not next or next.flag:
                                break
                        face=next
 
                if self.strip_debug:
                        print "  %s"%[v.index for v in result]
 
-               return result
+               return result"""
 
        def get_locality(self, strip):
                total=0
@@ -265,9 +455,23 @@ class Exporter:
                if obj.getType()!="Mesh":
                        raise Exception, "Can only export Mesh data"
 
-               mesh=obj.getData(mesh=True)
+               mesh=Mesh(obj.getData(mesh=True))
+
+               if self.debug:
+                       ntris=sum([len(f.verts)-2 for f in mesh.faces])
+                       print "Starting with %d vertices, %d faces (%d triangles) and %d edges"%(len(mesh.verts), len(mesh.faces), ntris, len(mesh.edges))
+
+               mesh.split_vertices(self.smooth_debug)
+
+               if self.debug:
+                       ntris=sum([len(f.verts)-2 for f in mesh.faces])
+                       print "After splitting %d vertices, %d faces (%d triangles) and %d edges"%(len(mesh.verts), len(mesh.faces), ntris, len(mesh.edges))
+
+               mesh.compute_normals()
+
+               #return
 
-               faces=[Face(f) for f in mesh.faces]
+               """faces=[Face(f) for f in mesh.faces]
 
                edges=dict([(e.key, Edge(e)) for e in mesh.edges])
                for f in faces:
@@ -307,27 +511,32 @@ class Exporter:
                        for i in range(len(smooth_groups)):
                                sg=smooth_groups[i]
                                print "  %d: %d faces, %d vertices"%(i, len(sg.faces), len(sg.verts))
-                       print "%d vertices total"%len(verts)
+                       print "%d vertices total"%len(verts)"""
 
                strips=[]
                if self.use_strips:
+                       for f in mesh.faces:
+                               f.flag=False
+
                        while 1:
                                best=5
                                face=None
-                               for f in faces:
+                               for f in mesh.faces:
                                        if f.flag:
                                                continue
                                        score=0
                                        for e in f.edges:
                                                other=e.other_face(f)
-                                               if other and other.smooth_group.index==f.smooth_group.index and not other.flag:
+                                               if other and not other.flag:
                                                        score+=1
                                        if score>0 and score<best:
                                                face=f
                                                best=score
+
                                if not face:
                                        break
-                               strip=self.create_strip(face, self.use_degen_tris and sum([len(s) for s in strips])%2)
+
+                               strip=mesh.create_strip(face, self.use_degen_tris and sum([len(s) for s in strips])%2, self.strip_debug)
                                if strip:
                                        strips.append(strip)
 
@@ -335,8 +544,8 @@ class Exporter:
                                print "%d strips:"%len(strips)
                                for i in range(len(strips)):
                                        print "  %d: %d indices"%(i, len(strips[i]))
-                               print "%d loose faces"%len([f for f in faces if not f.flag])
-                               nind=sum([len(s) for s in strips])+sum([len(f.verts) for f in faces if not f.flag])
+                               print "%d loose faces"%len([f for f in mesh.faces if not f.flag])
+                               nind=sum([len(s) for s in strips])+sum([len(f.verts) for f in mesh.faces if not f.flag])
                                print "%d indices total"%nind
 
                        if self.use_degen_tris:
@@ -346,7 +555,7 @@ class Exporter:
                                                big_strip+=[big_strip[-1], s[0]]
                                        big_strip+=s
 
-                               for f in faces:
+                               for f in mesh.faces:
                                        if not f.flag:
                                                if len(big_strip)%2:
                                                        order=(-1, -2, 0, 1)
@@ -383,12 +592,12 @@ class Exporter:
                                        flw=followers[vert.index]
                                        best=0
                                        for n in flw:
-                                               if flw[n]>best and not verts[n].flag:
-                                                       next=verts[n]
+                                               if flw[n]>best and not mesh.verts[n].flag:
+                                                       next=mesh.verts[n]
                                                        best=flw[n]+0.9/abs(vert.index-n)
 
                                if not next:
-                                       for v in verts:
+                                       for v in mesh.verts:
                                                if not v.flag:
                                                        next=v
                                                        break
@@ -397,10 +606,10 @@ class Exporter:
 
                                vert=next
 
-                       verts=verts2
+                       mesh.verts=verts2
 
-                       for i in range(len(verts)):
-                               verts[i].index=i
+                       for i in range(len(mesh.verts)):
+                               mesh.verts[i].index=i
 
                        if self.debug:
                                print "Locality after optimization: "+" ".join(["%.3f"%self.get_locality(s) for s in strips])
@@ -411,7 +620,7 @@ class Exporter:
                self.out_file.write("_VERTEX3\n{\n")
                norm=None
                uv=None
-               for v in verts:
+               for v in mesh.verts:
                        if v.no!=norm:
                                self.out_file.write("\tnormal3 %f %f %f;\n"%tuple(v.no))
                                norm=v.no
@@ -431,7 +640,7 @@ class Exporter:
                        self.out_file.write(";\n};\n")
 
                first=True
-               for f in faces:
+               for f in mesh.faces:
                        if not f.flag:
                                if first:
                                        self.out_file.write("batch TRIANGLES\n{\n")
@@ -449,13 +658,15 @@ class FrontEnd:
                self.optimize_locality=Blender.Draw.Create(True)
                self.debug=Blender.Draw.Create(False)
                self.strip_debug=Blender.Draw.Create(False)
+               self.smooth_debug=Blender.Draw.Create(False)
                ret=Blender.Draw.PupBlock("Export MSP GL mesh",
                        [("Use strips", self.use_strips, "Generage OpenGL triangle strips"),
                                ("Use degen tris", self.use_degen_tris, "Use degenerate triangles to combine triangle strips"),
                                ("Optimize locality", self.optimize_locality),
                                ("Debugging options"),
                                ("Debug", self.debug),
-                               ("Debug strips", self.strip_debug)])
+                               ("Debug strips", self.strip_debug),
+                               ("Debug smoothing", self.smooth_debug)])
                if ret:
                        Blender.Window.FileSelector(self.export, "Export MSP GL mesh", Blender.sys.makename(ext='.mesh'))
 
@@ -469,6 +680,7 @@ class FrontEnd:
                exp.optimize_locality=self.optimize_locality.val
                exp.debug=self.debug.val
                exp.strip_debug=self.strip_debug.val
+               exp.smooth_debug=self.smooth_debug.val
                exp.export()
 
 
index 12e0d7fb561de95018c3ca6811bfab28cba4de75..00e98791006a17eafd098cda51a2b12d5cf4809d 100644 (file)
@@ -23,6 +23,9 @@ class ObjectPass;
 Represents a single instance of an Object.  An application can derive another
 class from this and overload the hook functions to specify location and other
 instance-specific parameters for the rendered objects.
+
+The finish_render function generally should clean up everything done by
+setup_render, unless the rendering sequence is known to allow otherwise.
 */
 class ObjectInstance: public Renderable
 {
index f057ea74aefbfe75d4aa447866d6a57a4cf05288..2ed6fba8800c9f804127827ec85eca65a95bcea9 100644 (file)
@@ -182,11 +182,6 @@ Program::Loader::Loader(Program &p):
        add("attribute",       &Loader::attribute);
 }
 
-Program::Loader::~Loader()
-{
-       prog.link();
-}
-
 void Program::Loader::vertex_shader(const string &src)
 {
        prog.attach_shader(*new Shader(VERTEX_SHADER, src));
@@ -202,5 +197,10 @@ void Program::Loader::attribute(uint i, const string &n)
        prog.bind_attribute(i, n);
 }
 
+void Program::Loader::finish()
+{
+       prog.link();
+}
+
 } // namespace GL
 } // namespace Msp
index ed5410076244bcb0f4c8d16e08482354a3d26ba7..3b86a9c6d17d4af1af0ae0f1596eb67246799733 100644 (file)
@@ -37,12 +37,12 @@ public:
 
        public:
                Loader(Program &);
-               ~Loader();
 
        private:
                void vertex_shader(const std::string &);
                void fragment_shader(const std::string &);
                void attribute(uint, const std::string &);
+               virtual void finish();
        };
 
        Program();
index af2679a5965bbd932082b679ffe88f135ff47434..f627f2f1039c7fbefb12d198b5937217d3ca7108 100644 (file)
@@ -29,7 +29,10 @@ ProgramData::~ProgramData()
 void ProgramData::uniform(int index, Uniform *uni)
 {
        if(index<0)
+       {
+               delete uni;
                return;
+       }
 
        map<int, Uniform *>::iterator i=data.find(index);
        if(i!=data.end())
index c8041e0d0331c8c20fc7f78a657b39d651e5daab..8e29bee1f3eba6f97665bc9abd0e3fb60dd24d99 100644 (file)
@@ -1,3 +1,10 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
 #include "tag.h"
 
 namespace Msp {
index 87d4af656d9a8cea87969f7c966ac6d74d7fb26e..b2d4fd512b9a10c4c777950eda43ed8943005b9e 100644 (file)
@@ -1,3 +1,10 @@
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
 #ifndef MSP_GL_TAG_H_
 #define MSP_GL_TAG_H_