]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Unbind vertex buffer after updating array data
[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.h"
9 #include "vertexarray.h"
10 #include "vertexbuffer.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 VertexArray::VertexArray(VertexFormat f):
18         format(NODATA),
19         stride(get_stride(f)),
20         vbuf(0),
21         own_vbuf(false)
22 {
23         // Reverse the format so the first item is in lowest bits.  This makes handling in bind() easier.
24         for(uint fmt=f; fmt; fmt>>=4)
25                 format=(format, static_cast<VertexFormat>(fmt&15));
26 }
27
28 VertexArray::~VertexArray()
29 {
30         if(own_vbuf)
31                 delete vbuf;
32 }
33
34 void VertexArray::use_vertex_buffer()
35 {
36         if(vbuf && own_vbuf)
37                 return;
38
39         vbuf=new VertexBuffer();
40         own_vbuf=true;
41
42         update_data();
43 }
44
45 void VertexArray::use_vertex_buffer(VertexBuffer *b)
46 {
47         if(own_vbuf)
48                 delete vbuf;
49         vbuf=b;
50         own_vbuf=false;
51
52         update_data();
53 }
54
55 void VertexArray::reserve(unsigned n)
56 {
57         data.reserve(n*stride);
58 }
59
60 void VertexArray::clear()
61 {
62         data.clear();
63 }
64
65 void VertexArray::reset(VertexFormat f)
66 {
67         clear();
68         format=NODATA;
69         for(uint fmt=f; fmt; fmt>>=4)
70                 format=(format, static_cast<VertexFormat>(fmt&15));
71         stride=get_stride(format);
72 }
73
74 RefPtr<VertexArrayBuilder> VertexArray::modify()
75 {
76         return new VertexArrayBuilder(*this);
77 }
78
79 void VertexArray::apply() const
80 {
81         if(format==NODATA)
82                 throw InvalidState("Trying to apply a vertex apply of format NODATA");
83
84         if(vbuf)
85                 vbuf->bind();
86
87         const float *base=vbuf?0:&data[0];
88         uint offset=0;
89         uint found=0;
90         uint bpv=stride*sizeof(float);
91         for(uint fmt=format; fmt; fmt>>=4)
92         {
93                 uint sz=(fmt&3)+1;
94                 switch(fmt&12)
95                 {
96                 case 0:
97                         glVertexPointer(sz, GL_FLOAT, bpv, base+offset);
98                         break;
99                 case 4:
100                         glNormalPointer(GL_FLOAT, bpv, base+offset);
101                         break;
102                 case 8:
103                         glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset);
104                         break;
105                 case 12:
106                         if(sz==1)
107                                 glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset);
108                         else
109                                 glColorPointer(sz, GL_FLOAT, bpv, base+offset);
110                         break;
111                 }
112                 found|=1<<((fmt&12)>>2);
113                 offset+=sz;
114         }
115
116         set_array(GL_VERTEX_ARRAY, found&1, 1);
117         set_array(GL_NORMAL_ARRAY, found&2, 2);
118         set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
119         set_array(GL_COLOR_ARRAY, found&8, 8);
120
121         if(vbuf)
122                 VertexBuffer::unbind();
123 }
124
125 /**
126 Updates the VertexArray data to the VertexBuffer tied to the array, if any.
127 */
128 void VertexArray::update_data()
129 {
130         if(vbuf)
131         {
132                 vbuf->data(data.size()*sizeof(float), &data[0]);
133                 VertexBuffer::unbind();
134         }
135 }
136
137 void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const
138 {
139         if((enabled_arrays&mask) && !bit)
140         {
141                 glDisableClientState(array);
142                 enabled_arrays&=~mask;
143         }
144         else if(!(enabled_arrays&mask) && bit)
145         {
146                 glEnableClientState(array);
147                 enabled_arrays|=mask;
148         }
149 }
150
151 unsigned VertexArray::enabled_arrays=0;
152
153
154 VertexArray::Loader::Loader(VertexArray &a):
155         VertexArrayBuilder(a)
156 {
157         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
158         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
159         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
160         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
161         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
162         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
163         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
164         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
165         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
166         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
167 }
168
169 } // namespace GL
170 } // namespace Msp