X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fbatch.cpp;h=f14cc307ff71b92deb212e9f759ac70f1c8d69f0;hp=1d9b1d4cd4ab7081a3bf95522056f61b91375217;hb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;hpb=50175b88e2f189e80881d292dcc32523c5b272fc diff --git a/source/batch.cpp b/source/batch.cpp index 1d9b1d4c..f14cc307 100644 --- a/source/batch.cpp +++ b/source/batch.cpp @@ -1,9 +1,10 @@ +#include +#include #include "batch.h" #include "bindable.h" #include "buffer.h" #include "error.h" -#include "ext_draw_range_elements.h" -#include "nv_primitive_restart.h" +#include "mesh.h" #include "vertexarray.h" using namespace std; @@ -11,7 +12,7 @@ using namespace std; namespace { template -void append(vector &data, T i) +void append(vector &data, T i) { data.insert(data.end(), sizeof(T), 0); *(T *)(&data[data.size()-sizeof(T)]) = i; @@ -27,7 +28,7 @@ U convert(T n) } template -void expand(vector &data) +void expand(vector &data) { unsigned count = data.size()/sizeof(T); data.resize(count*sizeof(U)); @@ -36,7 +37,7 @@ void expand(vector &data) } template -void shrink(vector &data) +void shrink(vector &data) { unsigned count = data.size()/sizeof(T); for(unsigned i=0; i0xFE) - throw invalid_operation("Batch::set_data_type"); - else if(t==UNSIGNED_SHORT && max_index>0xFFFE) + if(t==UNSIGNED_SHORT && max_index>0xFFFE) throw invalid_operation("Batch::set_data_type"); - if(data_type==UNSIGNED_BYTE && t==UNSIGNED_SHORT) - expand(data); - else if(data_type==UNSIGNED_BYTE && t==UNSIGNED_INT) - expand(data); - else if(data_type==UNSIGNED_SHORT && t==UNSIGNED_INT) - expand(data); - else if(data_type==UNSIGNED_INT && t==UNSIGNED_BYTE) - shrink(data); - else if(data_type==UNSIGNED_INT && t==UNSIGNED_SHORT) - shrink(data); - else if(data_type==UNSIGNED_SHORT && t==UNSIGNED_BYTE) - shrink(data); - - data_type = t; - update_ibuf_offsets(); - dirty = true; -} - -void Batch::use_index_buffer(Buffer *buf, Batch *prev) -{ - if(buf && prev && prev->ibuf!=buf) - throw invalid_argument("Batch::use_index_buffer"); - - if(!buf) - { - prev = 0; - unlink_from_ibuf(); - } - - ibuf = buf; - prev_in_ibuf = prev; - next_in_ibuf = 0; - if(prev) - { - prev->next_in_ibuf = this; - ibuf_offset = prev->ibuf_offset+prev->data.size(); - } - else - ibuf_offset = 0; + if(index_type==UNSIGNED_SHORT && t==UNSIGNED_INT) + expand(data); + else if(index_type==UNSIGNED_INT && t==UNSIGNED_SHORT) + shrink(data); + index_type = t; + update_offset(); dirty = true; } -void Batch::unlink_from_ibuf() -{ - if(next_in_ibuf) - next_in_ibuf->prev_in_ibuf = prev_in_ibuf; - if(prev_in_ibuf) - { - prev_in_ibuf->next_in_ibuf = next_in_ibuf; - prev_in_ibuf->update_ibuf_offsets(); - } - else if(next_in_ibuf) - { - next_in_ibuf->ibuf_offset = 0; - next_in_ibuf->update_ibuf_offsets(); - } -} - -void Batch::update_ibuf_offsets() -{ - for(Batch *b=this; b->next_in_ibuf; b=b->next_in_ibuf) - b->next_in_ibuf->ibuf_offset = b->ibuf_offset+b->data.size(); -} - Batch &Batch::append(unsigned i) { - if(data.empty()) - min_index = max_index = i; - else - { - min_index = min(min_index, i); - max_index = max(max_index, i); - } - - if((data_type==UNSIGNED_BYTE || data_type==UNSIGNED_SHORT) && max_index>0xFFFE) - set_data_type(UNSIGNED_INT); - else if(data_type==UNSIGNED_BYTE && max_index>0xFE) - set_data_type(UNSIGNED_SHORT); + append_index(i); - if(data_type==UNSIGNED_SHORT) - ::append(data, i); - else if(data_type==UNSIGNED_INT) - ::append(data, i); - else - data.push_back(i); - - update_ibuf_offsets(); + update_offset(); dirty = true; return *this; } -void Batch::append(const vector &ind) +Batch &Batch::append(const vector &ind) { if(ind.empty()) - return; - - if(data.empty()) - min_index = max_index = ind.front(); + return *this; + data.reserve(data.size()+ind.size()*get_index_size()); for(vector::const_iterator i=ind.begin(); i!=ind.end(); ++i) - { - min_index = min(min_index, *i); - max_index = max(max_index, *i); - } + append_index(*i); - if((data_type==UNSIGNED_BYTE || data_type==UNSIGNED_SHORT) && max_index>0xFFFE) - set_data_type(UNSIGNED_INT); - else if(data_type==UNSIGNED_BYTE && max_index>0xFE) - set_data_type(UNSIGNED_SHORT); + update_offset(); + dirty = true; - unsigned base = data.size(); - data.resize(data.size()+ind.size()*get_index_size()); - if(data_type==UNSIGNED_SHORT) - { - unsigned short *ptr = reinterpret_cast(&data[base]); - for(unsigned i=0; i(&data[base]); - for(unsigned i=0; i(data, 0xFFFF); - else if(data_type==UNSIGNED_INT) - ::append(data, 0xFFFFFFFF); + if(index_type==UNSIGNED_INT) + ::append(data, 0xFFFFFFFF); else - data.push_back(0xFF); + ::append(data, 0xFFFF); } else if(prim_type==TRIANGLE_STRIP) { @@ -246,91 +144,96 @@ void Batch::append(const Batch &other) if(size()&1) append(other.get_index(0)); } - else if(prim_type==QUAD_STRIP) - { - append(get_index(size()-1)); - append(get_index(size()-1)); - append(other.get_index(0)); - append(other.get_index(0)); - } unsigned count = other.size(); for(unsigned i=0; i0xFFFE) + set_index_type(UNSIGNED_INT); + + if(index_type==UNSIGNED_INT) + ::append(data, i); + else + ::append(data, i); } unsigned Batch::get_index_size() const { - if(data_type==UNSIGNED_SHORT) - return sizeof(unsigned short); - else if(data_type==UNSIGNED_INT) - return sizeof(unsigned); - return sizeof(unsigned char); + return (index_type==UNSIGNED_INT ? sizeof(UInt32) : sizeof(UInt16)); } unsigned Batch::get_index(unsigned i) const { - if(data_type==UNSIGNED_SHORT) - return *(unsigned short *)&data[i*sizeof(unsigned short)]; - else if(data_type==UNSIGNED_INT) - return *(unsigned *)&data[i*sizeof(unsigned )]; + if(index_type==UNSIGNED_INT) + return *(UInt32 *)&data[i*sizeof(UInt32)]; else - return data[i]; + return *(UInt16 *)&data[i*sizeof(UInt16)]; } void Batch::draw() const { + BindRestore _bind_ibuf(get_buffer(), ELEMENT_ARRAY_BUFFER); + const void *data_ptr = setup_draw(); + + glDrawElements(prim_type, size(), index_type, data_ptr); +} + +void Batch::draw_instanced(unsigned count) const +{ + static Require req(ARB_draw_instanced); + + BindRestore _bind_ibuf(get_buffer(), ELEMENT_ARRAY_BUFFER); + const void *data_ptr = setup_draw(); + + glDrawElementsInstanced(prim_type, size(), index_type, data_ptr, count); +} + +const void *Batch::setup_draw() const +{ + if(!get_buffer()) + throw invalid_operation("Batch::setup_draw"); + if(restart) { - unsigned index; - if(data_type==UNSIGNED_SHORT) - index = 0xFFFF; - else if(data_type==UNSIGNED_INT) - index = 0xFFFFFFFF; - else - index = 0xFF; + unsigned index = (index_type==UNSIGNED_INT ? 0xFFFFFFFF : 0xFFFF); if(index!=restart_index) - { - if(!restart_index) - glEnableClientState(GL_PRIMITIVE_RESTART_NV); - glPrimitiveRestartIndexNV(index); - restart_index = index; - } + set_restart_index(index); } - else if(restart_index && restart_indexprev_in_ibuf; b=b->prev_in_ibuf) ; - - unsigned chain_size = 0; - for(const Batch *a=b; a; a=a->next_in_ibuf) - chain_size += a->data.size(); + else if(restart_index && restart_index<=max_index) + set_restart_index(0); - ibuf->data(chain_size, 0); + refresh(); - for(; b; b=b->next_in_ibuf) - { - ibuf->sub_data(b->ibuf_offset, b->data.size(), &b->data[0]); - b->dirty = false; - } - } - - BufferAlias alias(*ibuf); - Bind bind_ibuf(alias, true); + return reinterpret_cast(get_offset()); +} - glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, reinterpret_cast(ibuf_offset)); +void Batch::set_restart_index(unsigned index) +{ + if(index>0) + { + if(!restart_index) + glEnable(GL_PRIMITIVE_RESTART); + glPrimitiveRestartIndex(index); } else - glDrawRangeElements(prim_type, min_index, max_index, size(), data_type, &data[0]); + glDisable(GL_PRIMITIVE_RESTART); + + restart_index = index; }