#include <msp/core/algorithm.h>
#include <msp/core/maputils.h>
-#include <msp/gl/extensions/arb_draw_instanced.h>
-#include <msp/gl/extensions/arb_instanced_arrays.h>
-#include <msp/gl/extensions/arb_vertex_array_object.h>
-#include <msp/gl/extensions/arb_vertex_shader.h>
#include "buffer.h"
#include "camera.h"
#include "instancearray.h"
#include "program.h"
#include "renderer.h"
#include "technique.h"
-#include "vertexsetup.h"
using namespace std;
InstanceArray::InstanceArray(const Object &o):
object(o),
- instance_data(0),
instance_buffer(0),
- vtx_setup(0),
matrix_location(-1),
matrix_offset(0)
{
throw invalid_argument("InstanceArray::InstanceArray");
}
- if(ARB_vertex_array_object && ARB_instanced_arrays && ARB_draw_instanced)
- {
- instance_data = new VertexArray((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
- const VertexFormat &fmt = instance_data->get_format();
- matrix_offset = fmt.offset((RAW_ATTRIB4,matrix_location));
+ instance_data.set_format((RAW_ATTRIB4,matrix_location, RAW_ATTRIB4,matrix_location+1, RAW_ATTRIB4,matrix_location+2));
+ const VertexFormat &fmt = instance_data.get_format();
+ matrix_offset = fmt.offset((RAW_ATTRIB4,matrix_location));
- instance_buffer = new Buffer;
- instance_data->use_buffer(instance_buffer);
+ instance_buffer = new Buffer;
+ instance_data.use_buffer(instance_buffer);
- const Mesh *mesh = object.get_mesh();
+ const Mesh *mesh = object.get_mesh();
- vtx_setup = new VertexSetup;
- vtx_setup->set_format_instanced(mesh->get_vertices().get_format(), fmt);
- vtx_setup->set_vertex_array(mesh->get_vertices());
- vtx_setup->set_index_buffer(*mesh->get_index_buffer(), mesh->get_batches().front().get_index_type());
- vtx_setup->set_instance_array(*instance_data);
- }
- else
- static Require req(ARB_vertex_shader);
+ vtx_setup.set_format_instanced(mesh->get_vertices().get_format(), fmt);
+ vtx_setup.set_vertex_array(mesh->get_vertices());
+ vtx_setup.set_index_buffer(*mesh->get_index_buffer(), mesh->get_batches().front().get_index_type());
+ vtx_setup.set_instance_array(instance_data);
}
InstanceArray::~InstanceArray()
{
for(ObjectInstance *i: instances)
delete i;
- delete vtx_setup;
- delete instance_data;
delete instance_buffer;
}
void InstanceArray::append(ObjectInstance *inst)
{
instances.push_back(inst);
- if(instance_data)
+ if(instance_data.size()<instances.size())
{
- if(instance_data->size()<instances.size())
+ instance_data.append();
+ unsigned req_size = instance_data.get_required_buffer_size();
+ if(instance_buffer->get_size()>0 && instance_buffer->get_size()<req_size)
{
- instance_data->append();
- unsigned req_size = instance_data->get_required_buffer_size();
- if(instance_buffer->get_size()>0 && instance_buffer->get_size()<req_size)
- {
- delete instance_buffer;
- instance_buffer = new Buffer;
- instance_data->use_buffer(instance_buffer);
- }
+ delete instance_buffer;
+ instance_buffer = new Buffer;
+ instance_data.use_buffer(instance_buffer);
}
- update_instance_matrix(instances.size()-1);
}
+ update_instance_matrix(instances.size()-1);
}
void InstanceArray::remove(ObjectInstance &inst)
void InstanceArray::update_instance_matrix(unsigned index)
{
- if(!instance_data)
- return;
-
const Matrix &m = *instances[index]->get_matrix();
- float *d = reinterpret_cast<float *>(instance_data->modify(instances.size()-1)+matrix_offset);
+ float *d = reinterpret_cast<float *>(instance_data.modify(instances.size()-1)+matrix_offset);
for(unsigned i=0; i<12; ++i)
d[i] = m(i/4, i%4);
}
if(instances.empty())
return;
- if(instance_data)
- {
- const Technique *tech = object.get_technique();
- if(!tech)
- throw logic_error("no technique");
- const RenderPass *pass = tech->find_pass(tag);
- if(!pass)
- 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();
-
- Renderer::Push push(renderer);
- pass->apply(renderer);
- mesh->draw_instanced(renderer, *vtx_setup, instances.size());
- }
- else
- {
- for(ObjectInstance *i: instances)
- {
- const Matrix &m = *i->get_matrix();
- for(unsigned j=0; j<3; ++j)
- glVertexAttrib4f(matrix_location+j, m(j, 0), m(j, 1), m(j, 2), m(j, 3));
- i->render(renderer, tag);
- }
- }
+ const Technique *tech = object.get_technique();
+ if(!tech)
+ throw logic_error("no technique");
+ const RenderPass *pass = tech->find_pass(tag);
+ if(!pass)
+ 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();
+
+ Renderer::Push push(renderer);
+ pass->apply(renderer);
+ mesh->draw_instanced(renderer, vtx_setup, instances.size());
}
} // namespace GL