]> git.tdb.fi Git - libs/gl.git/blobdiff - source/vertexsetup.cpp
Move vertex array object management out of Mesh
[libs/gl.git] / source / vertexsetup.cpp
diff --git a/source/vertexsetup.cpp b/source/vertexsetup.cpp
new file mode 100644 (file)
index 0000000..f6a71f4
--- /dev/null
@@ -0,0 +1,90 @@
+#include <msp/gl/extensions/arb_vertex_array_object.h>
+#include <msp/gl/extensions/arb_vertex_buffer_object.h>
+#include <msp/gl/extensions/arb_vertex_shader.h>
+#include "buffer.h"
+#include "gl.h"
+#include "vertexarray.h"
+#include "vertexsetup.h"
+
+namespace Msp {
+namespace GL {
+
+VertexSetup::VertexSetup():
+       dirty(false),
+       array(0),
+       index_buffer(0)
+{
+       static Require req(ARB_vertex_array_object);
+       glGenVertexArrays(1, &id);
+}
+
+VertexSetup::~VertexSetup()
+{
+       if(current()==this)
+               unbind();
+       glDeleteVertexArrays(1, &id);
+}
+
+void VertexSetup::set_vertex_array(const VertexArray &a)
+{
+       array = &a;
+       update();
+}
+
+void VertexSetup::set_index_buffer(const Buffer &ibuf)
+{
+       index_buffer = &ibuf;
+       update();
+}
+
+void VertexSetup::update() const
+{
+       if(current()!=this)
+       {
+               dirty = true;
+               return;
+       }
+
+       Bind bind_vbuf(array->get_buffer(), ARRAY_BUFFER);
+
+       const VertexFormat &fmt = array->get_format();
+       unsigned stride = get_stride(fmt)*sizeof(float);
+       float *ptr = 0;
+       for(const unsigned char *c=fmt.begin(); c!=fmt.end(); ++c)
+       {
+               unsigned t = get_component_type(*c);
+               if(t>=get_component_type(ATTRIB1))
+                       t -= get_component_type(ATTRIB1);
+               unsigned sz = get_component_size(*c);
+               if(*c==COLOR4_UBYTE)
+                       glVertexAttribPointer(t, 4, GL_UNSIGNED_BYTE, true, stride, ptr);
+               else
+                       glVertexAttribPointer(t, sz, GL_FLOAT, false, stride, ptr);
+               glEnableVertexAttribArray(t);
+               ptr += sz;
+       }
+
+       glBindBuffer(ELEMENT_ARRAY_BUFFER, index_buffer->get_id());
+}
+
+void VertexSetup::bind() const
+{
+       if(set_current(this))
+       {
+               glBindVertexArray(id);
+               if(dirty)
+               {
+                       update();
+                       dirty = false;
+               }
+       }
+}
+
+void VertexSetup::unbind()
+{
+       if(set_current(0))
+               glBindVertexArray(0);
+}
+
+} // namespace GL
+} // namespace Msp