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()
23 /* We must deactivate arrays here, or apply() would try to access deleted
24 data on the next invocation. */
26 apply_arrays(0, &arrays, 0, 0);
30 void VertexArray::reset(const VertexFormat &f)
34 stride = get_stride(format);
39 for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
41 unsigned slot = get_array_slot(*c);
42 if(slot>=arrays.size())
43 arrays.resize(slot+1);
45 Array &arr = arrays[slot];
49 offs += get_component_size(*c);
53 unsigned VertexArray::get_array_slot(unsigned char comp)
55 unsigned t = get_component_type(comp);
56 if(t==get_component_type(VERTEX3))
58 else if(t==get_component_type(NORMAL3))
60 else if(t==get_component_type(COLOR4_FLOAT))
62 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
64 t -= get_component_type(TEXCOORD1);
66 static Require _req(ARB_multitexture);
71 static Require _req(ARB_vertex_shader);
73 t -= get_component_type(ATTRIB1);
78 void VertexArray::clear()
83 void VertexArray::reserve(unsigned n)
85 data.reserve(n*stride);
88 float *VertexArray::append()
90 data.insert(data.end(), stride, 0.0f);
92 return &*(data.end()-stride);
95 float *VertexArray::modify(unsigned i)
98 return &data[0]+i*stride;
101 unsigned VertexArray::get_data_size() const
103 return data.size()*sizeof(float);
106 void VertexArray::apply() const
109 throw invalid_operation("VertexArray::apply");
110 // Don't mess up the vertex array object of a mesh
112 throw invalid_operation("VertexArray::apply");
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 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 active_tex = 0;
135 unsigned n_arrays = arrays ? arrays->size() : 0;
137 n_arrays = max<unsigned>(n_arrays, old_arrays->size());
138 for(unsigned i=0; i<n_arrays; ++i)
140 const Array *arr = ((arrays && i<arrays->size() && (*arrays)[i].component) ? &(*arrays)[i] : 0);
141 const Array *old_arr = ((old_arrays && i<old_arrays->size() && (*old_arrays)[i].component) ? &(*old_arrays)[i] : 0);
145 unsigned char comp = (arr ? arr->component : old_arr->component);
146 unsigned sz = get_component_size(comp);
147 unsigned t = get_component_type(comp);
148 GLenum array_type = 0;
149 if(t==get_component_type(VERTEX3))
152 glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
153 array_type = GL_VERTEX_ARRAY;
155 else if(t==get_component_type(NORMAL3))
158 glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
159 array_type = GL_NORMAL_ARRAY;
161 else if(t==get_component_type(COLOR4_FLOAT))
166 glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
168 glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
170 array_type = GL_COLOR_ARRAY;
172 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
174 t -= get_component_type(TEXCOORD1);
175 if(t>0 || active_tex)
177 glClientActiveTexture(GL_TEXTURE0+t);
181 glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
182 array_type = GL_TEXTURE_COORD_ARRAY;
186 if(t>=get_component_type(ATTRIB1))
187 t -= get_component_type(ATTRIB1);
189 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
192 // Only change enable state if needed
196 glEnableClientState(array_type);
198 glEnableVertexAttribArray(t);
200 else if(old_arr && !arr)
203 glDisableClientState(array_type);
205 glDisableVertexAttribArray(t);
210 glClientActiveTexture(GL_TEXTURE0);
214 VertexArray::Array::Array():
220 VertexArray::Loader::Loader(VertexArray &a):
221 VertexArrayBuilder(a)
223 add("vertex2", static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
224 add("vertex3", static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
225 add("vertex4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
226 add("normal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
227 add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
228 add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
229 add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
230 add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
231 add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
232 add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
233 add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
234 add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
235 add("color3", static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
236 add("color4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
237 add("attrib1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
238 add("attrib2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
239 add("attrib3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
240 add("attrib4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
241 add("tangent3", static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
242 add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));