]> git.tdb.fi Git - libs/gl.git/blob - source/vertexformat.cpp
Drop Id tags and copyright notices from files
[libs/gl.git] / source / vertexformat.cpp
1 #include <cstring>
2 #include <msp/strings/lexicalcast.h>
3 #include <msp/strings/utils.h>
4 #include "except.h"
5 #include "vertexformat.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11
12 VertexFormat::VertexFormat():
13         data(0)
14 { }
15
16 VertexFormat::VertexFormat(VertexComponent c):
17         data(new unsigned char[8])
18 {
19         data[0] = 1;
20         data[1] = c;
21 }
22
23 VertexFormat::VertexFormat(const VertexFormat &f):
24         data(0)
25 {
26         if(f.data)
27         {
28                 data = new unsigned char[(f.data[0]&~7)+8];
29                 memcpy(data, f.data, f.data[0]+1);
30         }
31 }
32
33 VertexFormat &VertexFormat::operator=(const VertexFormat &f)
34 {
35         delete[] data;
36         if(f.data)
37         {
38                 data = new unsigned char[(f.data[0]&~7)+8];
39                 memcpy(data, f.data, f.data[0]+1);
40         }
41         else
42                 data = 0;
43
44         return *this;
45 }
46
47 VertexFormat::~VertexFormat()
48 {
49         delete[] data;
50 }
51
52 unsigned VertexFormat::stride() const
53 {
54         unsigned s = 0;
55         for(const unsigned char *i=begin(); i!=end(); ++i)
56                 s += (*i&3)+1;
57         return s;
58 }
59
60 int VertexFormat::offset(VertexComponent comp, unsigned index) const
61 {
62         if((comp<TEXCOORD1 && index>0) || (comp<ATTRIB1 && index>=8) || index>=53)
63                 throw InvalidParameterValue("Vertex component index out of range");
64
65         unsigned type = (comp>>2)+index;
66         unsigned size = comp&3;
67         unsigned offs = 0;
68         for(const unsigned char *i=begin(); i!=end(); ++i)
69         {
70                 if(static_cast<unsigned>(*i>>2)==type)
71                 {
72                         if((*i&3)>=size)
73                                 return offs;
74                         else
75                                 return -1;
76                 }
77                 else
78                         offs += (*i&3)+1;
79         }
80
81         return -1;
82 }
83
84 VertexFormat operator,(const VertexFormat &f, VertexComponent c)
85 {
86         VertexFormat r = f;
87         if(r.data)
88         {
89                 const unsigned char n = ++r.data[0];
90                 if((n&7)==7)
91                 {
92                         unsigned char *newdt = new unsigned char[n+9];
93                         memcpy(newdt, r.data, n);
94                         delete r.data;
95                         r.data = newdt;
96                 }
97                 r.data[n] = c;
98         }
99         else
100         {
101                 r.data = new unsigned char[8];
102                 r.data[0] = 1;
103                 r.data[1] = c;
104         }
105
106         return r;
107 }
108
109 VertexFormat operator,(const VertexFormat &f, unsigned i)
110 {
111         if(!f.data)
112                 throw InvalidState("VertexFormat has no components");
113         VertexFormat r = f;
114         unsigned char *c = r.data+r.data[0];
115         if((*c<TEXCOORD1 && i>0) || (*c<ATTRIB1 && i>=8) || i>=53)
116                 throw InvalidParameterValue("Vertex component index out of range");
117         *c += i*4;
118
119         return r;
120 }
121
122 void operator>>(const LexicalConverter &conv, VertexComponent &c)
123 {
124         const string &str = conv.get();
125         if(str.size()==7 && !str.compare(0, 6, "VERTEX") && str[6]>='2' && str[6]<='4')
126                 c = static_cast<VertexComponent>(VERTEX2+(str[6]-'2'));
127         else if(str=="NORMAL3")
128                 c = NORMAL3;
129         else if(str.size()==12 && !str.compare(0, 5, "COLOR") && str[5]>='3' && str[5]<='4' && !str.compare(6, 6, "_FLOAT"))
130                 c = static_cast<VertexComponent>(COLOR3_FLOAT+(str[5]-'3'));
131         else if(str=="COLOR4_UBYTE")
132                 c = COLOR4_UBYTE;
133         else if(str.size()>=9 && !str.compare(0, 8, "TEXCOORD") && str[8]>='1' && str[8]<='4')
134         {
135                 if(str.size()==9)
136                         c = static_cast<VertexComponent>(TEXCOORD1+(str[8]-'1'));
137                 else if(str.size()==11 && str[9]=='_' && str[10]>='0' && str[10]<='7')
138                         c = static_cast<VertexComponent>(TEXCOORD1+(str[8]-'1')+(str[10]-'0')*4);
139                 else
140                         throw LexicalError("Invalid texture unit in VertexComponent conversion");
141         }
142         else if(str.size()>=9 && !str.compare(0, 6, "ATTRIB") && str[6]>='1' && str[6]<='4' && str[7]=='_')
143         {
144                 unsigned n;
145                 try
146                 {
147                         n = lexical_cast<unsigned>(str.substr(8));
148                 }
149                 catch(const LexicalError &)
150                 {
151                         throw LexicalError("Invalid attribute in VertexComponent conversion");
152                 }
153                 c = static_cast<VertexComponent>(ATTRIB1+(str[6]-'1')+n*4);
154         }
155         else
156                 throw LexicalError("Invalid input in VertexComponent conversion");
157 }
158
159 // XXX This will go away eventually
160 void operator>>(const LexicalConverter &conv, VertexFormat &f)
161 {
162         vector<string> parts = split(conv.get(), '_');
163         for(vector<string>::iterator i=parts.begin(); i!=parts.end(); ++i)
164         {
165                 if(*i=="COLOR4UB")
166                         *i = "COLOR4_UBYTE";
167                 else if(i->size()==7 && !i->compare(0, 5, "COLOR") && (*i)[6]=='F')
168                         *i = i->substr(0, 6)+"_FLOAT";
169                 else if(i->size()>=10 && !i->compare(0, 8, "TEXCOORD"))
170                         *i = i->substr(0, 9)+"_"+i->substr(9);
171                 else if(i->size()>=8 && !i->compare(0, 6, "ATTRIB"))
172                         *i = i->substr(0, 7)+"_"+i->substr(7);
173         }
174
175         for(vector<string>::iterator i=parts.begin(); i!=parts.end(); ++i)
176                 f = (f, lexical_cast<VertexComponent>(*i));
177 }
178
179 } // namespace GL
180 } // namespace Msp