]> git.tdb.fi Git - libs/gl.git/blob - source/render/instancearray.h
d793ce2ed229cd8159ac9fc2504c9c1d0472a854
[libs/gl.git] / source / render / instancearray.h
1 #ifndef MSP_GL_INSTANCEARRAY_H_
2 #define MSP_GL_INSTANCEARRAY_H_
3
4 #include <vector>
5 #include "programdata.h"
6 #include "renderable.h"
7 #include "vertexarray.h"
8 #include "vertexsetup.h"
9
10 namespace Msp {
11 namespace GL {
12
13 class Buffer;
14 class Object;
15 class ObjectInstance;
16
17 /**
18 Renders multiple instances of an Object in an efficient manner.
19
20 The instance specific transform is passed to the shader in an attribute with
21 the name instance_transform.  The attribute should have the type vec4[3].  Each
22 elements of the array corresponds to a row of the transform matrix.
23
24 If the Mesh or Technique of the Object is changed during the lifetime of the
25 InstanceArray, behaviour is undefined.
26 */
27 class InstanceArray: public Renderable
28 {
29 public:
30         template<typename T>
31         class Instance: public T
32         {
33         private:
34                 InstanceArray &array;
35                 unsigned index;
36
37         public:
38                 Instance(const Object &o, InstanceArray &a, unsigned i): T(o), array(a), index(i) { }
39
40                 virtual void set_matrix(const Matrix &);
41         };
42
43 private:
44         const Object &object;
45         std::vector<ObjectInstance *> instances;
46         VertexArray instance_data;
47         Buffer *instance_buffer = 0;
48         VertexSetup vtx_setup;
49         int matrix_location = -1;
50         unsigned matrix_offset = 0;
51
52 public:
53         InstanceArray(const Object &);
54         ~InstanceArray();
55
56         void set_matrix_attribute(const std::string &);
57
58         /** Adds a new instance to the array.  The instance class must have a
59         constructor taking a const reference to Object as its sole parameter. */
60         template<typename T = ObjectInstance>
61         T &append();
62 private:
63         void append(ObjectInstance *);
64         void update_instance_matrix(unsigned);
65 public:
66         void remove(ObjectInstance &);
67
68         virtual void render(Renderer &, Tag) const;
69 };
70
71 template<typename T>
72 T &InstanceArray::append()
73 {
74         Instance<T> *inst = new Instance<T>(object, *this, instances.size());
75         append(inst);
76         return *inst;
77 }
78
79 template<typename T>
80 void InstanceArray::Instance<T>::set_matrix(const Matrix &m)
81 {
82         T::set_matrix(m);
83         array.update_instance_matrix(index);
84 }
85
86 } // namespace GL
87 } // namespace Msp
88
89 #endif