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