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