/* $Id$ This file is part of libmspgl Copyright © 2010 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ #include #include #include #include using namespace std; using namespace Msp; const char *types[] = { "unsigned char", "GL_UNSIGNED_BYTE", "unsigned short", "GL_UNSIGNED_SHORT", "unsigned", "GL_UNSIGNED_INT" }; int main(int argc, char **argv) { string prefix; bool render_func = false; bool separate_arrays = false; GetOpt getopt; getopt.add_option('p', "prefix", prefix, GetOpt::REQUIRED_ARG); getopt.add_option('r', "render-func", render_func, GetOpt::NO_ARG); getopt.add_option('s', "separate-arrays", separate_arrays, GetOpt::NO_ARG); getopt(argc, argv); const vector &args = getopt.get_args(); if(args.empty()) { IO::print(IO::cerr, "Usage: %s [options] \n", argv[0]); return 1; } GL::Mesh mesh; mesh.use_buffers(false); DataFile::load(mesh, args[0]); IO::print("/* Exported from %s */\n", args[0]); const GL::VertexArray &array = mesh.get_vertices(); const GL::VertexFormat &fmt = array.get_format(); unsigned stride = fmt.stride(); if(separate_arrays) { unsigned offset = 0; for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i) { unsigned kind = (*i)>>2; unsigned size = ((*i)&3)+1; string name; switch(kind) { case 0: name = "vertex"; break; case 1: name = "normal"; break; case 2: name = "color"; break; case 3: name = "texcoord"; break; default: if(kind<11) name = format("texcoord%d", kind-3); else name = format("attrib%d", kind-11); break; } IO::print("float %s%s_data[] =\n{", prefix, name); for(unsigned j=0; j::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i) { unsigned count = i->size(); for(unsigned j=0; jget_index(j)); } } IO::print("\n};\n\n"); if(render_func) IO::print("void %srender()\n{\n", prefix); else IO::print("/*\nTo render the object, #include this file and add the following code:\n"); unsigned offset = 0; for(const unsigned char *i=fmt.begin(); i!=fmt.end(); ++i) { unsigned kind = (*i)>>2; unsigned size = ((*i)&3)+1; string source = format("%svertex_data+%d", prefix, offset); switch((*i)>>2) { case 0: if(separate_arrays) source = prefix+"vertex_data"; IO::print("\tglVertexPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n", size, stride, source); IO::print("\tglEnableClientState(GL_VERTEX_ARRAY);\n"); break; case 1: if(separate_arrays) source = prefix+"normal_data"; IO::print("\tglNormalPointer(GL_FLOAT, %d*sizeof(float), %s);\n", stride, source); IO::print("\tglEnableClientState(GL_NORMAL_ARRAY);\n"); break; case 2: if(separate_arrays) source = prefix+"color_data"; IO::print("\tglColorPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n", size, stride, source); IO::print("\tglEnableClientState(GL_COLOR_ARRAY);\n"); break; case 3: if(separate_arrays) source = prefix+"texcoord_data"; IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n", size, stride, source); IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n"); break; default: if(kind<11) { if(separate_arrays) source = format("%stexcoord%d_data", prefix, kind-3); IO::print("\tglClientActiveTexture(GL_TEXTURE%d);\n", kind-3); IO::print("\tglTexCoordPointer(%d, GL_FLOAT, %d*sizeof(float), %s);\n", size, stride, source); IO::print("\tglEnableClientState(GL_TEXTURE_COORD_ARRAY);\n"); } else { if(separate_arrays) source = format("%sattrib%d_data", prefix, kind-11); IO::print("\tglVertexAttribPointer(%d, %d, GL_FLOAT, GL_FALSE, %d*sizeof(float), %s);\n", kind-11, size, stride, source); IO::print("\tglEnableVertexAttribArray(%d);\n", kind-11); } break; } offset += size; } offset = 0; for(list::const_iterator i=mesh.get_batches().begin(); i!=mesh.get_batches().end(); ++i) { string mode; switch(i->get_type()) { case GL_TRIANGLE_STRIP: mode = "GL_TRIANGLE_STRIP"; break; case GL_TRIANGLES: mode = "GL_TRIANGLES"; break; default: mode = format("%d", i->get_type()); break; } IO::print("\tglDrawElements(%s, %d, %s, %sindices+%d);\n", mode, i->size(), type[1], prefix, offset); offset += i->size(); } if(render_func) { IO::print("}\n\n"); IO::print("/* To render this object, #include this file and call %srender() */\n", prefix); } else IO::print("*/\n"); return 0; }