-#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 "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):
+ Mesh()
{
- init(rm);
-}
-
-Mesh::Mesh(const VertexFormat &f, ResourceManager *rm):
- vertices(f)
-{
- init(rm);
-}
-
-void Mesh::init(ResourceManager *rm)
-{
- vbuf = 0;
- ibuf = 0;
- dirty = 0;
- disallow_rendering = false;
- winding = 0;
-
- if(rm)
- set_manager(rm);
+ storage(f);
}
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();
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
}
}
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());
}
}
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);
}
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);
}
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
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);
}
}
{
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;
}
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)
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<VertexComponent> &c)
+void Mesh::Loader::storage(const vector<VertexAttribute> &attrs)
{
- if(c.empty())
- throw invalid_argument("No vertex components");
+ if(attrs.empty())
+ throw invalid_argument("No vertex attributes");
VertexFormat fmt;
- for(vector<VertexComponent>::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::vertices_with_format(const vector<VertexAttribute> &a)
+{
+ storage(a);
+ vertices();
}
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),
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();