]> git.tdb.fi Git - libs/gl.git/blob - tools/mesh2c.cpp
Fix PIL import
[libs/gl.git] / tools / mesh2c.cpp
1 #include <msp/core/getopt.h>
2 #include <msp/gl/mesh.h>
3 #include <msp/io/print.h>
4 #include <msp/strings/format.h>
5
6 using namespace std;
7 using namespace Msp;
8
9 const char *types[] =
10 {
11         "unsigned char", "GL_UNSIGNED_BYTE",
12         "unsigned short", "GL_UNSIGNED_SHORT",
13         "unsigned", "GL_UNSIGNED_INT"
14 };
15
16 int main(int argc, char **argv)
17 {
18         string prefix;
19         bool render_func = false;
20         bool separate_arrays = false;
21         GetOpt getopt;
22         getopt.add_option('p', "prefix",      prefix,      GetOpt::REQUIRED_ARG);
23         getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG);
24         getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG);
25         getopt(argc, argv);
26
27         const vector<string> &args = getopt.get_args();
28         if(args.empty())
29         {
30                 IO::print(IO::cerr, "Usage: %s [options] <meshfile>\n", argv[0]);
31                 return 1;
32         }
33
34         GL::Mesh mesh;
35         mesh.use_buffers(false);
36         DataFile::load(mesh, args[0]);
37
38         IO::print("/* Exported from %s */\n", args[0]);
39
40         const GL::VertexArray &array = mesh.get_vertices();
41         const GL::VertexFormat &fmt = array.get_format();
42         unsigned stride = fmt.stride();
43         if(separate_arrays)
44         {
45                 unsigned offset = 0;
46                 for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
47                 {
48                         unsigned kind = (*i)>>2;
49                         unsigned size = ((*i)&3)+1;
50                         string name;
51                         switch(kind)
52                         {
53                         case 0:
54                                 name = "vertex";
55                                 break;
56                         case 1:
57                                 name = "normal";
58                                 break;
59                         case 2:
60                                 name = "color";
61                                 break;
62                         case 3:
63                                 name = "texcoord";
64                                 break;
65                         default:
66                                 if(kind<11)
67                                         name = format("texcoord%d", kind-3);
68                                 else
69                                         name = format("attrib%d", kind-11);
70                                 break;
71                         }
72
73                         IO::print("float %s%s_data[] =\n{", prefix, name);
74                         for(unsigned j=0; j<array.size(); ++j)
75                         {
76                                 const float *ptr = array[j]+offset;
77                                 IO::print("\n\t");
78                                 for(unsigned k=0; k<size; ++k)
79                                         IO::print("%g, ", ptr[k]);
80                         }
81                         IO::print("\n};\n\n");
82
83                         offset += size;
84                 }
85         }
86         else
87         {
88                 IO::print("float %svertex_data[] =\n{", prefix);
89                 for(unsigned i=0; i<array.size(); ++i)
90                 {
91                         const float *ptr = array[i];
92                         IO::print("\n\t");
93                         for(unsigned j=0; j<stride; ++j)
94                                 IO::print("%g, ", ptr[j]);
95                 }
96                 IO::print("\n};\n\n");
97         }
98
99         const char **type = 0;
100         if(array.size()<0x100)
101                 type = types;
102         else if(array.size()<0x10000)
103                 type = types+2;
104         else
105                 type = types+4;
106
107         IO::print("%s %sindices[] =\n{", type[0], prefix);
108         for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
109         {
110                 unsigned count = i->size();
111                 for(unsigned j=0; j<count; ++j)
112                 {
113                         if(j%16==0)
114                                 IO::print("\n\t");
115                         IO::print("%d, ", i->get_index(j));
116                 }
117         }
118         IO::print("\n};\n\n");
119
120         if(render_func)
121                 IO::print("void %srender()\n{\n", prefix);
122         else
123                 IO::print("/*\nTo render the object, #include this file and add the following code:\n");
124         unsigned offset = 0;
125         for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i)
126         {
127                 unsigned kind = (*i)>>2;
128                 unsigned size = ((*i)&3)+1;
129                 string source = format("%svertex_data+%d", prefix, offset);
130                 switch((*i)>>2)
131                 {
132                 case 0:
133                         if(separate_arrays)
134                                 source = prefix+"vertex_data";
135                         IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
136                                 size, stride, source);
137                         IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n");
138                         break;
139                 case 1:
140                         if(separate_arrays)
141                                 source = prefix+"normal_data";
142                         IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n",
143                                 stride, source);
144                         IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n");
145                         break;
146                 case 2:
147                         if(separate_arrays)
148                                 source = prefix+"color_data";
149                         IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
150                                 size, stride, source);
151                         IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n");
152                         break;
153                 case 3:
154                         if(separate_arrays)
155                                 source = prefix+"texcoord_data";
156                         IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
157                                 size, stride, source);
158                         IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
159                         break;
160                 default:
161                         if(kind<11)
162                         {
163                                 if(separate_arrays)
164                                         source = format("%stexcoord%d_data", prefix, kind-3);
165                                 IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3);
166                                 IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n",
167                                         size, stride, source);
168                                 IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n");
169                         }
170                         else
171                         {
172                                 if(separate_arrays)
173                                         source = format("%sattrib%d_data", prefix, kind-11);
174                                 IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n",
175                                         kind-11, size, stride, source);
176                                 IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11);
177                         }
178                         break;
179                 }
180                 offset += size;
181         }
182         offset = 0;
183         for(list<GL::Batch>::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i)
184         {
185                 string mode;
186                 switch(i->get_type())
187                 {
188                 case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break;
189                 case GL_TRIANGLES: mode = "GL_TRIANGLES"; break;
190                 default: mode = format("%d", i->get_type()); break;
191                 }
192                 IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset);
193                 offset += i->size();
194         }
195         if(render_func)
196         {
197                 IO::print("}\n\n");
198                 IO::print("/* To render this object, #include this file and call %srender() */\n", prefix);
199         }
200         else
201                 IO::print("*/\n");
202
203         return 0;
204 }