]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Drop Id tags and copyright notices from files
[libs/gl.git] / source / vertexarray.cpp
1 #include "arb_vertex_program.h"
2 #include "buffer.h"
3 #include "extension.h"
4 #include "gl.h"
5 #include "version_1_2.h"
6 #include "version_1_3.h"
7 #include "vertexarray.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace GL {
13
14 VertexArray::ArrayMask VertexArray::enabled_arrays;
15
16 VertexArray::VertexArray(const VertexFormat &f):
17         defer_vbuf(true),
18         dirty(false)
19 {
20         reset(f);
21 }
22
23 VertexArray::~VertexArray()
24 { }
25
26 void VertexArray::use_vertex_buffer()
27 {
28         if(vbuf)
29                 return;
30
31         vbuf = new Buffer(ARRAY_BUFFER);
32         defer_vbuf = false;
33         dirty = true;
34 }
35
36 void VertexArray::use_vertex_buffer(Buffer *b)
37 {
38         vbuf = b;
39         vbuf.keep();
40         defer_vbuf = false;
41         dirty = true;
42 }
43
44 void VertexArray::reserve(unsigned n)
45 {
46         data.reserve(n*stride);
47 }
48
49 void VertexArray::clear()
50 {
51         data.clear();
52 }
53
54 void VertexArray::reset(const VertexFormat &f)
55 {
56         clear();
57         format = f;
58         stride = get_stride(format);
59
60         bool has_multitex = false;
61         bool has_gen_attrs = false;
62         for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
63         {
64                 if(*c>=TEXCOORD1+4 && *c<ATTRIB1)
65                         has_multitex = true;
66                 if(*c>=ATTRIB1)
67                         has_gen_attrs = true;
68         }
69         if(has_multitex)
70                 static RequireVersion _ver(1, 3);
71         if(has_gen_attrs)
72                 static RequireExtension _ext("GL_ARB_vertex_program");
73 }
74
75 void VertexArray::apply() const
76 {
77         if(format.empty())
78                 throw InvalidState("Trying to apply a vertex array with no data");
79
80         if(vbuf)
81         {
82                 vbuf->bind_to(ARRAY_BUFFER);
83                 if(dirty)
84                 {
85                         vbuf->data(data.size()*sizeof(float), &data[0]);
86                         dirty = false;
87                 }
88         }
89
90         const float *base = (vbuf ? 0 : &data[0]);
91         unsigned offset = 0;
92         ArrayMask found;
93         unsigned bpv = stride*sizeof(float);
94         unsigned active_tex = 0;
95         for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
96         {
97                 unsigned sz = (*c&3)+1;
98                 unsigned t = *c>>2;
99                 bool en = enabled_arrays.is_set(t);
100                 switch(t)
101                 {
102                 case 0:
103                         glVertexPointer(sz, GL_FLOAT, bpv, base+offset);
104                         if(!en)
105                                 glEnableClientState(GL_VERTEX_ARRAY);
106                         break;
107                 case 1:
108                         glNormalPointer(GL_FLOAT, bpv, base+offset);
109                         if(!en)
110                                 glEnableClientState(GL_NORMAL_ARRAY);
111                         break;
112                 case 2:
113                         if(sz==1)
114                                 glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset);
115                         else
116                                 glColorPointer(sz, GL_FLOAT, bpv, base+offset);
117                         if(!en)
118                                 glEnableClientState(GL_COLOR_ARRAY);
119                         break;
120                 default:
121                         if(t<11)
122                         {
123                                 if(t>3 || active_tex)
124                                 {
125                                         glClientActiveTexture(GL_TEXTURE0+(t-3));
126                                         active_tex = t-3;
127                                 }
128                                 glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset);
129                                 if(!en)
130                                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
131                         }
132                         else
133                         {
134                                 glVertexAttribPointerARB(t-11, sz, GL_FLOAT, false, bpv, base+offset);
135                                 if(!en)
136                                         glEnableVertexAttribArrayARB(t-11);
137                         }
138                         break;
139                 }
140                 found.set(t);
141                 offset += sz;
142         }
143
144         for(unsigned i=0; i<64; ++i)
145                 if(enabled_arrays.is_set(i) && !found.is_set(i))
146                 {
147                         if(i==0)
148                                 glDisableClientState(GL_VERTEX_ARRAY);
149                         else if(i==1)
150                                 glDisableClientState(GL_NORMAL_ARRAY);
151                         else if(i==2)
152                                 glDisableClientState(GL_COLOR_ARRAY);
153                         else if(i>=3 && i<11)
154                         {
155                                 if(i>3 || active_tex)
156                                         glClientActiveTexture(GL_TEXTURE0+(i-3));
157                                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
158                                 active_tex = i-3;
159                         }
160                         else
161                                 glDisableVertexAttribArrayARB(i-11);
162                 }
163
164         enabled_arrays = found;
165
166         if(active_tex)
167                 glClientActiveTexture(GL_TEXTURE0);
168
169         if(vbuf)
170                 Buffer::unbind_from(ARRAY_BUFFER);
171 }
172
173 float *VertexArray::append()
174 {
175         data.insert(data.end(), stride, 0.0f);
176         set_dirty();
177         return &*(data.end()-stride);
178 }
179
180 float *VertexArray::modify(unsigned i)
181 {
182         set_dirty();
183         return &data[0]+i*stride;
184 }
185
186 void VertexArray::set_dirty()
187 {
188         dirty = true;
189         if(defer_vbuf)
190         {
191                 vbuf = new Buffer(ARRAY_BUFFER);
192                 defer_vbuf = false;
193         }
194 }
195
196
197 VertexArray::ArrayMask::ArrayMask()
198 {
199         for(unsigned i=0; i<N; ++i)
200                 mask[i] = 0;
201 }
202
203 void VertexArray::ArrayMask::set(unsigned bit)
204 {
205         mask[bit/B] |= 1<<(bit%B);
206 }
207
208 bool VertexArray::ArrayMask::is_set(unsigned bit) const
209 {
210         return mask[bit/B]&(1<<(bit%B));
211 }
212
213
214 VertexArray::Loader::Loader(VertexArray &a):
215         VertexArrayBuilder(a)
216 {
217         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
218         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
219         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
220         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
221         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
222         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
223         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
224         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
225         add("multitexcoord1", static_cast<void (Loader::*)(unsigned, float)>(&Loader::multitexcoord));
226         add("multitexcoord2", static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::multitexcoord));
227         add("multitexcoord3", static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::multitexcoord));
228         add("multitexcoord4", static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::multitexcoord));
229         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
230         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
231         add("attrib1",   static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
232         add("attrib2",   static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
233         add("attrib3",   static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
234         add("attrib4",   static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
235 }
236
237
238 void array_element(int i)
239 {
240         glArrayElement(i);
241 }
242
243 void draw_arrays(PrimitiveType mode, int first, unsigned count)
244 {
245         glDrawArrays(mode, first, count);
246 }
247
248 void draw_elements(PrimitiveType mode, unsigned count, DataType type, const void *indices)
249 {
250         glDrawElements(mode, count, type, indices);
251 }
252
253 void draw_range_elements(PrimitiveType mode, unsigned low, unsigned high, unsigned count, DataType type, const void *indices)
254 {
255         static RequireVersion _ver(1, 2);
256         glDrawRangeElements(mode, low, high, count, type, indices);
257 }
258
259 } // namespace GL
260 } // namespace Msp