]> git.tdb.fi Git - libs/gl.git/blobdiff - source/mesh.cpp
Move buffer resizing out of Bufferable
[libs/gl.git] / source / mesh.cpp
index 8f7911219ec68afa3cb9048d35960bef3462437c..3569e1c38badaac3a1f705769bfd4e6e625ff3e0 100644 (file)
@@ -29,6 +29,7 @@ void Mesh::init(ResourceManager *rm)
 {
        vbuf = 0;
        ibuf = 0;
+       dirty = 0;
        disallow_rendering = false;
        winding = 0;
 
@@ -49,20 +50,41 @@ void Mesh::clear()
        batches.clear();
 }
 
-void Mesh::create_buffers()
+void Mesh::check_buffers(unsigned mask)
 {
-       if(vbuf && ibuf)
-               return;
-
-       if(!vbuf)
-               vbuf = new Buffer(ARRAY_BUFFER);
-       vertices.use_buffer(vbuf);
-
-       if(!ibuf)
-               ibuf = new Buffer(ELEMENT_ARRAY_BUFFER);
+       if(mask&VERTEX_BUFFER)
+       {
+               if(!vbuf)
+               {
+                       vbuf = new Buffer(ARRAY_BUFFER);
+                       vertices.use_buffer(vbuf);
+                       vtx_setup.set_vertex_array(vertices);
+               }
+               unsigned req_size = vertices.get_required_buffer_size();
+               if(vbuf->get_size()<req_size)
+               {
+                       dirty |= VERTEX_BUFFER;
+                       vertices.buffer_resized();
+               }
+       }
 
-       vtx_setup.set_vertex_array(vertices);
-       vtx_setup.set_index_buffer(*ibuf);
+       if(mask&INDEX_BUFFER)
+       {
+               if(!ibuf)
+               {
+                       ibuf = new Buffer(ELEMENT_ARRAY_BUFFER);
+                       if(!batches.empty())
+                               batches.front().use_buffer(ibuf);
+                       vtx_setup.set_index_buffer(*ibuf);
+               }
+               unsigned req_size = (batches.empty() ? 0 : batches.front().get_required_buffer_size());
+               if(ibuf->get_size()<req_size)
+               {
+                       dirty |= INDEX_BUFFER;
+                       if(!batches.empty())
+                               batches.front().buffer_resized();
+               }
+       }
 }
 
 unsigned Mesh::get_n_vertices() const
@@ -77,12 +99,11 @@ float *Mesh::modify_vertex(unsigned i)
 
 void Mesh::add_batch(const Batch &b)
 {
-       create_buffers();
-
        if(batches.empty())
        {
                batches.push_back(b);
-               batches.back().use_buffer(ibuf);
+               if(ibuf)
+                       batches.back().use_buffer(ibuf);
        }
        else if(batches.back().can_append(b.get_type()))
                batches.back().append(b);
@@ -109,6 +130,8 @@ void Mesh::add_batch(const Batch &b)
                else
                        batches.back().use_buffer(ibuf, prev);
        }
+
+       check_buffers(INDEX_BUFFER);
 }
 
 void Mesh::set_winding(const WindingTest *w)
@@ -138,6 +161,9 @@ void Mesh::draw(Renderer &renderer, const VertexSetup *vs, unsigned count) const
                        return;
        }
 
+       if(dirty)
+               resize_buffers();
+
        renderer.set_vertex_setup(vs ? vs : &vtx_setup);
        renderer.set_winding_test(winding);
 
@@ -153,6 +179,15 @@ void Mesh::draw(Renderer &renderer, const VertexSetup *vs, unsigned count) const
        }
 }
 
+void Mesh::resize_buffers() const
+{
+       if(dirty&VERTEX_BUFFER)
+               vbuf->data(vertices.get_required_buffer_size(), 0);
+       if(dirty&INDEX_BUFFER)
+               ibuf->data(batches.front().get_required_buffer_size(), 0);
+       dirty = 0;
+}
+
 Resource::AsyncLoader *Mesh::load(IO::Seekable &io, const Resources *)
 {
        return new AsyncLoader(*this, io);
@@ -197,10 +232,8 @@ void Mesh::Loader::vertices(const vector<VertexComponent> &c)
        for(vector<VertexComponent>::const_iterator i=c.begin(); i!=c.end(); ++i)
                fmt = (fmt, *i);
        obj.vertices.reset(fmt);
-       if(obj.vbuf)
-               // Set it again to force the vertex setup to update
-               obj.vtx_setup.set_vertex_array(obj.vertices);
        load_sub(obj.vertices);
+       obj.check_buffers(VERTEX_BUFFER);
 }
 
 void Mesh::Loader::batch(PrimitiveType p)
@@ -227,7 +260,7 @@ Mesh::AsyncLoader::AsyncLoader(Mesh &m, IO::Seekable &i):
        phase(0)
 {
        mesh.disallow_rendering = true;
-       mesh.create_buffers();
+       mesh.check_buffers(VERTEX_BUFFER|INDEX_BUFFER);
 }
 
 Mesh::AsyncLoader::~AsyncLoader()
@@ -253,6 +286,7 @@ bool Mesh::AsyncLoader::process()
        }
        else if(phase==1)
        {
+               mesh.resize_buffers();
                vertex_updater = mesh.vertices.refresh_async();
                if(!mesh.batches.empty())
                        index_updater = mesh.batches.front().refresh_async();