1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
4 #include "instancearray.h"
7 #include "objectinstance.h"
10 #include "technique.h"
17 InstanceArray::InstanceArray(const Object &o):
20 const Technique *tech = object.get_technique();
21 for(const auto &kvp: tech->get_methods())
23 const Program *shprog = kvp.second.get_shader_program();
25 throw invalid_argument("InstanceArray::InstanceArray");
27 int loc = shprog->get_attribute_location("instance_transform");
29 matrix_location = loc;
30 else if(loc!=matrix_location)
31 throw invalid_argument("InstanceArray::InstanceArray");
34 instance_data.set_format((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
35 const VertexFormat &fmt = instance_data.get_format();
36 matrix_offset = fmt.offset((RAW_ATTRIB4,matrix_location));
38 instance_buffer = new Buffer;
39 instance_data.use_buffer(instance_buffer);
41 const Mesh *mesh = object.get_mesh();
43 vtx_setup.set_format_instanced(mesh->get_vertices().get_format(), fmt);
44 vtx_setup.set_vertex_array(mesh->get_vertices());
45 vtx_setup.set_index_buffer(*mesh->get_index_buffer(), mesh->get_batches().front().get_index_type());
46 vtx_setup.set_instance_array(instance_data);
49 InstanceArray::~InstanceArray()
51 for(ObjectInstance *i: instances)
53 delete instance_buffer;
56 void InstanceArray::append(ObjectInstance *inst)
58 instances.push_back(inst);
59 if(instance_data.size()<instances.size())
61 instance_data.append();
62 unsigned req_size = instance_data.get_required_buffer_size();
63 if(instance_buffer->get_size()>0 && instance_buffer->get_size()<req_size)
65 delete instance_buffer;
66 instance_buffer = new Buffer;
67 instance_data.use_buffer(instance_buffer);
70 update_instance_matrix(instances.size()-1);
73 void InstanceArray::remove(ObjectInstance &inst)
75 auto i = find(instances, &inst);
76 if(i==instances.end())
77 throw key_error(&inst);
80 *i = instances.back();
84 void InstanceArray::update_instance_matrix(unsigned index)
86 const Matrix &m = *instances[index]->get_matrix();
88 float *d = reinterpret_cast<float *>(instance_data.modify(index)+matrix_offset);
89 for(unsigned i=0; i<12; ++i)
93 void InstanceArray::render(Renderer &renderer, Tag tag) const
98 const Technique *tech = object.get_technique();
100 throw logic_error("no technique");
101 const RenderMethod *method = tech->find_method(tag);
105 const Mesh *mesh = object.get_mesh();
106 if(instance_buffer->get_size()==0)
107 instance_buffer->storage(instance_data.get_required_buffer_size(), STREAMING);
109 Renderer::Push push(renderer);
110 renderer.set_pipeline_key(this, tag.id);
111 method->apply(renderer);
112 mesh->draw_instanced(renderer, vtx_setup, instances.size());