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);
89 return &*(data.end()-stride);
92 float *VertexArray::modify(unsigned i)
95 return &data[0]+i*stride;
98 unsigned VertexArray::get_data_size() const
100 return data.size()*sizeof(float);
103 void VertexArray::bind() const
106 throw invalid_operation("VertexArray::apply");
107 // Don't mess up the vertex array object of a mesh
109 throw invalid_operation("VertexArray::apply");
111 const VertexArray *old = current();
112 /* If the array has been modified, apply it even if it was the last one to
113 be applied. This is necessary to get the data updated to vertex buffer, and
114 to resync things after a format change. Radeon drivers also have some
115 problems with modifying vertex arrays without re-setting the pointers. */
116 if(!set_current(this) && !dirty)
119 Buffer *vbuf = get_buffer();
120 Bind _bind_vbuf(vbuf, ARRAY_BUFFER);
124 const float *base = (vbuf ? reinterpret_cast<float *>(get_offset()) : &data[0]);
125 unsigned stride_bytes = stride*sizeof(float);
126 apply_arrays(&arrays, (old ? &old->arrays : 0), base, stride_bytes);
129 void VertexArray::apply_arrays(const vector<Array> *arrays, const vector<Array> *old_arrays, const float *base, unsigned stride_bytes)
131 unsigned active_tex = 0;
132 unsigned n_arrays = arrays ? arrays->size() : 0;
134 n_arrays = max<unsigned>(n_arrays, old_arrays->size());
135 for(unsigned i=0; i<n_arrays; ++i)
137 const Array *arr = ((arrays && i<arrays->size() && (*arrays)[i].component) ? &(*arrays)[i] : 0);
138 const Array *old_arr = ((old_arrays && i<old_arrays->size() && (*old_arrays)[i].component) ? &(*old_arrays)[i] : 0);
142 unsigned char comp = (arr ? arr->component : old_arr->component);
143 unsigned sz = get_component_size(comp);
144 unsigned t = get_component_type(comp);
145 GLenum array_type = 0;
146 if(t==get_component_type(VERTEX3))
149 glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
150 array_type = GL_VERTEX_ARRAY;
152 else if(t==get_component_type(NORMAL3))
155 glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
156 array_type = GL_NORMAL_ARRAY;
158 else if(t==get_component_type(COLOR4_FLOAT))
163 glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
165 glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
167 array_type = GL_COLOR_ARRAY;
169 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
171 t -= get_component_type(TEXCOORD1);
172 if(t>0 || active_tex)
174 glClientActiveTexture(GL_TEXTURE0+t);
178 glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
179 array_type = GL_TEXTURE_COORD_ARRAY;
183 if(t>=get_component_type(ATTRIB1))
184 t -= get_component_type(ATTRIB1);
186 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
189 // Only change enable state if needed
193 glEnableClientState(array_type);
195 glEnableVertexAttribArray(t);
197 else if(old_arr && !arr)
200 glDisableClientState(array_type);
202 glDisableVertexAttribArray(t);
207 glClientActiveTexture(GL_TEXTURE0);
210 void VertexArray::unbind()
212 const VertexArray *old = current();
214 apply_arrays(0, &old->arrays, 0, 0);
218 VertexArray::Array::Array():
224 VertexArray::Loader::Loader(VertexArray &a):
225 VertexArrayBuilder(a)
227 add("vertex2", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
228 add("vertex3", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
229 add("vertex4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
230 add("normal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
231 add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
232 add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
233 add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
234 add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
235 add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
236 add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
237 add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
238 add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
239 add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
240 add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
241 add("attrib1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
242 add("attrib2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
243 add("attrib3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
244 add("attrib4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
245 add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
246 add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));