]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Add append() method and and operator[] to VertexArray
[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 void VertexArray::apply() const
75 {
76         if(format==NODATA)
77                 throw InvalidState("Trying to apply a vertex apply of format NODATA");
78
79         if(vbuf)
80                 vbuf->bind();
81
82         const float *base=vbuf?0:&data[0];
83         uint offset=0;
84         uint found=0;
85         uint bpv=stride*sizeof(float);
86         for(uint fmt=format; fmt; fmt>>=4)
87         {
88                 uint sz=(fmt&3)+1;
89                 switch(fmt&12)
90                 {
91                 case 0:
92                         glVertexPointer(sz, GL_FLOAT, bpv, base+offset);
93                         break;
94                 case 4:
95                         glNormalPointer(GL_FLOAT, bpv, base+offset);
96                         break;
97                 case 8:
98                         glTexCoordPointer(sz, GL_FLOAT, bpv, base+offset);
99                         break;
100                 case 12:
101                         if(sz==1)
102                                 glColorPointer(4, GL_UNSIGNED_BYTE, bpv, base+offset);
103                         else
104                                 glColorPointer(sz, GL_FLOAT, bpv, base+offset);
105                         break;
106                 }
107                 found|=1<<((fmt&12)>>2);
108                 offset+=sz;
109         }
110
111         set_array(GL_VERTEX_ARRAY, found&1, 1);
112         set_array(GL_NORMAL_ARRAY, found&2, 2);
113         set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
114         set_array(GL_COLOR_ARRAY, found&8, 8);
115
116         if(vbuf)
117                 VertexBuffer::unbind();
118 }
119
120 /**
121 Updates the VertexArray data to the VertexBuffer tied to the array, if any.
122 */
123 void VertexArray::update_data()
124 {
125         if(vbuf)
126         {
127                 vbuf->data(data.size()*sizeof(float), &data[0]);
128                 VertexBuffer::unbind();
129         }
130 }
131
132 float *VertexArray::append()
133 {
134         data.insert(data.end(), stride, 0.0f);
135         return &*data.end()-stride;
136 }
137
138 void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const
139 {
140         if((enabled_arrays&mask) && !bit)
141         {
142                 glDisableClientState(array);
143                 enabled_arrays&=~mask;
144         }
145         else if(!(enabled_arrays&mask) && bit)
146         {
147                 glEnableClientState(array);
148                 enabled_arrays|=mask;
149         }
150 }
151
152 unsigned VertexArray::enabled_arrays=0;
153
154
155 VertexArray::Loader::Loader(VertexArray &a):
156         VertexArrayBuilder(a)
157 {
158         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
159         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
160         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
161         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
162         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
163         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
164         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
165         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
166         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
167         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
168 }
169
170 } // namespace GL
171 } // namespace Msp