1 #include <msp/gl/extensions/arb_multitexture.h>
2 #include <msp/gl/extensions/arb_vertex_shader.h>
7 #include "vertexarray.h"
14 VertexArray::VertexArray(const VertexFormat &f)
19 VertexArray::~VertexArray()
21 /* Unbind accesses the current VertexArray, so a call from ~Bindable would
22 try to access destroyed data. */
27 void VertexArray::reset(const VertexFormat &f)
31 stride = get_stride(format);
36 for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
38 unsigned slot = get_array_slot(*c);
39 if(slot>=arrays.size())
40 arrays.resize(slot+1);
42 Array &arr = arrays[slot];
46 offs += get_component_size(*c);
50 unsigned VertexArray::get_array_slot(unsigned char comp)
52 unsigned t = get_component_type(comp);
53 if(t==get_component_type(VERTEX3))
55 else if(t==get_component_type(NORMAL3))
57 else if(t==get_component_type(COLOR4_FLOAT))
59 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
61 t -= get_component_type(TEXCOORD1);
63 static Require _req(ARB_multitexture);
68 static Require _req(ARB_vertex_shader);
70 t -= get_component_type(ATTRIB1);
75 void VertexArray::clear()
80 void VertexArray::reserve(unsigned n)
82 data.reserve(n*stride);
85 float *VertexArray::append()
87 data.insert(data.end(), stride, 0.0f);
90 return &*(data.end()-stride);
93 float *VertexArray::modify(unsigned i)
96 return &data[0]+i*stride;
99 unsigned VertexArray::get_data_size() const
101 return data.size()*sizeof(float);
104 void VertexArray::apply() const
107 throw invalid_operation("VertexArray::apply");
108 // Don't mess up the vertex array object of a mesh
110 throw invalid_operation("VertexArray::apply");
112 static Require _req(ARB_vertex_shader);
114 const VertexArray *old = current();
115 /* If the array has been modified, apply it even if it was the last one to
116 be applied. This is necessary to get the data updated to vertex buffer, and
117 to resync things after a format change. Radeon drivers also have some
118 problems with modifying vertex arrays without re-setting the pointers. */
119 if(!set_current(this) && !dirty)
122 const Buffer *vbuf = get_buffer();
123 Bind _bind_vbuf(vbuf, ARRAY_BUFFER);
127 const float *base = (vbuf ? reinterpret_cast<float *>(get_offset()) : &data[0]);
128 unsigned stride_bytes = stride*sizeof(float);
129 apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes);
132 void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes)
134 unsigned n_arrays = arrays ? arrays->size() : 0;
136 n_arrays = max<unsigned>(n_arrays, old_arrays->size());
137 for(unsigned i=0; i<n_arrays; ++i)
139 const Array *arr = ((arrays && i<arrays->size() && (*arrays)[i].component) ? &(*arrays)[i] : 0);
140 const Array *old_arr = ((old_arrays && i<old_arrays->size() && (*old_arrays)[i].component) ? &(*old_arrays)[i] : 0);
144 unsigned char comp = (arr ? arr->component : old_arr->component);
145 unsigned sz = get_component_size(comp);
146 unsigned t = get_component_type(comp);
148 if(t>=get_component_type(ATTRIB1))
149 t -= get_component_type(ATTRIB1);
152 if(arr->component==COLOR4_UBYTE)
153 glVertexAttribPointer(t, 4, GL_UNSIGNED_BYTE, true, stride_bytes, base+arr->offset);
155 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
158 // Only change enable state if needed
160 glEnableVertexAttribArray(t);
161 else if(old_arr && !arr)
162 glDisableVertexAttribArray(t);
166 void VertexArray::unbind()
168 const VertexArray *old = current();
170 apply_arrays(0, &old->arrays, 0, 0);
174 VertexArray::Array::Array():
180 VertexArray::Loader::Loader(VertexArray &a):
181 VertexArrayBuilder(a)
183 add("vertex", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
184 add("vertex", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
185 add("vertex", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
186 add("normal", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
187 add("texcoord", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
188 add("texcoord", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
189 add("texcoord", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
190 add("texcoord", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
191 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
192 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
193 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
194 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
195 add("color", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
196 add("color", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
197 add("attrib", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
198 add("attrib", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
199 add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
200 add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
201 add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
202 add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
204 add("vertex2", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
205 add("vertex3", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
206 add("vertex4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
207 add("normal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
208 add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
209 add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
210 add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
211 add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
212 add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
213 add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
214 add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
215 add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
216 add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
217 add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
218 add("attrib1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
219 add("attrib2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
220 add("attrib3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
221 add("attrib4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
222 add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
223 add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));