]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Generalize VertexBuffer into Buffer with support for other types as well
[libs/gl.git] / source / vertexarray.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007-2009  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include "arb_vertex_program.h"
9 #include "extension.h"
10 #include "gl.h"
11 #include "version_1_2.h"
12 #include "vertexarray.h"
13 #include "vertexbuffer.h"
14
15 using namespace std;
16
17 namespace Msp {
18 namespace GL {
19
20 VertexArray::VertexArray(const VertexFormat &f):
21         vbuf(0),
22         own_vbuf(false)
23 {
24         reset(f);
25 }
26
27 VertexArray::~VertexArray()
28 {
29         if(own_vbuf)
30                 delete vbuf;
31 }
32
33 void VertexArray::use_vertex_buffer()
34 {
35         if(vbuf && own_vbuf)
36                 return;
37
38         vbuf=new Buffer(ARRAY_BUFFER);
39         own_vbuf=true;
40
41         update_data();
42 }
43
44 void VertexArray::use_vertex_buffer(Buffer *b)
45 {
46         if(own_vbuf)
47                 delete vbuf;
48         vbuf=b;
49         own_vbuf=false;
50
51         update_data();
52 }
53
54 void VertexArray::reserve(unsigned n)
55 {
56         data.reserve(n*stride);
57 }
58
59 void VertexArray::clear()
60 {
61         data.clear();
62 }
63
64 void VertexArray::reset(const VertexFormat &f)
65 {
66         clear();
67         format=f;
68         stride=get_stride(format);
69
70         bool has_gen_attrs=false;
71         for(const unsigned char *c=format.begin(); (!has_gen_attrs && c!=format.end()); ++c)
72                 has_gen_attrs=(*c>=ATTRIB1);
73         if(has_gen_attrs)
74                 static RequireExtension _ext("GL_ARB_vertex_program");
75 }
76
77 void VertexArray::apply() const
78 {
79         if(format.empty())
80                 throw InvalidState("Trying to apply a vertex array with no data");
81
82         if(vbuf)
83                 vbuf->bind();
84
85         const float *base=vbuf?0:&data[0];
86         uint offset=0;
87         uint found=0;
88         uint bpv=stride*sizeof(float);
89         for(const unsigned char *c=format.begin(); c!=format.end(); ++c)
90         {
91                 uint sz=(*c&3)+1;
92                 uint t=*c>>2;
93                 switch(t)
94                 {
95                 case 0:
96                         glVertexPointer(sz, GL_FLOAT, bpv, base+offset);
97                         break;
98                 case 1:
99                         glNormalPointer(GL_FLOAT, bpv, base+offset);
100                         break;
101                 case 2:
102                         glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset);
103                         break;
104                 case 3:
105                         if(sz==1)
106                                 glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset);
107                         else
108                                 glColorPointer(sz, GL_FLOAT, bpv, base+offset);
109                         break;
110                 default:
111                         glVertexAttribPointerARB(t-4, sz, GL_FLOAT, false, bpv, base+offset);
112                         break;
113                 }
114                 found|=1<<t;
115                 offset+=sz;
116         }
117
118         set_array(GL_VERTEX_ARRAY, found&1, 1);
119         set_array(GL_NORMAL_ARRAY, found&2, 2);
120         set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
121         set_array(GL_COLOR_ARRAY, found&8, 8);
122         for(unsigned i=4; i<32; ++i)
123                 set_array(i-4, (found>>i)&1, 1<<i);
124
125         if(vbuf)
126                 vbuf->unbind();
127 }
128
129 /**
130 Updates the VertexArray data to the VertexBuffer tied to the array, if any.
131 */
132 void VertexArray::update_data()
133 {
134         if(vbuf)
135         {
136                 vbuf->data(data.size()*sizeof(float), &data[0]);
137                 vbuf->unbind();
138         }
139 }
140
141 float *VertexArray::append()
142 {
143         data.insert(data.end(), stride, 0.0f);
144         return &*data.end()-stride;
145 }
146
147 void VertexArray::set_array(unsigned array, bool en, unsigned mask) const
148 {
149         if((enabled_arrays&mask) && !en)
150         {
151                 if(mask<16)
152                         glDisableClientState(array);
153                 else
154                         glDisableVertexAttribArrayARB(array);
155                 enabled_arrays&=~mask;
156         }
157         else if(!(enabled_arrays&mask) && en)
158         {
159                 if(mask<16)
160                         glEnableClientState(array);
161                 else
162                         glEnableVertexAttribArrayARB(array);
163                 enabled_arrays|=mask;
164         }
165 }
166
167 unsigned VertexArray::enabled_arrays=0;
168
169
170 VertexArray::Loader::Loader(VertexArray &a):
171         VertexArrayBuilder(a)
172 {
173         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
174         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
175         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
176         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
177         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
178         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
179         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
180         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
181         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
182         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
183         add("attrib1",   static_cast<void (Loader::*)(unsigned, float)>(&Loader::attrib));
184         add("attrib2",   static_cast<void (Loader::*)(unsigned, float, float)>(&Loader::attrib));
185         add("attrib3",   static_cast<void (Loader::*)(unsigned, float, float, float)>(&Loader::attrib));
186         add("attrib4",   static_cast<void (Loader::*)(unsigned, float, float, float, float)>(&Loader::attrib));
187 }
188
189
190 void array_element(int i)
191 {
192         glArrayElement(i);
193 }
194
195 void draw_arrays(PrimitiveType mode, int first, sizei count)
196 {
197         glDrawArrays(mode, first, count);
198 }
199
200 void draw_elements(PrimitiveType mode, sizei count, DataType type, const void *indices)
201 {
202         glDrawElements(mode, count, type, indices);
203 }
204
205 void draw_range_elements(PrimitiveType mode, uint low, uint high, sizei count, DataType type, const void *indices)
206 {
207         static RequireVersion _ver(1, 2);
208         glDrawRangeElements(mode, low, high, count, type, indices);
209 }
210
211 } // namespace GL
212 } // namespace Msp