]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Compatibility fixes
[libs/gl.git] / source / vertexarray.cpp
1 #include "arb_multitexture.h"
2 #include "arb_vertex_shader.h"
3 #include "buffer.h"
4 #include "error.h"
5 #include "gl.h"
6 #include "vertexarray.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 VertexArray::VertexArray(const VertexFormat &f):
14         defer_vbuf(true),
15         dirty(false)
16 {
17         reset(f);
18 }
19
20 VertexArray::~VertexArray()
21 { }
22
23 void VertexArray::reset(const VertexFormat &f)
24 {
25         clear();
26         format = f;
27         stride = get_stride(format);
28
29         arrays.clear();
30
31         unsigned offset = 0;
32         for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
33         {
34                 unsigned slot = get_array_slot(*c);
35                 if(slot>=arrays.size())
36                         arrays.resize(slot+1);
37
38                 Array &arr = arrays[slot];
39                 arr.component = *c;
40                 arr.offset = offset;
41
42                 offset += get_component_size(*c);
43         }
44 }
45
46 unsigned VertexArray::get_array_slot(unsigned char comp)
47 {
48         unsigned t = get_component_type(comp);
49         if(t==get_component_type(VERTEX3))
50                 return 0;
51         else if(t==get_component_type(NORMAL3))
52                 return 1;
53         else if(t==get_component_type(COLOR4_FLOAT))
54                 return 2;
55         else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
56         {
57                 t -= get_component_type(TEXCOORD1);
58                 if(t>0)
59                         static Require _req(ARB_multitexture);
60                 return 3+t;
61         }
62         else
63         {
64                 static Require _req(ARB_vertex_shader);
65                 if(comp>=ATTRIB1)
66                         t -= get_component_type(ATTRIB1);
67                 return 7+t;
68         }
69 }
70
71 void VertexArray::use_vertex_buffer()
72 {
73         if(vbuf)
74                 return;
75
76         vbuf = new Buffer(ARRAY_BUFFER);
77         defer_vbuf = false;
78         dirty = true;
79 }
80
81 void VertexArray::use_vertex_buffer(Buffer *b)
82 {
83         vbuf = b;
84         vbuf.keep();
85         defer_vbuf = false;
86         dirty = true;
87 }
88
89 void VertexArray::clear()
90 {
91         data.clear();
92 }
93
94 void VertexArray::reserve(unsigned n)
95 {
96         data.reserve(n*stride);
97 }
98
99 float *VertexArray::append()
100 {
101         data.insert(data.end(), stride, 0.0f);
102         set_dirty();
103         return &*(data.end()-stride);
104 }
105
106 float *VertexArray::modify(unsigned i)
107 {
108         set_dirty();
109         return &data[0]+i*stride;
110 }
111
112 void VertexArray::set_dirty()
113 {
114         dirty = true;
115         if(defer_vbuf)
116         {
117                 vbuf = new Buffer(ARRAY_BUFFER);
118                 defer_vbuf = false;
119         }
120 }
121
122 void VertexArray::apply() const
123 {
124         if(format.empty())
125                 throw invalid_operation("VertexArray::apply");
126
127         const VertexArray *old = current();
128         if(!set_current(this))
129                 return;
130
131         if(vbuf)
132         {
133                 vbuf->bind_to(ARRAY_BUFFER);
134                 if(dirty)
135                 {
136                         vbuf->data(data.size()*sizeof(float), &data[0]);
137                         dirty = false;
138                 }
139         }
140
141         const float *base = (vbuf ? 0 : &data[0]);
142         unsigned stride_bytes = stride*sizeof(float);
143         unsigned active_tex = 0;
144         unsigned n_arrays = arrays.size();
145         if(old)
146                 n_arrays = max<unsigned>(n_arrays, old->arrays.size());
147         for(unsigned i=0; i<n_arrays; ++i)
148         {
149                 const Array *arr = ((i<arrays.size() && arrays[i].component) ? &arrays[i] : 0);
150                 const Array *old_arr = ((old && i<old->arrays.size() && old->arrays[i].component) ? &old->arrays[i] : 0);
151                 if(!arr && !old_arr)
152                         continue;
153
154                 unsigned char comp = (arr ? arr->component : old_arr->component);
155                 unsigned sz = get_component_size(comp);
156                 unsigned t = get_component_type(comp);
157                 GLenum array_type = 0;
158                 if(t==get_component_type(VERTEX3))
159                 {
160                         if(arr)
161                                 glVertexPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
162                         array_type = GL_VERTEX_ARRAY;
163                 }
164                 else if(t==get_component_type(NORMAL3))
165                 {
166                         if(arr)
167                                 glNormalPointer(GL_FLOAT, stride_bytes, base+arr->offset);
168                         array_type = GL_NORMAL_ARRAY;
169                 }
170                 else if(t==get_component_type(COLOR4_FLOAT))
171                 {
172                         if(arr)
173                         {
174                                 if(sz==1)
175                                         glColorPointer(4, GL_UNSIGNED_BYTE, stride_bytes, base+arr->offset);
176                                 else
177                                         glColorPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
178                         }
179                         array_type = GL_COLOR_ARRAY;
180                 }
181                 else if(comp>=TEXCOORD1 && comp<=TEXCOORD4+12)
182                 {
183                         t -= get_component_type(TEXCOORD1);
184                         if(t>0 || active_tex)
185                         {
186                                 glClientActiveTexture(GL_TEXTURE0+t);
187                                 active_tex = t;
188                         }
189                         if(arr)
190                                 glTexCoordPointer(sz, GL_FLOAT, stride_bytes, base+arr->offset);
191                         array_type = GL_TEXTURE_COORD_ARRAY;
192                 }
193                 else
194                 {
195                         if(t>=get_component_type(ATTRIB1))
196                                 t -= get_component_type(ATTRIB1);
197                         if(arr)
198                                 glVertexAttribPointer(t, sz, GL_FLOAT, false, stride_bytes, base+arr->offset);
199                 }
200
201                 // Only change enable state if needed
202                 if(arr && !old_arr)
203                 {
204                         if(array_type)
205                                 glEnableClientState(array_type);
206                         else
207                                 glEnableVertexAttribArray(t);
208                 }
209                 else if(old_arr && !arr)
210                 {
211                         if(array_type)
212                                 glDisableClientState(array_type);
213                         else
214                                 glDisableVertexAttribArray(t);
215                 }
216         }
217
218         if(active_tex)
219                 glClientActiveTexture(GL_TEXTURE0);
220
221         if(vbuf)
222                 Buffer::unbind_from(ARRAY_BUFFER);
223 }
224
225
226 VertexArray::Array::Array():
227         component(0),
228         offset(0)
229 { }
230
231
232 VertexArray::Loader::Loader(VertexArray &a):
233         VertexArrayBuilder(a)
234 {
235         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
236         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
237         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
238         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
239         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
240         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
241         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
242         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
243         add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
244         add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
245         add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
246         add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
247         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
248         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
249         add("attrib1",   static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
250         add("attrib2",   static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
251         add("attrib3",   static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
252         add("attrib4",   static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
253         add("tangent3",  static_cast<void (Loader::*)(float, float, float)>(&Loader::tangent));
254         add("binormal3", static_cast<void (Loader::*)(float, float, float)>(&Loader::binormal));
255 }
256
257 } // namespace GL
258 } // namespace Msp