X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Frender%2Finstancearray.cpp;h=eec72f98dc18144c777f8ae61bb5eb3d18677db0;hp=37d7ccb68e3815f8f24b31351d904f4f41175490;hb=HEAD;hpb=96cfb8224fe73afd04289a5d1c7780170f479e25 diff --git a/source/render/instancearray.cpp b/source/render/instancearray.cpp index 37d7ccb6..20dcb888 100644 --- a/source/render/instancearray.cpp +++ b/source/render/instancearray.cpp @@ -1,7 +1,6 @@ #include #include #include "buffer.h" -#include "camera.h" #include "instancearray.h" #include "mesh.h" #include "object.h" @@ -15,14 +14,13 @@ using namespace std; namespace Msp { namespace GL { -InstanceArray::InstanceArray(const Object &o): +InstanceArrayBase::InstanceArrayBase(const Object &o, size_t s): object(o), - instance_buffer(0), - matrix_location(-1), - matrix_offset(0) + instance_size(s), + default_count(max(4096U/instance_size, 8U)) { const Technique *tech = object.get_technique(); - for(const auto &kvp: tech->get_passes()) + for(const auto &kvp: tech->get_methods()) { const Program *shprog = kvp.second.get_shader_program(); if(!shprog) @@ -50,71 +48,164 @@ InstanceArray::InstanceArray(const Object &o): vtx_setup.set_instance_array(instance_data); } -InstanceArray::~InstanceArray() +InstanceArrayBase::~InstanceArrayBase() { - for(ObjectInstance *i: instances) - delete i; delete instance_buffer; + for(Block &b: storage) + delete[] b.begin; } -void InstanceArray::append(ObjectInstance *inst) +void InstanceArrayBase::add_block(size_t count) { - instances.push_back(inst); - if(instance_data.size()0) + slots[last_free].next_free = base; + else + { + first_free = base; + last_free = slots.size()-1; + } + + slots.back().next_free = first_free; +} + +size_t InstanceArrayBase::allocate() +{ + if(first_free<0) + add_block(default_count); + + size_t index = first_free; + Slot &slot = slots[index]; + if(first_free==last_free) + { + first_free = -1; + last_free = -1; + } + else + { + first_free = slot.next_free; + slots[last_free].next_free = first_free; + } + + slot.used = true; + slot.array_index = instance_count++; + if(instance_data.size()get_size()>0 && instance_buffer->get_size()=b.begin && addrget_matrix(); + Slot &slot = slots[index]; + + --instance_count; + if(slot.array_index=0) + { + slot.next_free = first_free; + slots[last_free].next_free = index; + } + else + { + slot.next_free = index; + first_free = index; + } + last_free = index; +} - float *d = reinterpret_cast(instance_data.modify(instances.size()-1)+matrix_offset); +void InstanceArrayBase::update_instance_matrix(size_t index, const Matrix &matrix) +{ + float *d = reinterpret_cast(instance_data.modify(slots[index].array_index)+matrix_offset); for(unsigned i=0; i<12; ++i) - d[i] = m(i/4, i%4); + d[i] = matrix(i/4, i%4); } -void InstanceArray::render(Renderer &renderer, Tag tag) const +void InstanceArrayBase::render(Renderer &renderer, Tag tag) const { - if(instances.empty()) + if(!instance_count) return; const Technique *tech = object.get_technique(); if(!tech) throw logic_error("no technique"); - const RenderPass *pass = tech->find_pass(tag); - if(!pass) + const RenderMethod *method = tech->find_method(tag); + if(!method) return; const Mesh *mesh = object.get_mesh(); - mesh->get_vertices().refresh(); if(instance_buffer->get_size()==0) - instance_buffer->storage(instance_data.get_required_buffer_size()); - instance_data.refresh(); + instance_buffer->storage(instance_data.get_required_buffer_size(), STREAMING); Renderer::Push push(renderer); - pass->apply(renderer); - mesh->draw_instanced(renderer, vtx_setup, instances.size()); + renderer.set_pipeline_key(this, tag.id); + method->apply(renderer); + mesh->draw_instanced(renderer, vtx_setup, instance_count); +} + + +DataFile::Loader::ActionMap InstanceArrayBase::Loader::shared_actions; + +InstanceArrayBase::Loader::Loader(InstanceArrayBase &o): + ObjectLoader(o) +{ + set_actions(shared_actions); +} + +void InstanceArrayBase::Loader::init_actions() +{ + add("instance", &Loader::instance); } } // namespace GL