X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fmesh.cpp;h=360d588f97659d9a3e2d395fa876029a4d84a337;hp=dba8a9915489aede7906f8a684b9d59e288428b5;hb=HEAD;hpb=7aaec9a70b8d7733429bec043f8e33e02956f266 diff --git a/source/core/mesh.cpp b/source/core/mesh.cpp index dba8a991..360d588f 100644 --- a/source/core/mesh.cpp +++ b/source/core/mesh.cpp @@ -1,40 +1,33 @@ -#include -#include -#include #include "buffer.h" #include "error.h" #include "mesh.h" #include "renderer.h" #include "resourcemanager.h" -#include "vertexsetup.h" using namespace std; namespace Msp { namespace GL { -Mesh::Mesh(ResourceManager *rm): - vertices(VERTEX3) +Mesh::Mesh(const VertexFormat &f) { - init(rm); + storage(f); } -Mesh::Mesh(const VertexFormat &f, ResourceManager *rm): - vertices(f) +Mesh::Mesh(Mesh &&other): + Resource(move(other)), + vertices(move(other.vertices)), + batches(move(other.batches)), + vbuf(other.vbuf), + ibuf(other.ibuf), + vtx_setup(move(other.vtx_setup)), + dirty(other.dirty), + disallow_rendering(other.disallow_rendering), + face_winding(other.face_winding), + debug_name(move(other.debug_name)) { - init(rm); -} - -void Mesh::init(ResourceManager *rm) -{ - vbuf = 0; - ibuf = 0; - dirty = 0; - disallow_rendering = false; - winding = 0; - - if(rm) - set_manager(rm); + other.vbuf = 0; + other.ibuf = 0; } Mesh::~Mesh() @@ -45,6 +38,17 @@ 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); + if(vbuf) + vtx_setup.set_vertex_array(vertices); +} + void Mesh::clear() { vertices.clear(); @@ -59,10 +63,16 @@ void Mesh::check_buffers(unsigned mask) if(!vbuf || (vbuf->get_size()>0 && vbuf->get_size()set_debug_name(debug_name+" [VBO]"); +#endif } } @@ -72,30 +82,39 @@ void Mesh::check_buffers(unsigned mask) if(!ibuf || (ibuf->get_size()>0 && ibuf->get_size()set_debug_name(debug_name+" [IBO]"); +#endif } + + if(!batches.empty()) + vtx_setup.set_index_buffer(*ibuf, batches.front().get_index_type()); } } -unsigned Mesh::get_n_vertices() const +size_t Mesh::get_n_vertices() const { return vertices.size(); } -float *Mesh::modify_vertex(unsigned i) +char *Mesh::modify_vertex(size_t i) { + if(vertices.get_format().empty()) + throw invalid_operation("Mesh::modify_vertex"); return vertices.modify(i); } -void Mesh::add_batch(const Batch &b) +void Mesh::add_batch(Batch &&b) { if(batches.empty()) { - batches.push_back(b); + batches.emplace_back(move(b)); if(ibuf) batches.back().use_buffer(ibuf); } @@ -106,31 +125,44 @@ void Mesh::add_batch(const Batch &b) bool reallocate = (batches.size()==batches.capacity()); if(reallocate) { - for(vector::iterator i=batches.end(); i!=batches.begin(); ) + for(auto i=batches.end(); i!=batches.begin(); ) (--i)->use_buffer(0); } Batch *prev = &batches.back(); - batches.push_back(b); + batches.emplace_back(move(b)); if(reallocate) { prev = 0; - for(vector::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,30 +187,33 @@ 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::const_iterator i=batches.begin(); i!=batches.end(); ++i) - renderer.draw(*i); + for(const Batch &b: batches) + renderer.draw(b); } else { - for(vector::const_iterator i=batches.begin(); i!=batches.end(); ++i) - renderer.draw_instanced(*i, count); + for(const Batch &b: batches) + renderer.draw_instanced(b, count); } } void Mesh::resize_buffers() const { if(dirty&VERTEX_BUFFER) - vbuf->storage(vertices.get_required_buffer_size()); - if(dirty&INDEX_BUFFER) - ibuf->storage(batches.front().get_required_buffer_size()); + vbuf->storage(vertices.get_required_buffer_size(), STATIC); + if((dirty&INDEX_BUFFER) && !batches.empty()) + ibuf->storage(batches.front().get_required_buffer_size(), STATIC); dirty = 0; } @@ -187,9 +222,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,61 +237,73 @@ 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(m), - allow_gl_calls(g) +Mesh::Loader::Loader(Mesh &m): + DataFile::ObjectLoader(m) { 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 &c) +void Mesh::Loader::storage(const vector &attrs) { - if(c.empty()) - throw invalid_argument("No vertex components"); + if(attrs.empty()) + throw invalid_argument("No vertex attributes"); VertexFormat fmt; - for(vector::const_iterator i=c.begin(); i!=c.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::batch(PrimitiveType p) +void Mesh::Loader::vertices_with_format(const vector &a) { - Batch btc(p); - load_sub(btc); - obj.add_batch(btc); + storage(a); + vertices(); } -void Mesh::Loader::winding(FaceWinding w) +void Mesh::Loader::batch(PrimitiveType p) { - if(w==CLOCKWISE) - obj.winding = &WindingTest::clockwise(); - else if(w==COUNTERCLOCKWISE) - obj.winding = &WindingTest::counterclockwise(); + Batch btc(p); + load_sub(btc); + obj.add_batch(move(btc)); } Mesh::AsyncLoader::AsyncLoader(Mesh &m, IO::Seekable &i): mesh(m), - io(i), - vertex_updater(0), - index_updater(0), - phase(0) + io(i) { mesh.disallow_rendering = true; mesh.check_buffers(VERTEX_BUFFER|INDEX_BUFFER); @@ -280,13 +327,13 @@ bool Mesh::AsyncLoader::process() { // TODO use correct filename DataFile::Parser parser(io, "async"); - Loader loader(mesh, false); + Loader loader(mesh); + loader.allow_gl_calls = false; loader.load(parser); } 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();