1 #include <msp/core/algorithm.h>
2 #include <msp/core/maputils.h>
5 #include "instancearray.h"
8 #include "objectinstance.h"
11 #include "technique.h"
18 InstanceArray::InstanceArray(const Object &o):
24 const Technique *tech = object.get_technique();
25 for(const auto &kvp: tech->get_passes())
27 const Program *shprog = kvp.second.get_shader_program();
29 throw invalid_argument("InstanceArray::InstanceArray");
31 int loc = shprog->get_attribute_location("instance_transform");
33 matrix_location = loc;
34 else if(loc!=matrix_location)
35 throw invalid_argument("InstanceArray::InstanceArray");
38 instance_data.set_format((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
39 const VertexFormat &fmt = instance_data.get_format();
40 matrix_offset = fmt.offset((RAW_ATTRIB4,matrix_location));
42 instance_buffer = new Buffer;
43 instance_data.use_buffer(instance_buffer);
45 const Mesh *mesh = object.get_mesh();
47 vtx_setup.set_format_instanced(mesh->get_vertices().get_format(), fmt);
48 vtx_setup.set_vertex_array(mesh->get_vertices());
49 vtx_setup.set_index_buffer(*mesh->get_index_buffer(), mesh->get_batches().front().get_index_type());
50 vtx_setup.set_instance_array(instance_data);
53 InstanceArray::~InstanceArray()
55 for(ObjectInstance *i: instances)
57 delete instance_buffer;
60 void InstanceArray::append(ObjectInstance *inst)
62 instances.push_back(inst);
63 if(instance_data.size()<instances.size())
65 instance_data.append();
66 unsigned req_size = instance_data.get_required_buffer_size();
67 if(instance_buffer->get_size()>0 && instance_buffer->get_size()<req_size)
69 delete instance_buffer;
70 instance_buffer = new Buffer;
71 instance_data.use_buffer(instance_buffer);
74 update_instance_matrix(instances.size()-1);
77 void InstanceArray::remove(ObjectInstance &inst)
79 auto i = find(instances, &inst);
80 if(i==instances.end())
81 throw key_error(&inst);
84 *i = instances.back();
88 void InstanceArray::update_instance_matrix(unsigned index)
90 const Matrix &m = *instances[index]->get_matrix();
92 float *d = reinterpret_cast<float *>(instance_data.modify(instances.size()-1)+matrix_offset);
93 for(unsigned i=0; i<12; ++i)
97 void InstanceArray::render(Renderer &renderer, Tag tag) const
102 const Technique *tech = object.get_technique();
104 throw logic_error("no technique");
105 const RenderPass *pass = tech->find_pass(tag);
109 const Mesh *mesh = object.get_mesh();
110 mesh->get_vertices().refresh();
111 if(instance_buffer->get_size()==0)
112 instance_buffer->storage(instance_data.get_required_buffer_size());
113 instance_data.refresh();
115 Renderer::Push push(renderer);
116 pass->apply(renderer);
117 mesh->draw_instanced(renderer, vtx_setup, instances.size());