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