]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Add Id tags and copyright notices to files
[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 <GL/gl.h>
9 #include "vertexarray.h"
10 #include "vertexbuffer.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 uint get_stride(VertexFormat f)
18 {
19         uint stride=0;
20         for(uint fmt=f; fmt; fmt>>=4)
21                 stride+=(fmt&3)+1;
22         return stride*sizeof(float);
23 }
24
25
26 VertexArrayBuilder::VertexArrayBuilder(VertexArray &a, vector<float> &d):
27         data(d),
28         array(a),
29         format(array.get_format()),
30         stride(get_stride(format)),
31         cr(1), cg(1), cb(1), ca(1),
32         ts(0), tt(0), tr(0), tq(0),
33         nx(0), ny(0), nz(1)
34 { }
35
36 void VertexArrayBuilder::vertex(float x, float y, float z, float w)
37 {
38         for(uint fmt=format; fmt; fmt>>=4)
39         {
40                 uint size=(fmt&3)+1;
41                 switch(fmt&12)
42                 {
43                 case 0:
44                         data.push_back(x);
45                         data.push_back(y);
46                         if(size>=3) data.push_back(z);
47                         if(size>=4) data.push_back(w);
48                         break;
49                 case 4:
50                         data.push_back(nx);
51                         data.push_back(ny);
52                         data.push_back(nz);
53                         break;
54                 case 8:
55                         data.push_back(ts);
56                         if(size>=2) data.push_back(tt);
57                         if(size>=3) data.push_back(tr);
58                         if(size>=4) data.push_back(tq);
59                         break;
60                 case 12:
61                         if(size==1)
62                         {
63                                 union { ubyte c[4]; float f; } u;
64                                 u.c[0]=(ubyte)(cr*255);
65                                 u.c[1]=(ubyte)(cg*255);
66                                 u.c[2]=(ubyte)(cb*255);
67                                 u.c[3]=(ubyte)(ca*255);
68                                 data.push_back(u.f);
69                         }
70                         else
71                         {
72                                 data.push_back(cr);
73                                 data.push_back(cg);
74                                 data.push_back(cb);
75                                 if(size>=4) data.push_back(ca);
76                         }
77                         break;
78                 }
79         }
80         //cout<<"Added vertex with "<<data.size()-old_size<<" floats\n";
81 }
82
83 VertexArrayBuilder::~VertexArrayBuilder()
84 {
85         array.update_data();
86 }
87
88
89 VertexArray::VertexArray(VertexFormat f):
90         format(NODATA),
91         stride(get_stride(f)),
92         vbuf(0),
93         own_vbuf(false)
94 {
95         // Reverse the format so the first item is in lowest bits
96         for(uint fmt=f; fmt; fmt>>=4)
97                 format=(format, static_cast<VertexFormat>(fmt&15));
98 }
99
100 VertexArray::~VertexArray()
101 {
102         if(own_vbuf)
103                 delete vbuf;
104 }
105
106 void VertexArray::use_vertex_buffer()
107 {
108         if(vbuf) return;
109
110         vbuf=new VertexBuffer();
111         own_vbuf=true;
112         update_data();
113 }
114
115 void VertexArray::use_vertex_buffer(VertexBuffer *b)
116 {
117         if(vbuf) return;
118
119         vbuf=b;
120         update_data();
121 }
122
123 void VertexArray::clear()
124 {
125         data.clear();
126 }
127
128 void VertexArray::apply() const
129 {
130         if(vbuf) vbuf->bind();
131
132         const float *base=vbuf?0:&data[0];
133         uint offset=0;
134         uint found=0;
135         for(uint fmt=format; fmt; fmt>>=4)
136         {
137                 uint size=(fmt&3)+1;
138                 switch(fmt&12)
139                 {
140                 case 0:
141                         glVertexPointer(size, GL_FLOAT, stride, base+offset);
142                         break;
143                 case 4:
144                         glNormalPointer(GL_FLOAT, stride, base+offset);
145                         break;
146                 case 8:
147                         glTexCoordPointer(size, GL_FLOAT, stride, base+offset);
148                         break;
149                 case 12:
150                         if(size==1)
151                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, base+offset);
152                         else
153                                 glColorPointer(size, GL_FLOAT, stride, base+offset);
154                         break;
155                 }
156                 found|=1<<((fmt&12)>>2);
157                 offset+=size;
158         }
159
160         set_array(GL_VERTEX_ARRAY, found&1, 1);
161         set_array(GL_NORMAL_ARRAY, found&2, 2);
162         set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
163         set_array(GL_COLOR_ARRAY, found&8, 8);
164
165         VertexBuffer::unbind();
166 }
167
168 /**
169 Updates the VertexArray data to the VertexBuffer tied to the array, if any.
170 */
171 void VertexArray::update_data()
172 {
173         if(vbuf)
174                 vbuf->data(data.size()*sizeof(float), &data[0]);
175 }
176
177 void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const
178 {
179         if((enabled_arrays&mask) && !bit)
180         {
181                 glDisableClientState(array);
182                 enabled_arrays&=~mask;
183         }
184         else if(!(enabled_arrays&mask) && bit)
185         {
186                 glEnableClientState(array);
187                 enabled_arrays|=mask;
188         }
189 }
190
191 unsigned VertexArray::enabled_arrays=0;
192
193
194 } // namespace GL
195 } // namespace Msp