1 #include <msp/gl/extensions/arb_multitexture.h>
2 #include <msp/gl/extensions/arb_vertex_shader.h>
3 #include <msp/gl/extensions/msp_legacy_features.h>
8 #include "vertexarray.h"
15 bool VertexArray::legacy_used = false;
17 VertexArray::VertexArray(const VertexFormat &f)
22 VertexArray::~VertexArray()
24 /* Unbind accesses the current VertexArray, so a call from ~Bindable would
25 try to access destroyed data. */
30 void VertexArray::reset(const VertexFormat &f)
34 stride = get_stride(format);
40 for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
42 unsigned slot = get_array_slot(*c);
43 if(slot>=arrays.size())
44 arrays.resize(slot+1);
46 Array &arr = arrays[slot];
53 offs += get_component_size(*c);
57 unsigned VertexArray::get_array_slot(unsigned char comp)
59 unsigned t = get_component_type(comp);
60 if(t==get_component_type(VERTEX3))
62 else if(t==get_component_type(NORMAL3))
64 else if(t==get_component_type(COLOR4_FLOAT))
66 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
68 t -= get_component_type(TEXCOORD1);
70 static Require _req(ARB_multitexture);
75 static Require _req(ARB_vertex_shader);
77 t -= get_component_type(ATTRIB1);
82 void VertexArray::clear()
87 void VertexArray::reserve(unsigned n)
89 data.reserve(n*stride);
92 float *VertexArray::append()
94 data.insert(data.end(), stride, 0.0f);
97 return &*(data.end()-stride);
100 float *VertexArray::modify(unsigned i)
103 return &data[0]+i*stride;
106 unsigned VertexArray::get_data_size() const
108 return data.size()*sizeof(float);
111 void VertexArray::apply(bool use_legacy) const
114 throw invalid_operation("VertexArray::apply");
115 // Don't mess up the vertex array object of a mesh
117 throw invalid_operation("VertexArray::apply");
119 /* Unbind first if the legacy flag changes. The logic for supporting it
120 directly in apply_arrays would get too complicated, and this also allows
121 rebinding the same array with different legacy setting. */
122 if(legacy_used!=use_legacy)
126 static Require _req(ARB_vertex_shader);
128 static Require _req(MSP_legacy_features);
130 const VertexArray *old = current();
131 /* If the array has been modified, apply it even if it was the last one to
132 be applied. This is necessary to get the data updated to vertex buffer, and
133 to resync things after a format change. Radeon drivers also have some
134 problems with modifying vertex arrays without re-setting the pointers. */
135 if(!set_current(this) && !dirty)
138 const Buffer *vbuf = get_buffer();
139 Bind _bind_vbuf(vbuf, ARRAY_BUFFER);
143 const float *base = (vbuf ? reinterpret_cast<float *>(get_offset()) : &data[0]);
144 unsigned stride_bytes = stride*sizeof(float);
145 apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes, use_legacy);
148 void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes, bool use_legacy)
150 unsigned active_tex = 0;
151 unsigned n_arrays = arrays ? arrays->size() : 0;
153 n_arrays = max<unsigned>(n_arrays, old_arrays->size());
154 for(unsigned i=0; i<n_arrays; ++i)
156 const Array *arr = ((arrays && i<arrays->size() && (*arrays)[i].component) ? &(*arrays)[i] : 0);
157 const Array *old_arr = ((old_arrays && i<old_arrays->size() && (*old_arrays)[i].component) ? &(*old_arrays)[i] : 0);
161 unsigned char comp = (arr ? arr->component : old_arr->component);
162 unsigned sz = get_component_size(comp);
163 unsigned t = get_component_type(comp);
166 GLenum array_type = 0;
167 if(t==get_component_type(VERTEX3))
170 glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
171 array_type = GL_VERTEX_ARRAY;
173 else if(t==get_component_type(NORMAL3))
176 glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
177 array_type = GL_NORMAL_ARRAY;
179 else if(t==get_component_type(COLOR4_FLOAT))
184 glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
186 glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
188 array_type = GL_COLOR_ARRAY;
190 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
192 t -= get_component_type(TEXCOORD1);
193 if(t>0 || active_tex)
195 glClientActiveTexture(GL_TEXTURE0+t);
199 glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
200 array_type = GL_TEXTURE_COORD_ARRAY;
205 // Only change enable state if needed
207 glEnableClientState(array_type);
208 else if(old_arr && !arr)
209 glDisableClientState(array_type);
215 if(t>=get_component_type(ATTRIB1))
216 t -= get_component_type(ATTRIB1);
219 if(arr->component==COLOR4_UBYTE)
220 glVertexAttribPointer(t, 4, GL_UNSIGNED_BYTE, true, stride_bytes, base+arr->offset);
222 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
225 // Only change enable state if needed
227 glEnableVertexAttribArray(t);
228 else if(old_arr && !arr)
229 glDisableVertexAttribArray(t);
233 glClientActiveTexture(GL_TEXTURE0);
235 legacy_used = use_legacy;
238 void VertexArray::unbind()
240 const VertexArray *old = current();
242 apply_arrays(0, &old->arrays, 0, 0, legacy_used);
246 VertexArray::Array::Array():
252 VertexArray::Loader::Loader(VertexArray &a):
253 VertexArrayBuilder(a)
255 add("vertex", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
256 add("vertex", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
257 add("vertex", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
258 add("normal", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
259 add("texcoord", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
260 add("texcoord", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
261 add("texcoord", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
262 add("texcoord", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
263 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
264 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
265 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
266 add("multitexcoord", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
267 add("color", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
268 add("color", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
269 add("attrib", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
270 add("attrib", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
271 add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
272 add("attrib", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
273 add("tangent", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
274 add("binormal", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
276 add("vertex2", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
277 add("vertex3", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
278 add("vertex4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
279 add("normal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
280 add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
281 add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
282 add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
283 add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
284 add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
285 add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
286 add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
287 add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
288 add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
289 add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
290 add("attrib1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
291 add("attrib2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
292 add("attrib3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
293 add("attrib4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
294 add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
295 add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));