]> git.tdb.fi Git - libs/gl.git/blob - source/vertexarray.cpp
Add Mesh and Batch classes
[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 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) return;
37
38         vbuf=new VertexBuffer();
39         own_vbuf=true;
40         update_data();
41 }
42
43 void VertexArray::use_vertex_buffer(VertexBuffer *b)
44 {
45         if(vbuf) return;
46
47         vbuf=b;
48         update_data();
49 }
50
51 void VertexArray::clear()
52 {
53         data.clear();
54 }
55
56 void VertexArray::reset(VertexFormat f)
57 {
58         clear();
59         format=NODATA;
60         for(uint fmt=f; fmt; fmt>>=4)
61                 format=(format, static_cast<VertexFormat>(fmt&15));
62         stride=get_stride(format);
63 }
64
65 RefPtr<VertexArrayBuilder> VertexArray::modify()
66 {
67         return new VertexArrayBuilder(*this, data);
68 }
69
70 void VertexArray::apply() const
71 {
72         if(format==NODATA)
73                 throw InvalidState("Trying to apply a vertex apply of format NODATA");
74
75         if(vbuf)
76                 vbuf->bind();
77
78         const float *base=vbuf?0:&data[0];
79         uint offset=0;
80         uint found=0;
81         for(uint fmt=format; fmt; fmt>>=4)
82         {
83                 uint size=(fmt&3)+1;
84                 switch(fmt&12)
85                 {
86                 case 0:
87                         glVertexPointer(size, GL_FLOAT, stride, base+offset);
88                         break;
89                 case 4:
90                         glNormalPointer(GL_FLOAT, stride, base+offset);
91                         break;
92                 case 8:
93                         glTexCoordPointer(size, GL_FLOAT, stride, base+offset);
94                         break;
95                 case 12:
96                         if(size==1)
97                                 glColorPointer(4, GL_UNSIGNED_BYTE, stride, base+offset);
98                         else
99                                 glColorPointer(size, GL_FLOAT, stride, base+offset);
100                         break;
101                 }
102                 found|=1<<((fmt&12)>>2);
103                 offset+=size;
104         }
105
106         set_array(GL_VERTEX_ARRAY, found&1, 1);
107         set_array(GL_NORMAL_ARRAY, found&2, 2);
108         set_array(GL_TEXTURE_COORD_ARRAY, found&4, 4);
109         set_array(GL_COLOR_ARRAY, found&8, 8);
110
111         VertexBuffer::unbind();
112 }
113
114 /**
115 Updates the VertexArray data to the VertexBuffer tied to the array, if any.
116 */
117 void VertexArray::update_data()
118 {
119         if(vbuf)
120                 vbuf->data(data.size()*sizeof(float), &data[0]);
121 }
122
123 void VertexArray::set_array(unsigned array, unsigned bit, unsigned mask) const
124 {
125         if((enabled_arrays&mask) && !bit)
126         {
127                 glDisableClientState(array);
128                 enabled_arrays&=~mask;
129         }
130         else if(!(enabled_arrays&mask) && bit)
131         {
132                 glEnableClientState(array);
133                 enabled_arrays|=mask;
134         }
135 }
136
137 unsigned VertexArray::enabled_arrays=0;
138
139
140 VertexArray::Loader::Loader(VertexArray &a):
141         VertexArrayBuilder(a, a.data)
142 {
143         add("vertex2",   static_cast<void (Loader::*)(float, float)>(&Loader::vertex));
144         add("vertex3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::vertex));
145         add("vertex4",   static_cast<void (Loader::*)(float, float, float, float)>(&Loader::vertex));
146         add("normal3",   static_cast<void (Loader::*)(float, float, float)>(&Loader::normal));
147         add("texcoord1", static_cast<void (Loader::*)(float)>(&Loader::texcoord));
148         add("texcoord2", static_cast<void (Loader::*)(float, float)>(&Loader::texcoord));
149         add("texcoord3", static_cast<void (Loader::*)(float, float, float)>(&Loader::texcoord));
150         add("texcoord4", static_cast<void (Loader::*)(float, float, float, float)>(&Loader::texcoord));
151         add("color3",    static_cast<void (Loader::*)(float, float, float)>(&Loader::color));
152         add("color4",    static_cast<void (Loader::*)(float, float, float, float)>(&Loader::color));
153 }
154
155 } // namespace GL
156 } // namespace Msp