]> git.tdb.fi Git - libs/gl.git/blobdiff - source/core/mesh.cpp
Use standard fixed-size integer types
[libs/gl.git] / source / core / mesh.cpp
index 3a79f3e53193c0c1c63cb32bde351926c2cb4a63..371b38b4894a96935cbd2c75326e790e38e45ce6 100644 (file)
@@ -1,6 +1,7 @@
 #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 <msp/gl/extensions/khr_debug.h>
 #include "buffer.h"
 #include "error.h"
 #include "mesh.h"
@@ -13,16 +14,15 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-Mesh::Mesh(ResourceManager *rm):
-       vertices(VERTEX3)
+Mesh::Mesh(ResourceManager *rm)
 {
        init(rm);
 }
 
-Mesh::Mesh(const VertexFormat &f, ResourceManager *rm):
-       vertices(f)
+Mesh::Mesh(const VertexFormat &f, ResourceManager *rm)
 {
        init(rm);
+       storage(f);
 }
 
 void Mesh::init(ResourceManager *rm)
@@ -31,7 +31,7 @@ void Mesh::init(ResourceManager *rm)
        ibuf = 0;
        dirty = 0;
        disallow_rendering = false;
-       winding = 0;
+       face_winding = NON_MANIFOLD;
 
        if(rm)
                set_manager(rm);
@@ -45,6 +45,15 @@ Mesh::~Mesh()
        delete ibuf;
 }
 
+void Mesh::storage(const VertexFormat &fmt)
+{
+       if(!vertices.get_format().empty())
+               throw invalid_operation("Mesh::storage");
+
+       vertices.set_format(fmt);
+       vtx_setup.set_format(fmt);
+}
+
 void Mesh::clear()
 {
        vertices.clear();
@@ -59,10 +68,15 @@ void Mesh::check_buffers(unsigned mask)
                if(!vbuf || (vbuf->get_size()>0 && vbuf->get_size()<req_size))
                {
                        delete vbuf;
-                       vbuf = new Buffer(ARRAY_BUFFER);
+                       vbuf = new Buffer;
                        vertices.use_buffer(vbuf);
                        vtx_setup.set_vertex_array(vertices);
                        dirty |= VERTEX_BUFFER;
+
+#ifdef DEBUG
+                       if(!debug_name.empty())
+                               vbuf->set_debug_name(debug_name+" [VBO]");
+#endif
                }
        }
 
@@ -72,12 +86,19 @@ void Mesh::check_buffers(unsigned mask)
                if(!ibuf || (ibuf->get_size()>0 && ibuf->get_size()<req_size))
                {
                        delete ibuf;
-                       ibuf = new Buffer(ELEMENT_ARRAY_BUFFER);
+                       ibuf = new Buffer;
                        if(!batches.empty())
                                batches.front().change_buffer(ibuf);
-                       vtx_setup.set_index_buffer(*ibuf);
                        dirty |= INDEX_BUFFER;
+
+#ifdef DEBUG
+                       if(!debug_name.empty())
+                               vbuf->set_debug_name(debug_name+" [IBO]");
+#endif
                }
+
+               if(!batches.empty())
+                       vtx_setup.set_index_buffer(*ibuf, batches.front().get_index_type());
        }
 }
 
@@ -86,8 +107,10 @@ unsigned Mesh::get_n_vertices() const
        return vertices.size();
 }
 
-float *Mesh::modify_vertex(unsigned i)
+char *Mesh::modify_vertex(unsigned i)
 {
+       if(vertices.get_format().empty())
+               throw invalid_operation("Mesh::modify_vertex");
        return vertices.modify(i);
 }
 
@@ -106,7 +129,7 @@ void Mesh::add_batch(const Batch &b)
                bool reallocate = (batches.size()==batches.capacity());
                if(reallocate)
                {
-                       for(vector<Batch>::iterator i=batches.end(); i!=batches.begin(); )
+                       for(auto i=batches.end(); i!=batches.begin(); )
                                (--i)->use_buffer(0);
                }
 
@@ -115,22 +138,35 @@ void Mesh::add_batch(const Batch &b)
                if(reallocate)
                {
                        prev = 0;
-                       for(vector<Batch>::iterator i=batches.begin(); i!=batches.end(); ++i)
+                       for(Batch &a: batches)
                        {
-                               i->use_buffer(ibuf, prev);
-                               prev = &*i;
+                               a.use_buffer(ibuf, prev);
+                               prev = &a;
                        }
                }
                else
                        batches.back().use_buffer(ibuf, prev);
        }
 
+       DataType existing_type = batches.front().get_index_type();
+       DataType added_type = batches.back().get_index_type();
+       if(existing_type!=added_type)
+       {
+               if(get_type_size(existing_type)>get_type_size(added_type))
+                       batches.back().set_index_type(existing_type);
+               else
+               {
+                       for(Batch &a: batches)
+                               a.set_index_type(added_type);
+               }
+       }
+
        check_buffers(INDEX_BUFFER);
 }
 
-void Mesh::set_winding(const WindingTest *w)
+void Mesh::set_winding(FaceWinding w)
 {
-       winding = w;
+       face_winding = w;
 }
 
 void Mesh::draw(Renderer &renderer) const
@@ -155,21 +191,24 @@ void Mesh::draw(Renderer &renderer, const VertexSetup *vs, unsigned count) const
                        return;
        }
 
+       if(batches.empty())
+               return;
+
        if(dirty)
                resize_buffers();
 
        renderer.set_vertex_setup(vs ? vs : &vtx_setup);
-       renderer.set_winding_test(winding);
+       renderer.set_front_face(face_winding);
 
        if(!count)
        {
-               for(vector<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
-                       renderer.draw(*i);
+               for(const Batch &b: batches)
+                       renderer.draw(b);
        }
        else
        {
-               for(vector<Batch>::const_iterator i=batches.begin(); i!=batches.end(); ++i)
-                       renderer.draw_instanced(*i, count);
+               for(const Batch &b: batches)
+                       renderer.draw_instanced(b, count);
        }
 }
 
@@ -177,7 +216,7 @@ void Mesh::resize_buffers() const
 {
        if(dirty&VERTEX_BUFFER)
                vbuf->storage(vertices.get_required_buffer_size());
-       if(dirty&INDEX_BUFFER)
+       if((dirty&INDEX_BUFFER) && !batches.empty())
                ibuf->storage(batches.front().get_required_buffer_size());
        dirty = 0;
 }
@@ -187,9 +226,9 @@ Resource::AsyncLoader *Mesh::load(IO::Seekable &io, const Resources *)
        return new AsyncLoader(*this, io);
 }
 
-UInt64 Mesh::get_data_size() const
+uint64_t Mesh::get_data_size() const
 {
-       UInt64 size = 0;
+       uint64_t size = 0;
        if(vbuf)
                size += vbuf->get_size();
        if(ibuf)
@@ -202,37 +241,61 @@ void Mesh::unload()
        vertices.clear();
        vertices.use_buffer(0);
        batches.clear();
+       vtx_setup.unload();
        delete vbuf;
        delete ibuf;
        vbuf = 0;
        ibuf = 0;
 }
 
+void Mesh::set_debug_name(const string &name)
+{
+#ifdef DEBUG
+       debug_name = name;
+       if(vbuf)
+               vbuf->set_debug_name(name+" [VBO]");
+       if(ibuf)
+               ibuf->set_debug_name(name+" [IBO]");
+       vtx_setup.set_debug_name(name+" [VAO]");
+#else
+       (void)name;
+#endif
+}
+
 
 Mesh::Loader::Loader(Mesh &m, bool g):
        DataFile::ObjectLoader<Mesh>(m),
        allow_gl_calls(g)
 {
        add("batch",    &Loader::batch);
+       add("storage",  &Loader::storage);
        add("vertices", &Loader::vertices);
-       add("winding",  &Loader::winding);
+       add("vertices", &Loader::vertices_with_format);
+       add("winding",  &Mesh::face_winding);
 }
 
-void Mesh::Loader::vertices(const vector<VertexAttribute> &a)
+void Mesh::Loader::storage(const vector<VertexAttribute> &attrs)
 {
-       if(a.empty())
+       if(attrs.empty())
                throw invalid_argument("No vertex attributes");
 
        VertexFormat fmt;
-       for(vector<VertexAttribute>::const_iterator i=a.begin(); i!=a.end(); ++i)
-               fmt = (fmt, *i);
-       obj.vertices.reset(fmt);
+       for(VertexAttribute a: attrs)
+               fmt = (fmt, a);
+       obj.storage(fmt);
+}
+
+void Mesh::Loader::vertices()
+{
        load_sub(obj.vertices);
        if(allow_gl_calls)
-       {
                obj.check_buffers(VERTEX_BUFFER);
-               obj.vtx_setup.refresh();
-       }
+}
+
+void Mesh::Loader::vertices_with_format(const vector<VertexAttribute> &a)
+{
+       storage(a);
+       vertices();
 }
 
 void Mesh::Loader::batch(PrimitiveType p)
@@ -242,14 +305,6 @@ void Mesh::Loader::batch(PrimitiveType p)
        obj.add_batch(btc);
 }
 
-void Mesh::Loader::winding(FaceWinding w)
-{
-       if(w==CLOCKWISE)
-               obj.winding = &WindingTest::clockwise();
-       else if(w==COUNTERCLOCKWISE)
-               obj.winding = &WindingTest::counterclockwise();
-}
-
 
 Mesh::AsyncLoader::AsyncLoader(Mesh &m, IO::Seekable &i):
        mesh(m),
@@ -286,7 +341,6 @@ bool Mesh::AsyncLoader::process()
        else if(phase==1)
        {
                mesh.resize_buffers();
-               mesh.vtx_setup.refresh();
                vertex_updater = mesh.vertices.refresh_async();
                if(!mesh.batches.empty())
                        index_updater = mesh.batches.front().refresh_async();