]> git.tdb.fi Git - libs/gl.git/commitdiff
Rewrite VertexFormat to support an arbitary amount of components
authorMikko Rasa <tdb@tdb.fi>
Sat, 10 Jan 2009 10:07:36 +0000 (10:07 +0000)
committerMikko Rasa <tdb@tdb.fi>
Sat, 10 Jan 2009 10:07:36 +0000 (10:07 +0000)
Add support for generic vertex attributes to VertexFormat and VertexArray
Check for proper extensions in Shader constructor
Blender exporter: Export texture coordinates

13 files changed:
mesh_export.py
source/arb_vertex_program.cpp [new file with mode: 0644]
source/arb_vertex_program.h [new file with mode: 0644]
source/extension.cpp
source/mesh.cpp
source/shader.cpp
source/vertexarray.cpp
source/vertexarray.h
source/vertexarraybuilder.cpp
source/vertexbuilder.cpp
source/vertexbuilder.h
source/vertexformat.cpp
source/vertexformat.h

index fbb282281e3dce09e3ef3af62d14ec264a69f65b..7d21956a6cd1d14bab49c27161f2757c3b60ddd9 100644 (file)
@@ -66,6 +66,8 @@ class Vertex:
                return getattr(self._mvert, attr)
 
        def __cmp__(self, other):
+               if other is None:
+                       return 1
                return cmp(self.index, other.index)
 
        def __str__(self):
@@ -85,6 +87,8 @@ class Face:
                return getattr(self._mface, attr)
 
        def __cmp__(self, other):
+               if other is None:
+                       return 1
                return cmp(self.index, other.index)
 
        def __str__(self):
@@ -96,8 +100,7 @@ class Face:
                verts=self.verts[:]
                if reverse:
                        verts.reverse()
-               indices=[u.index for u in vt]
-               flags=[(v.index in indices) for v in verts]
+               flags=[(v in vt) for v in verts]
                l=len(verts)
                for i in range(l):
                        if flags[i] and not flags[(i+l-1)%l]:
@@ -151,7 +154,7 @@ class Mesh:
        def __getattr__(self, attr):
                return getattr(self._mesh, attr)
 
-       def split_vertices(self, debug=False):
+       def split_vertices(self, find_group_func, debug):
                groups=[]
                for v in self.verts:
                        for f in v.faces:
@@ -160,7 +163,7 @@ class Mesh:
                        vg=[]
                        for f in v.faces:
                                if not f.flag:
-                                       vg.append(self.find_group(v, f))
+                                       vg.append(find_group_func(v, f))
 
                        groups.append(vg)
 
@@ -189,15 +192,14 @@ class Mesh:
                                                if debug:
                                                        print "  Splitting edge %s with faces %s"%(e.key, e.faces)
 
-                                               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.other_face(f) not in g and 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
@@ -205,23 +207,27 @@ class Mesh:
                                                        e.v2=v
 
                                                e.key=make_edge_key(e.v1.index, e.v2.index)
-                                               if not e.smooth:
-                                                       self.edges[e.key]=e
+                                               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]
+       def split_smooth(self, debug=False):
+               self.split_vertices(self.find_smooth_group, debug)
+
+       def split_uv(self, debug=False):
+               self.split_vertices(self.find_uv_group, debug)
 
+       def find_smooth_group(self, vert, face):
                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:
+                               #if not other or other.index not in face_indices:
+                               if other not in vert.faces:
                                        continue
 
                                if e.smooth:
@@ -231,6 +237,16 @@ class Mesh:
 
                return queue
 
+       def find_uv_group(self, vert, face):
+               uv=face.uv[face.verts.index(vert)]
+               face.flag=True
+               group=[face]
+               for f in vert.faces:
+                       if not f.flag and f.uv[f.verts.index(vert)]==uv:
+                               f.flag=True
+                               group.append(f)
+               return group
+
        def compute_normals(self):
                for v in self.verts:
                        if v.faces:
@@ -242,6 +258,11 @@ class Mesh:
                                # XXX Should use edges to compute normal
                                v.no=Blender.Mathutils.Vector(0, 0, 1)
 
+       def compute_uv(self):
+               for v in self.verts:
+                       if v.faces:
+                               v.uv=v.faces[0].uv[v.faces[0].verts.index(v)]
+
        def create_strip(self, face, reverse, debug):
                edge=None
                for e in face.edges:
@@ -304,7 +325,7 @@ class Exporter:
                self.export_lines=True
                self.debug=False
                self.strip_debug=False
-               self.smooth_debug=False
+               self.split_debug=False
 
        def get_locality(self, strip):
                total=0
@@ -340,14 +361,20 @@ class Exporter:
                        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)
+               mesh.split_smooth(self.split_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))
+                       print "After smooth splitting %d vertices and %d edges"%(len(mesh.verts), len(mesh.edges))
 
                mesh.compute_normals()
 
+               if mesh.faceUV:
+                       mesh.split_uv(self.split_debug)
+                       if self.debug:
+                               print "After UV splitting %d vertices and %d edges"%(len(mesh.verts), len(mesh.edges))
+
+                       mesh.compute_uv()
+
                strips=[]
                if self.use_strips:
                        for f in mesh.faces:
@@ -504,7 +531,7 @@ class FrontEnd:
                self.export_lines=Blender.Draw.Create(self.config.get('export_lines', False))
                self.debug=Blender.Draw.Create(self.config.get('debug', False))
                self.strip_debug=Blender.Draw.Create(self.config.get('strip_debug', False))
-               self.smooth_debug=Blender.Draw.Create(self.config.get('smooth_debug', False))
+               self.split_debug=Blender.Draw.Create(self.config.get('split_debug', 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"),
@@ -513,7 +540,7 @@ class FrontEnd:
                                ("Debugging options"),
                                ("Debug", self.debug),
                                ("Debug strips", self.strip_debug),
-                               ("Debug smoothing", self.smooth_debug)])
+                               ("Debug splitting", self.split_debug)])
                if ret:
                        dirname=self.temp_config.get("dirname", Blender.sys.dirname(Blender.Get("filename")))
                        obj=bpy.data.scenes.active.objects.active
@@ -529,7 +556,7 @@ class FrontEnd:
                self.config['export_lines']=self.export_lines.val
                self.config['debug']=self.debug.val
                self.config['strip_debug']=self.strip_debug.val
-               self.config['smooth_debug']=self.smooth_debug.val
+               self.config['split_debug']=self.split_debug.val
                Blender.Registry.SetKey('mspgl_export', self.config, True)
 
                import os
@@ -543,7 +570,7 @@ class FrontEnd:
                exp.export_lines=self.export_lines.val
                exp.debug=self.debug.val
                exp.strip_debug=self.strip_debug.val
-               exp.smooth_debug=self.smooth_debug.val
+               exp.split_debug=self.split_debug.val
                exp.export()
 
 
diff --git a/source/arb_vertex_program.cpp b/source/arb_vertex_program.cpp
new file mode 100644 (file)
index 0000000..c68da2b
--- /dev/null
@@ -0,0 +1,137 @@
+#include "extension.h"
+#include "arb_vertex_program.h"
+
+namespace Msp {
+namespace GL {
+
+PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB=0;
+PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB=0;
+PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB=0;
+PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB=0;
+PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB=0;
+PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB=0;
+PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB=0;
+PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB=0;
+PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB=0;
+PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB=0;
+PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB=0;
+PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB=0;
+PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB=0;
+PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB=0;
+PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB=0;
+PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB=0;
+PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB=0;
+PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB=0;
+PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4NbvARB=0;
+PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4NivARB=0;
+PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4NsvARB=0;
+PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4NubARB=0;
+PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4NubvARB=0;
+PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4NuivARB=0;
+PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4NusvARB=0;
+PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB=0;
+PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB=0;
+PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB=0;
+PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB=0;
+PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB=0;
+PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB=0;
+PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB=0;
+PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB=0;
+PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB=0;
+PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB=0;
+PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB=0;
+PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB=0;
+PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB=0;
+PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB=0;
+PFNGLPROGRAMSTRINGARBPROC glProgramStringARB=0;
+PFNGLBINDPROGRAMARBPROC glBindProgramARB=0;
+PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB=0;
+PFNGLGENPROGRAMSARBPROC glGenProgramsARB=0;
+PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB=0;
+PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB=0;
+PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB=0;
+PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB=0;
+PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB=0;
+PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB=0;
+PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB=0;
+PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB=0;
+PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB=0;
+PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB=0;
+PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB=0;
+PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB=0;
+PFNGLGETPROGRAMIVARBPROC glGetProgramivARB=0;
+PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB=0;
+PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB=0;
+PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB=0;
+PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB=0;
+PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB=0;
+PFNGLISPROGRAMARBPROC glIsProgramARB=0;
+
+void init_arb_vertex_program()
+{
+       glVertexAttrib1dARB=reinterpret_cast<PFNGLVERTEXATTRIB1DARBPROC>(get_proc_address("glVertexAttrib1dARB"));
+       glVertexAttrib1dvARB=reinterpret_cast<PFNGLVERTEXATTRIB1DVARBPROC>(get_proc_address("glVertexAttrib1dvARB"));
+       glVertexAttrib1fARB=reinterpret_cast<PFNGLVERTEXATTRIB1FARBPROC>(get_proc_address("glVertexAttrib1fARB"));
+       glVertexAttrib1fvARB=reinterpret_cast<PFNGLVERTEXATTRIB1FVARBPROC>(get_proc_address("glVertexAttrib1fvARB"));
+       glVertexAttrib1sARB=reinterpret_cast<PFNGLVERTEXATTRIB1SARBPROC>(get_proc_address("glVertexAttrib1sARB"));
+       glVertexAttrib1svARB=reinterpret_cast<PFNGLVERTEXATTRIB1SVARBPROC>(get_proc_address("glVertexAttrib1svARB"));
+       glVertexAttrib2dARB=reinterpret_cast<PFNGLVERTEXATTRIB2DARBPROC>(get_proc_address("glVertexAttrib2dARB"));
+       glVertexAttrib2dvARB=reinterpret_cast<PFNGLVERTEXATTRIB2DVARBPROC>(get_proc_address("glVertexAttrib2dvARB"));
+       glVertexAttrib2fARB=reinterpret_cast<PFNGLVERTEXATTRIB2FARBPROC>(get_proc_address("glVertexAttrib2fARB"));
+       glVertexAttrib2fvARB=reinterpret_cast<PFNGLVERTEXATTRIB2FVARBPROC>(get_proc_address("glVertexAttrib2fvARB"));
+       glVertexAttrib2sARB=reinterpret_cast<PFNGLVERTEXATTRIB2SARBPROC>(get_proc_address("glVertexAttrib2sARB"));
+       glVertexAttrib2svARB=reinterpret_cast<PFNGLVERTEXATTRIB2SVARBPROC>(get_proc_address("glVertexAttrib2svARB"));
+       glVertexAttrib3dARB=reinterpret_cast<PFNGLVERTEXATTRIB3DARBPROC>(get_proc_address("glVertexAttrib3dARB"));
+       glVertexAttrib3dvARB=reinterpret_cast<PFNGLVERTEXATTRIB3DVARBPROC>(get_proc_address("glVertexAttrib3dvARB"));
+       glVertexAttrib3fARB=reinterpret_cast<PFNGLVERTEXATTRIB3FARBPROC>(get_proc_address("glVertexAttrib3fARB"));
+       glVertexAttrib3fvARB=reinterpret_cast<PFNGLVERTEXATTRIB3FVARBPROC>(get_proc_address("glVertexAttrib3fvARB"));
+       glVertexAttrib3sARB=reinterpret_cast<PFNGLVERTEXATTRIB3SARBPROC>(get_proc_address("glVertexAttrib3sARB"));
+       glVertexAttrib3svARB=reinterpret_cast<PFNGLVERTEXATTRIB3SVARBPROC>(get_proc_address("glVertexAttrib3svARB"));
+       glVertexAttrib4NbvARB=reinterpret_cast<PFNGLVERTEXATTRIB4NBVARBPROC>(get_proc_address("glVertexAttrib4NbvARB"));
+       glVertexAttrib4NivARB=reinterpret_cast<PFNGLVERTEXATTRIB4NIVARBPROC>(get_proc_address("glVertexAttrib4NivARB"));
+       glVertexAttrib4NsvARB=reinterpret_cast<PFNGLVERTEXATTRIB4NSVARBPROC>(get_proc_address("glVertexAttrib4NsvARB"));
+       glVertexAttrib4NubARB=reinterpret_cast<PFNGLVERTEXATTRIB4NUBARBPROC>(get_proc_address("glVertexAttrib4NubARB"));
+       glVertexAttrib4NubvARB=reinterpret_cast<PFNGLVERTEXATTRIB4NUBVARBPROC>(get_proc_address("glVertexAttrib4NubvARB"));
+       glVertexAttrib4NuivARB=reinterpret_cast<PFNGLVERTEXATTRIB4NUIVARBPROC>(get_proc_address("glVertexAttrib4NuivARB"));
+       glVertexAttrib4NusvARB=reinterpret_cast<PFNGLVERTEXATTRIB4NUSVARBPROC>(get_proc_address("glVertexAttrib4NusvARB"));
+       glVertexAttrib4bvARB=reinterpret_cast<PFNGLVERTEXATTRIB4BVARBPROC>(get_proc_address("glVertexAttrib4bvARB"));
+       glVertexAttrib4dARB=reinterpret_cast<PFNGLVERTEXATTRIB4DARBPROC>(get_proc_address("glVertexAttrib4dARB"));
+       glVertexAttrib4dvARB=reinterpret_cast<PFNGLVERTEXATTRIB4DVARBPROC>(get_proc_address("glVertexAttrib4dvARB"));
+       glVertexAttrib4fARB=reinterpret_cast<PFNGLVERTEXATTRIB4FARBPROC>(get_proc_address("glVertexAttrib4fARB"));
+       glVertexAttrib4fvARB=reinterpret_cast<PFNGLVERTEXATTRIB4FVARBPROC>(get_proc_address("glVertexAttrib4fvARB"));
+       glVertexAttrib4ivARB=reinterpret_cast<PFNGLVERTEXATTRIB4IVARBPROC>(get_proc_address("glVertexAttrib4ivARB"));
+       glVertexAttrib4sARB=reinterpret_cast<PFNGLVERTEXATTRIB4SARBPROC>(get_proc_address("glVertexAttrib4sARB"));
+       glVertexAttrib4svARB=reinterpret_cast<PFNGLVERTEXATTRIB4SVARBPROC>(get_proc_address("glVertexAttrib4svARB"));
+       glVertexAttrib4ubvARB=reinterpret_cast<PFNGLVERTEXATTRIB4UBVARBPROC>(get_proc_address("glVertexAttrib4ubvARB"));
+       glVertexAttrib4uivARB=reinterpret_cast<PFNGLVERTEXATTRIB4UIVARBPROC>(get_proc_address("glVertexAttrib4uivARB"));
+       glVertexAttrib4usvARB=reinterpret_cast<PFNGLVERTEXATTRIB4USVARBPROC>(get_proc_address("glVertexAttrib4usvARB"));
+       glVertexAttribPointerARB=reinterpret_cast<PFNGLVERTEXATTRIBPOINTERARBPROC>(get_proc_address("glVertexAttribPointerARB"));
+       glEnableVertexAttribArrayARB=reinterpret_cast<PFNGLENABLEVERTEXATTRIBARRAYARBPROC>(get_proc_address("glEnableVertexAttribArrayARB"));
+       glDisableVertexAttribArrayARB=reinterpret_cast<PFNGLDISABLEVERTEXATTRIBARRAYARBPROC>(get_proc_address("glDisableVertexAttribArrayARB"));
+       glProgramStringARB=reinterpret_cast<PFNGLPROGRAMSTRINGARBPROC>(get_proc_address("glProgramStringARB"));
+       glBindProgramARB=reinterpret_cast<PFNGLBINDPROGRAMARBPROC>(get_proc_address("glBindProgramARB"));
+       glDeleteProgramsARB=reinterpret_cast<PFNGLDELETEPROGRAMSARBPROC>(get_proc_address("glDeleteProgramsARB"));
+       glGenProgramsARB=reinterpret_cast<PFNGLGENPROGRAMSARBPROC>(get_proc_address("glGenProgramsARB"));
+       glProgramEnvParameter4dARB=reinterpret_cast<PFNGLPROGRAMENVPARAMETER4DARBPROC>(get_proc_address("glProgramEnvParameter4dARB"));
+       glProgramEnvParameter4dvARB=reinterpret_cast<PFNGLPROGRAMENVPARAMETER4DVARBPROC>(get_proc_address("glProgramEnvParameter4dvARB"));
+       glProgramEnvParameter4fARB=reinterpret_cast<PFNGLPROGRAMENVPARAMETER4FARBPROC>(get_proc_address("glProgramEnvParameter4fARB"));
+       glProgramEnvParameter4fvARB=reinterpret_cast<PFNGLPROGRAMENVPARAMETER4FVARBPROC>(get_proc_address("glProgramEnvParameter4fvARB"));
+       glProgramLocalParameter4dARB=reinterpret_cast<PFNGLPROGRAMLOCALPARAMETER4DARBPROC>(get_proc_address("glProgramLocalParameter4dARB"));
+       glProgramLocalParameter4dvARB=reinterpret_cast<PFNGLPROGRAMLOCALPARAMETER4DVARBPROC>(get_proc_address("glProgramLocalParameter4dvARB"));
+       glProgramLocalParameter4fARB=reinterpret_cast<PFNGLPROGRAMLOCALPARAMETER4FARBPROC>(get_proc_address("glProgramLocalParameter4fARB"));
+       glProgramLocalParameter4fvARB=reinterpret_cast<PFNGLPROGRAMLOCALPARAMETER4FVARBPROC>(get_proc_address("glProgramLocalParameter4fvARB"));
+       glGetProgramEnvParameterdvARB=reinterpret_cast<PFNGLGETPROGRAMENVPARAMETERDVARBPROC>(get_proc_address("glGetProgramEnvParameterdvARB"));
+       glGetProgramEnvParameterfvARB=reinterpret_cast<PFNGLGETPROGRAMENVPARAMETERFVARBPROC>(get_proc_address("glGetProgramEnvParameterfvARB"));
+       glGetProgramLocalParameterdvARB=reinterpret_cast<PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC>(get_proc_address("glGetProgramLocalParameterdvARB"));
+       glGetProgramLocalParameterfvARB=reinterpret_cast<PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC>(get_proc_address("glGetProgramLocalParameterfvARB"));
+       glGetProgramivARB=reinterpret_cast<PFNGLGETPROGRAMIVARBPROC>(get_proc_address("glGetProgramivARB"));
+       glGetProgramStringARB=reinterpret_cast<PFNGLGETPROGRAMSTRINGARBPROC>(get_proc_address("glGetProgramStringARB"));
+       glGetVertexAttribdvARB=reinterpret_cast<PFNGLGETVERTEXATTRIBDVARBPROC>(get_proc_address("glGetVertexAttribdvARB"));
+       glGetVertexAttribfvARB=reinterpret_cast<PFNGLGETVERTEXATTRIBFVARBPROC>(get_proc_address("glGetVertexAttribfvARB"));
+       glGetVertexAttribivARB=reinterpret_cast<PFNGLGETVERTEXATTRIBIVARBPROC>(get_proc_address("glGetVertexAttribivARB"));
+       glGetVertexAttribPointervARB=reinterpret_cast<PFNGLGETVERTEXATTRIBPOINTERVARBPROC>(get_proc_address("glGetVertexAttribPointervARB"));
+       glIsProgramARB=reinterpret_cast<PFNGLISPROGRAMARBPROC>(get_proc_address("glIsProgramARB"));
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/arb_vertex_program.h b/source/arb_vertex_program.h
new file mode 100644 (file)
index 0000000..a4c8dd0
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef MSP_GL_ARB_VERTEX_PROGRAM_
+#define MSP_GL_ARB_VERTEX_PROGRAM_
+
+#include "gl.h"
+#include <GL/glext.h>
+
+namespace Msp {
+namespace GL {
+
+extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
+extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
+extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
+extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
+extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
+extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
+extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
+extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
+extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
+extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
+extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
+extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
+extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
+extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
+extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
+extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
+extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
+extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
+extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4NbvARB;
+extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4NivARB;
+extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4NsvARB;
+extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4NubARB;
+extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4NubvARB;
+extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4NuivARB;
+extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4NusvARB;
+extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
+extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
+extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
+extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
+extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
+extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
+extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
+extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
+extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
+extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
+extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
+extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
+extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
+extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
+extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
+extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
+extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
+extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
+extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
+extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
+extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
+extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
+extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
+extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
+extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
+extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
+extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
+extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
+extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
+extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
+extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
+extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
+extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
+extern PFNGLISPROGRAMARBPROC glIsProgramARB;
+
+void init_arb_vertex_program();
+
+} // namespace GL
+} // namespace Msp
+
+#endif
index a5ad3191b88e518bae3116039a200a784bc0d6a8..ba7dd4020d4ce9164a39e525ae520073b9fbe1cc 100644 (file)
@@ -13,6 +13,7 @@ Distributed under the LGPL
 #include <msp/strings/utils.h>
 #include "arb_shader_objects.h"
 #include "arb_vertex_buffer_object.h"
+#include "arb_vertex_program.h"
 #include "arb_vertex_shader.h"
 #include "ext_framebuffer_object.h"
 #include "except.h"
@@ -45,6 +46,8 @@ bool is_supported(const string &ext)
                        init_arb_shader_objects();
                if(extensions.count("GL_ARB_vertex_shader"))
                        init_arb_vertex_shader();
+               if(extensions.count("GL_ARB_vertex_program"))
+                       init_arb_vertex_program();
                if(extensions.count("GL_EXT_framebuffer_object"))
                        init_ext_framebuffer_object();
                if(extensions.count("GL_ARB_vertex_buffer_object"))
index fec753d0d3938d157b93403cd47716539f30551c..7f50beb7b61bc055bb1e905529e6f91c9535c1fe 100644 (file)
@@ -13,7 +13,7 @@ namespace Msp {
 namespace GL {
 
 Mesh::Mesh():
-       vertices(NODATA)
+       vertices(VERTEX3)
 { }
 
 Mesh::Mesh(VertexFormat f):
index 93edafb45b35dab4dac34745cd404d51c1ad12e5..85451527c28bf8593aa64d8527555eff9aac7647 100644 (file)
@@ -33,9 +33,9 @@ void Shader::init(ShaderType t)
        compiled=false;
 
        if(t==FRAGMENT_SHADER)
-               static RequireExtension _ext("GL_ARB_fragment_program");
+               static RequireExtension _ext("GL_ARB_fragment_shader");
        else if(t==VERTEX_SHADER)
-               static RequireExtension _ext("GL_ARB_vertex_program");
+               static RequireExtension _ext("GL_ARB_vertex_shader");
 
        id=glCreateShaderObjectARB(t);
 }
index 3c17141cfb59a592264505c7c67956cc5a9fd355..de343bf7065a07aa573377a6e49be8114dd60356 100644 (file)
@@ -5,6 +5,7 @@ Copyright © 2007  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
+#include "arb_vertex_program.h"
 #include "extension.h"
 #include "gl.h"
 #include "version_1_2.h"
@@ -16,15 +17,11 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-VertexArray::VertexArray(VertexFormat f):
-       format(NODATA),
-       stride(get_stride(f)),
+VertexArray::VertexArray(const VertexFormat &f):
        vbuf(0),
        own_vbuf(false)
 {
-       // Reverse the format so the first item is in lowest bits.  This makes handling in bind() easier.
-       for(uint fmt=f; fmt; fmt>>=4)
-               format=(format, static_cast<VertexFormat>(fmt&15));
+       reset(f);
 }
 
 VertexArray::~VertexArray()
@@ -64,19 +61,23 @@ void VertexArray::clear()
        data.clear();
 }
 
-void VertexArray::reset(VertexFormat f)
+void VertexArray::reset(const VertexFormat &f)
 {
        clear();
-       format=NODATA;
-       for(uint fmt=f; fmt; fmt>>=4)
-               format=(format, static_cast<VertexFormat>(fmt&15));
+       format=f;
        stride=get_stride(format);
+
+       bool has_gen_attrs=false;
+       for(const unsigned char *c=format.begin(); (!has_gen_attrs && c!=format.end()); ++c)
+               has_gen_attrs=(*c>=ATTRIB1);
+       if(has_gen_attrs)
+               static RequireExtension _ext("GL_ARB_vertex_program");
 }
 
 void VertexArray::apply() const
 {
-       if(format==NODATA)
-               throw InvalidState("Trying to apply a vertex apply of format NODATA");
+       if(format.empty())
+               throw InvalidState("Trying to apply a vertex array with no data");
 
        if(vbuf)
                vbuf->bind();
@@ -85,28 +86,32 @@ void VertexArray::apply() const
        uint offset=0;
        uint found=0;
        uint bpv=stride*sizeof(float);
-       for(uint fmt=format; fmt; fmt>>=4)
+       for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
        {
-               uint sz=(fmt&3)+1;
-               switch(fmt&12)
+               uint sz=(*c&3)+1;
+               uint t=*c>>2;
+               switch(t)
                {
                case 0:
                        glVertexPointer(sz, GL_FLOAT, bpv, base+offset);
                        break;
-               case 4:
+               case 1:
                        glNormalPointer(GL_FLOAT, bpv, base+offset);
                        break;
-               case 8:
+               case 2:
                        glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset);
                        break;
-               case 12:
+               case 3:
                        if(sz==1)
                                glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset);
                        else
                                glColorPointer(sz, GL_FLOAT, bpv, base+offset);
                        break;
+               default:
+                       glVertexAttribPointerARB(t-3, sz, GL_FLOAT, false, bpv, base+offset);
+                       break;
                }
-               found|=1<<((fmt&12)>>2);
+               found|=1<<t;
                offset+=sz;
        }
 
@@ -114,6 +119,8 @@ void VertexArray::apply() const
        set_array(GL_NORMAL_ARRAY, found&2, 2);
        set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
        set_array(GL_COLOR_ARRAY, found&8, 8);
+       for(unsigned i=4; i<32; ++i)
+               set_array(i-3, (found>>i)&1, 1<<i);
 
        if(vbuf)
                VertexBuffer::unbind();
@@ -137,16 +144,22 @@ float *VertexArray::append()
        return &*data.end()-stride;
 }
 
-void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const
+void VertexArray::set_array(unsigned array, bool en, unsigned mask) const
 {
-       if((enabled_arrays&mask) && !bit)
+       if((enabled_arrays&mask) && !en)
        {
-               glDisableClientState(array);
+               if(mask<16)
+                       glDisableClientState(array);
+               else
+                       glDisableVertexAttribArrayARB(array);
                enabled_arrays&=~mask;
        }
-       else if(!(enabled_arrays&mask) && bit)
+       else if(!(enabled_arrays&mask) && en)
        {
-               glEnableClientState(array);
+               if(mask<16)
+                       glEnableClientState(array);
+               else
+                       glEnableVertexAttribArrayARB(array);
                enabled_arrays|=mask;
        }
 }
@@ -167,6 +180,10 @@ VertexArray::Loader::Loader(VertexArray &a):
        add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
        add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
        add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
+       add("attrib1",   static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
+       add("attrib2",   static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
+       add("attrib3",   static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
+       add("attrib4",   static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
 }
 
 
index 02fa64f70b0f0cfdfe5c9fa0c893433fa59818f1..ef7f6a24c23482292d38db863c56353159afed9e 100644 (file)
@@ -40,24 +40,24 @@ private:
        VertexArray(const VertexArray &);
        VertexArray &operator=(const VertexArray &);
 public:
-       VertexArray(VertexFormat);
+       VertexArray(const VertexFormat &);
        ~VertexArray();
 
-       VertexFormat get_format() const { return format; }
+       const VertexFormat &get_format() const { return format; }
        const std::vector<float> &get_data() const { return data; }
        void         use_vertex_buffer();
        void         use_vertex_buffer(VertexBuffer *);
        void         reserve(unsigned);
        unsigned     size() const { return data.size()/stride; }
        void         clear();
-       void         reset(VertexFormat);
+       void         reset(const VertexFormat &);
        void         apply() const;
        void         update_data();
        float        *append();
        float        *operator[](unsigned i) { return &data[0]+i*stride; }
        const float  *operator[](unsigned i) const { return &data[0]+i*stride; }
 private:
-       void set_array(unsigned, unsigned, unsigned) const;
+       void set_array(unsigned, bool, unsigned) const;
 
        static unsigned enabled_arrays;
 };
index f251632e9dfcaffce572aef546d056ee33d2b661..8e7e2cb5dd4433625747545cea073fee6715e89c 100644 (file)
@@ -23,10 +23,10 @@ VertexArrayBuilder::~VertexArrayBuilder()
 void VertexArrayBuilder::vertex_(float x, float y, float z, float w)
 {
        float *ptr=array.append();
-       for(uint fmt=array.get_format(); fmt; fmt>>=4)
+       for(const unsigned char *c=array.get_format().begin(); c!=array.get_format().end(); ++c)
        {
-               uint size=(fmt&3)+1;
-               switch(fmt&12)
+               uint size=(*c&3)+1;
+               switch(*c>>2)
                {
                case 0:
                        *ptr++=x;
@@ -34,18 +34,18 @@ void VertexArrayBuilder::vertex_(float x, float y, float z, float w)
                        if(size>=3) *ptr++=z;
                        if(size>=4) *ptr++=w;
                        break;
-               case 4:
-                       *+ptr++=nx;
-                       *+ptr++=ny;
-                       *+ptr++=nz;
+               case 1:
+                       *ptr++=nx;
+                       *ptr++=ny;
+                       *ptr++=nz;
                        break;
-               case 8:
-                       *+ptr++=ts;
-                       if(size>=2) *+ptr++=tt;
-                       if(size>=3) *+ptr++=tr;
-                       if(size>=4) *+ptr++=tq;
+               case 2:
+                       *ptr++=ts;
+                       if(size>=2) *ptr++=tt;
+                       if(size>=3) *ptr++=tr;
+                       if(size>=4) *ptr++=tq;
                        break;
-               case 12:
+               case 3:
                        if(size==1)
                        {
                                union { ubyte c[4]; float f; } u;
@@ -53,16 +53,23 @@ void VertexArrayBuilder::vertex_(float x, float y, float z, float w)
                                u.c[1]=static_cast<ubyte>(cg*255);
                                u.c[2]=static_cast<ubyte>(cb*255);
                                u.c[3]=static_cast<ubyte>(ca*255);
-                               *+ptr++=u.f;
+                               *ptr++=u.f;
                        }
                        else
                        {
-                               *+ptr++=cr;
-                               *+ptr++=cg;
-                               *+ptr++=cb;
+                               *ptr++=cr;
+                               *ptr++=cg;
+                               *ptr++=cb;
                                if(size>=4) *+ptr++=ca;
                        }
                        break;
+               default:
+                       const Attrib &a=av[(*c>>2)-4];
+                       *ptr++=a.x;
+                       if(size>=2) *ptr++=a.y;
+                       if(size>=3) *ptr++=a.z;
+                       if(size>=4) *ptr++=a.w;
+                       break;
                }
        }
 }
index 0b1d3f302fc41cff0cbdb8bc76279d09e2201f53..d6759d7e85be93d873f44b3c873b0cc2e4006fda 100644 (file)
@@ -16,5 +16,14 @@ VertexBuilder::VertexBuilder():
        nx(0), ny(0), nz(1)
 { }
 
+void VertexBuilder::attrib(unsigned i, float x, float y, float z, float w)
+{
+       Attrib &a=av[i];
+       a.x=x;
+       a.y=y;
+       a.z=z;
+       a.w=w;
+}
+
 } // namespace GL
 } // namespace Msp
index 1b2d02d17726d60b4f6e023bf304aa2b74d98363..3e02e1d47bd37837ba77e2740453d4738184ac41 100644 (file)
@@ -8,6 +8,7 @@ Distributed under the LGPL
 #ifndef MSP_GL_VERTEXBUILDER_H_
 #define MSP_GL_VERTEXBUILDER_H_
 
+#include <map>
 #include "types.h"
 
 namespace Msp {
@@ -24,6 +25,12 @@ data.  Attributes can be read from protected member variables.
 */
 class VertexBuilder
 {
+protected:
+       struct Attrib
+       {
+               float x, y, z, w;
+       };
+
 public:
        VertexBuilder();
        virtual ~VertexBuilder() { }
@@ -40,10 +47,15 @@ public:
        void color(ubyte r, ubyte g, ubyte b, ubyte a)    { color(r/255.f, g/255.f, b/255.f, a/255.f); }
        void color(float r, float g, float b)             { color(r, g, b, 1); }
        void color(float r, float g, float b, float a)    { cr=r; cg=g; cb=b; ca=a; }
+       void attrib(unsigned i, float x)                  { attrib(i, x, 0, 0, 1); }
+       void attrib(unsigned i, float x, float y)         { attrib(i, x, y, 0, 1); }
+       void attrib(unsigned i, float x, float y, float z) { attrib(i, x, y, z, 1); }
+       void attrib(unsigned i, float x, float y, float z, float w);
 protected:
        float cr, cg, cb, ca;  // Color
        float ts, tt, tr, tq;  // TexCoord
        float nx, ny, nz;     // Normal
+       std::map<unsigned, Attrib> av;
 
        virtual void vertex_(float, float, float, float) =0;
 };
index bf2d9095d77220333ac205a608375450c8ada8c9..232690ede2f99f2c7d1ebb8411d9ad442c68dffa 100644 (file)
@@ -5,16 +5,100 @@ Copyright © 2007  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
+#include <cstring>
+#include <msp/strings/lexicalcast.h>
+#include "except.h"
 #include "vertexformat.h"
 
 namespace Msp {
 namespace GL {
 
-uint get_stride(VertexFormat f)
+VertexFormat::VertexFormat():
+       data(0)
+{ }
+
+VertexFormat::VertexFormat(VertexComponent c):
+       data(new unsigned char[8])
+{
+       data[0]=1;
+       data[1]=c;
+}
+
+VertexFormat::VertexFormat(const VertexFormat &f):
+       data(0)
+{
+       if(f.data)
+       {
+               data=new unsigned char[f.data[0]/8+8];
+               memcpy(data, f.data, f.data[0]+1);
+       }
+}
+
+VertexFormat &VertexFormat::operator=(const VertexFormat &f)
+{
+       delete[] data;
+       if(f.data)
+       {
+               data=new unsigned char[f.data[0]/8+8];
+               memcpy(data, f.data, f.data[0]+1);
+       }
+       else
+               data=0;
+
+       return *this;
+}
+
+VertexFormat::~VertexFormat()
+{
+       delete[] data;
+}
+
+VertexFormat operator,(const VertexFormat &f, VertexComponent c)
+{
+       VertexFormat r=f;
+       if(r.data)
+       {
+               const unsigned char n=++r.data[0];
+               if((n&7)==7)
+               {
+                       unsigned char *newdt=new unsigned char[n+9];
+                       memcpy(newdt, r.data, n);
+                       delete r.data;
+                       r.data=newdt;
+               }
+               r.data[n]=c;
+       }
+       else
+       {
+               r.data=new unsigned char[8];
+               r.data[0]=1;
+               r.data[1]=c;
+       }
+
+       return r;
+}
+
+VertexFormat operator,(const VertexFormat &f, unsigned i)
+{
+       if(!f.data)
+               throw InvalidState("VertexFormat has no components");
+       VertexFormat r=f;
+       unsigned char *c=r.data+r.data[0];
+       if(*c<ATTRIB1)
+               throw InvalidState("Last component is not a generic attribute");
+       // VertexArray uses an unsigned to store flags for enabled arrays
+       if(i<1 || i>28)
+               throw InvalidParameterValue("Generic attribute index out of range");
+       *c+=(i-1)*4;
+
+       return r;
+}
+
+uint get_stride(const VertexFormat &f)
 {
        uint stride=0;
-       for(uint fmt=f; fmt; fmt>>=4)
-               stride+=(fmt&3)+1;
+       for(const unsigned char *i=f.begin(); i!=f.end(); ++i)
+               stride+=(*i&3)+1;
        return stride;
 }
 
@@ -24,11 +108,11 @@ std::istream &operator>>(std::istream &in, VertexFormat &f)
        in>>str;
 
        unsigned start=0;
-       f=NODATA;
 
        while(1)
        {
                unsigned underscore=str.find('_', start);
+               bool fail=false;
                if(!str.compare(start, underscore-start, "VERTEX2"))
                        f=(f,VERTEX2);
                else if(!str.compare(start, underscore-start, "VERTEX3"))
@@ -51,7 +135,32 @@ std::istream &operator>>(std::istream &in, VertexFormat &f)
                        f=(f,COLOR3_FLOAT);
                else if(!str.compare(start, underscore-start, "COLOR4F"))
                        f=(f,COLOR4_FLOAT);
+               else if(underscore>=start+8 && !str.compare(start, 6, "ATTRIB"))
+               {
+                       try
+                       {
+                               char n=str[start+6];
+                               unsigned i=lexical_cast<unsigned>(str.substr(start+7, underscore-start-7));
+                               if(n=='1')
+                                       f=(f,ATTRIB1,i);
+                               else if(n=='2')
+                                       f=(f,ATTRIB2,i);
+                               else if(n=='3')
+                                       f=(f,ATTRIB3,i);
+                               else if(n=='4')
+                                       f=(f,ATTRIB4,i);
+                               else
+                                       fail=true;
+                       }
+                       catch(const LexicalError &)
+                       {
+                               fail=true;
+                       }
+               }
                else
+                       fail=true;
+
+               if(fail)
                {
                        in.setstate(std::ios_base::failbit);
                        break;
index 3a0eb718f5a5937b1dcca4e5b786f241bdf8ff45..2432d7b60d54aec2fbf8e478cdfec5ff8971f90f 100644 (file)
@@ -14,9 +14,8 @@ Distributed under the LGPL
 namespace Msp {
 namespace GL {
 
-enum VertexFormat
+enum VertexComponent
 {
-       NODATA=0,
        VERTEX2=1,
        VERTEX3,
        VERTEX4,
@@ -28,10 +27,36 @@ enum VertexFormat
        COLOR4_UBYTE=12,
        COLOR3_FLOAT=14,
        COLOR4_FLOAT,
+       ATTRIB1=16,
+       ATTRIB2,
+       ATTRIB3,
+       ATTRIB4
 };
 
-inline VertexFormat operator,(VertexFormat a, VertexFormat b) { return VertexFormat(a<<4 | b); }
-uint get_stride(VertexFormat);
+struct VertexFormat
+{
+       unsigned char *data;
+
+       VertexFormat();
+       VertexFormat(VertexComponent);
+       VertexFormat(const VertexFormat &);
+       VertexFormat &operator=(const VertexFormat &);
+       ~VertexFormat();
+
+       bool empty() const { return !data || !data[0]; }
+       const unsigned char *begin() const { return data ? data+1 : 0; }
+       const unsigned char *end() const { return data ? data+1+data[0] : 0; }
+};
+
+VertexFormat operator,(const VertexFormat &f, VertexComponent c);
+inline VertexFormat operator,(VertexComponent c1, VertexComponent c2)
+{ return (VertexFormat(c1), c2); }
+
+VertexFormat operator,(const VertexFormat &f, unsigned i);
+inline VertexFormat operator,(VertexComponent c, unsigned i)
+{ return (VertexFormat(c), i); }
+
+uint get_stride(const VertexFormat &);
 std::istream &operator>>(std::istream &, VertexFormat &);
 
 } // namespace GL