]> git.tdb.fi Git - libs/gl.git/blob - source/vertexformat.cpp
Support multiple sets of texture coordinates in VertexArrays
[libs/gl.git] / source / vertexformat.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007-2010  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <cstring>
9 #include <msp/strings/lexicalcast.h>
10 #include "except.h"
11 #include "vertexformat.h"
12
13 using namespace std;
14
15 namespace Msp {
16 namespace GL {
17
18 VertexFormat::VertexFormat():
19         data(0)
20 { }
21
22 VertexFormat::VertexFormat(VertexComponent c):
23         data(new unsigned char[8])
24 {
25         data[0] = 1;
26         data[1] = c;
27 }
28
29 VertexFormat::VertexFormat(const VertexFormat &f):
30         data(0)
31 {
32         if(f.data)
33         {
34                 data = new unsigned char[(f.data[0]&~7)+8];
35                 memcpy(data, f.data, f.data[0]+1);
36         }
37 }
38
39 VertexFormat &VertexFormat::operator=(const VertexFormat &f)
40 {
41         delete[] data;
42         if(f.data)
43         {
44                 data = new unsigned char[(f.data[0]&~7)+8];
45                 memcpy(data, f.data, f.data[0]+1);
46         }
47         else
48                 data = 0;
49
50         return *this;
51 }
52
53 VertexFormat::~VertexFormat()
54 {
55         delete[] data;
56 }
57
58 unsigned VertexFormat::stride() const
59 {
60         unsigned s = 0;
61         for(const unsigned char *i=begin(); i!=end(); ++i)
62                 s += (*i&3)+1;
63         return s;
64 }
65
66 VertexFormat operator,(const VertexFormat &f, VertexComponent c)
67 {
68         VertexFormat r = f;
69         if(r.data)
70         {
71                 const unsigned char n = ++r.data[0];
72                 if((n&7)==7)
73                 {
74                         unsigned char *newdt = new unsigned char[n+9];
75                         memcpy(newdt, r.data, n);
76                         delete r.data;
77                         r.data = newdt;
78                 }
79                 r.data[n] = c;
80         }
81         else
82         {
83                 r.data = new unsigned char[8];
84                 r.data[0] = 1;
85                 r.data[1] = c;
86         }
87
88         return r;
89 }
90
91 VertexFormat operator,(const VertexFormat &f, unsigned i)
92 {
93         if(!f.data)
94                 throw InvalidState("VertexFormat has no components");
95         VertexFormat r = f;
96         unsigned char *c = r.data+r.data[0];
97         if((*c<TEXCOORD1 && i>0) || (*c<ATTRIB1 && i>=8) || i>=53)
98                 throw InvalidParameterValue("Vertex component index out of range");
99         *c += i*4;
100
101         return r;
102 }
103
104 istream &operator>>(istream &in, VertexFormat &f)
105 {
106         string str;
107         in>>str;
108
109         unsigned start = 0;
110
111         while(1)
112         {
113                 string::size_type underscore = str.find('_', start);
114                 bool fail = false;
115                 if(!str.compare(start, underscore-start, "VERTEX2"))
116                         f = (f,VERTEX2);
117                 else if(!str.compare(start, underscore-start, "VERTEX3"))
118                         f = (f,VERTEX3);
119                 else if(!str.compare(start, underscore-start, "VERTEX4"))
120                         f = (f,VERTEX4);
121                 else if(!str.compare(start, underscore-start, "NORMAL3"))
122                         f = (f,NORMAL3);
123                 else if(!str.compare(start, underscore-start, "TEXCOORD1"))
124                         f = (f,TEXCOORD1);
125                 else if(!str.compare(start, underscore-start, "TEXCOORD2"))
126                         f = (f,TEXCOORD2);
127                 else if(!str.compare(start, underscore-start, "TEXCOORD3"))
128                         f = (f,TEXCOORD3);
129                 else if(!str.compare(start, underscore-start, "TEXCOORD4"))
130                         f = (f,TEXCOORD4);
131                 else if(!str.compare(start, underscore-start, "COLOR4UB"))
132                         f = (f,COLOR4_UBYTE);
133                 else if(!str.compare(start, underscore-start, "COLOR3F"))
134                         f = (f,COLOR3_FLOAT);
135                 else if(!str.compare(start, underscore-start, "COLOR4F"))
136                         f = (f,COLOR4_FLOAT);
137                 else if(underscore>=start+8 && !str.compare(start, 6, "ATTRIB"))
138                 {
139                         try
140                         {
141                                 char n = str[start+6];
142                                 unsigned i = lexical_cast<unsigned>(str.substr(start+7, underscore-start-7));
143                                 if(n=='1')
144                                         f = (f,ATTRIB1,i);
145                                 else if(n=='2')
146                                         f = (f,ATTRIB2,i);
147                                 else if(n=='3')
148                                         f = (f,ATTRIB3,i);
149                                 else if(n=='4')
150                                         f = (f,ATTRIB4,i);
151                                 else
152                                         fail = true;
153                         }
154                         catch(const LexicalError &)
155                         {
156                                 fail = true;
157                         }
158                 }
159                 else
160                         fail = true;
161
162                 if(fail)
163                 {
164                         in.setstate(ios_base::failbit);
165                         break;
166                 }
167
168                 if(underscore==string::npos)
169                         break;
170                 start = underscore+1;
171         }
172
173         return in;
174 }
175
176 } // namespace GL
177 } // namespace Msp