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):
23 const Technique *tech = object.get_technique();
24 for(const auto &kvp: tech->get_methods())
26 const Program *shprog = kvp.second.get_shader_program();
28 throw invalid_argument("InstanceArray::InstanceArray");
30 int loc = shprog->get_attribute_location("instance_transform");
32 matrix_location = loc;
33 else if(loc!=matrix_location)
34 throw invalid_argument("InstanceArray::InstanceArray");
37 instance_data.set_format((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
38 const VertexFormat &fmt = instance_data.get_format();
39 matrix_offset = fmt.offset((RAW_ATTRIB4,matrix_location));
41 instance_buffer = new Buffer;
42 instance_data.use_buffer(instance_buffer);
44 const Mesh *mesh = object.get_mesh();
46 vtx_setup.set_format_instanced(mesh->get_vertices().get_format(), fmt);
47 vtx_setup.set_vertex_array(mesh->get_vertices());
48 vtx_setup.set_index_buffer(*mesh->get_index_buffer(), mesh->get_batches().front().get_index_type());
49 vtx_setup.set_instance_array(instance_data);
52 InstanceArray::~InstanceArray()
54 for(ObjectInstance *i: instances)
56 delete instance_buffer;
59 void InstanceArray::append(ObjectInstance *inst)
61 instances.push_back(inst);
62 if(instance_data.size()<instances.size())
64 instance_data.append();
65 unsigned req_size = instance_data.get_required_buffer_size();
66 if(instance_buffer->get_size()>0 && instance_buffer->get_size()<req_size)
68 delete instance_buffer;
69 instance_buffer = new Buffer;
70 instance_data.use_buffer(instance_buffer);
73 update_instance_matrix(instances.size()-1);
76 void InstanceArray::remove(ObjectInstance &inst)
78 auto i = find(instances, &inst);
79 if(i==instances.end())
80 throw key_error(&inst);
83 *i = instances.back();
87 void InstanceArray::update_instance_matrix(unsigned index)
89 const Matrix &m = *instances[index]->get_matrix();
91 float *d = reinterpret_cast<float *>(instance_data.modify(instances.size()-1)+matrix_offset);
92 for(unsigned i=0; i<12; ++i)
96 void InstanceArray::render(Renderer &renderer, Tag tag) const
101 const Technique *tech = object.get_technique();
103 throw logic_error("no technique");
104 const RenderMethod *method = tech->find_method(tag);
108 const Mesh *mesh = object.get_mesh();
109 mesh->get_vertices().refresh();
110 if(instance_buffer->get_size()==0)
111 instance_buffer->storage(instance_data.get_required_buffer_size());
112 instance_data.refresh();
114 Renderer::Push push(renderer);
115 method->apply(renderer);
116 mesh->draw_instanced(renderer, vtx_setup, instances.size());