Panda3D
 All Classes Functions Variables Enumerations
eggToC.cxx
00001 // Filename: eggToC.cxx
00002 // Created by:  drose (03Aug01)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "eggToC.h"
00016 
00017 #include "eggVertexPool.h"
00018 #include "eggVertex.h"
00019 #include "eggPolygon.h"
00020 #include "eggPrimitive.h"
00021 #include "eggGroupNode.h"
00022 #include "eggPolysetMaker.h"
00023 #include "eggBin.h"
00024 #include "string_utils.h"
00025 #include "pystub.h"
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: EggToC::Constructor
00029 //       Access: Public
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 EggToC::
00033 EggToC() :
00034   EggToSomething("C", ".c", true, true)
00035 {
00036   set_program_description
00037     ("This program reads Egg files and outputs code that will almost "
00038      "compile as a C or C++ program.  You get to define the data structures "
00039      "for the program after the fact; the program only generates tables "
00040      "of vertices and polygons.");
00041 
00042   // -f is always in effect for egg2c.  It doesn't make sense to
00043   // provide it as an option to the user.
00044   remove_option("f");
00045 
00046   add_option
00047     ("v", "", 0,
00048      "Generate a table of vertex positions.",
00049      &EggToC::dispatch_none, &_vertices);
00050 
00051   add_option
00052     ("u", "", 0,
00053      "Generate a table of UV's per each vertex.",
00054      &EggToC::dispatch_none, &_uvs);
00055 
00056   add_option
00057     ("vn", "", 0,
00058      "Generate a table of normals per each vertex.",
00059      &EggToC::dispatch_none, &_vertex_normals);
00060 
00061   add_option
00062     ("vc", "", 0,
00063      "Generate a table of colors per each vertex.",
00064      &EggToC::dispatch_none, &_vertex_colors);
00065 
00066   add_option
00067     ("p", "", 0,
00068      "Generate a table of polygons that index into the above tables.",
00069      &EggToC::dispatch_none, &_polygons);
00070 
00071   add_option
00072     ("pn", "", 0,
00073      "Generate a table of normals per each polygon.",
00074      &EggToC::dispatch_none, &_polygon_normals);
00075 
00076   add_option
00077     ("pc", "", 0,
00078      "Generate a table of colors per each polygon.",
00079      &EggToC::dispatch_none, &_polygon_colors);
00080 
00081   add_option
00082     ("t", "", 0,
00083      "Output only triangles by subdividing higher-order polygons.",
00084      &EggToC::dispatch_none, &_triangulate_polygons);
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: EggToC::run
00089 //       Access: Public
00090 //  Description:
00091 ////////////////////////////////////////////////////////////////////
00092 void EggToC::
00093 run() {
00094   nout << "Removing invalid primitives.\n";
00095   int num_removed = _data->remove_invalid_primitives(true);
00096   nout << "  (" << num_removed << " removed.)\n";
00097 
00098   if (_triangulate_polygons) {
00099     nout << "Triangulating polygons.\n";
00100     int num_produced = _data->triangulate_polygons(~0);
00101     nout << "  (" << num_produced << " triangles produced.)\n";
00102   }
00103 
00104   _data->apply_texmats();
00105   _data->flatten_transforms();
00106   _data->remove_unused_vertices(true);
00107 
00108   // Collect all the polygons together into polysets.
00109   EggPolysetMaker pmaker;
00110   pmaker.set_properties(0);
00111   pmaker.make_bins(_data);
00112 
00113   get_output()
00114     << "/*\n"
00115     << " * Generated by:\n"
00116     << " * " << get_exec_command() << "\n"
00117     << " *\n"
00118     << " */\n\n";
00119 
00120   _next_vpool_index = 0;
00121   _next_bin_index = 0;
00122   traverse(_data);
00123 }
00124 
00125 ////////////////////////////////////////////////////////////////////
00126 //     Function: EggToC::traverse
00127 //       Access: Public
00128 //  Description:
00129 ////////////////////////////////////////////////////////////////////
00130 void EggToC::
00131 traverse(EggNode *node) {
00132   if (node->is_of_type(EggVertexPool::get_class_type())) {
00133     write_vertex_pool(DCAST(EggVertexPool, node));
00134 
00135   } else if (node->is_of_type(EggBin::get_class_type())) {
00136     write_bin(DCAST(EggBin, node));
00137 
00138   } else if (node->is_of_type(EggGroupNode::get_class_type())) {
00139     EggGroupNode *group = DCAST(EggGroupNode, node);
00140 
00141     EggGroupNode::const_iterator ci;
00142     for (ci = group->begin(); ci != group->end(); ++ci) {
00143       traverse(*ci);
00144     }
00145   }
00146 }
00147 
00148 ////////////////////////////////////////////////////////////////////
00149 //     Function: EggToC::write_vertex_pool
00150 //       Access: Public
00151 //  Description:
00152 ////////////////////////////////////////////////////////////////////
00153 void EggToC::
00154 write_vertex_pool(EggVertexPool *vpool) {
00155   int highest_index = vpool->get_highest_index();
00156   int i;
00157 
00158   ostream &out = get_output();
00159   out << "/* Vertex pool index " << _next_vpool_index 
00160       << ": " << vpool->get_name() << " */\n";
00161   _vertex_pools[vpool] = _next_vpool_index;
00162   _next_vpool_index++;
00163 
00164   if (_vertices) {
00165     out << "/* Vertex definition for " << vpool->get_name() << " */\n"
00166         << "vertex vertices_" << vpool->get_name() << "[" << highest_index
00167         << "] = {\n";
00168     for (i = 0; i < highest_index; i++) {
00169       EggVertex *vert = vpool->get_vertex(i);
00170       if (vert == (EggVertex *)NULL) {
00171         out << "  vertex(),  /* " << i << " */\n";
00172       } else {
00173         LPoint4d p = vert->get_pos4();
00174         switch (vert->get_num_dimensions()) {
00175         case 1:
00176           out << "  vertex(" << p[0] << "),  /* " << i << " */\n";
00177           break;
00178   
00179         case 2:
00180           out << "  vertex(" << p[0] << ", " << p[1]
00181               << "),  /* " << i << " */\n";
00182           break;
00183   
00184         case 3:
00185           out << "  vertex(" << p[0] << ", " << p[1] << ", " << p[2]
00186               << "),  /* " << i << " */\n";
00187           break;
00188   
00189         case 4:
00190           out << "  vertex(" << p[0] << ", " << p[1] << ", " << p[2]
00191               << ", " << p[3] << "),  /* " << i << " */\n";
00192           break;
00193 
00194         default:
00195           out << "  vertex(),   /* error */\n";
00196         }
00197       }
00198     }
00199     out << "};\n\n";
00200   }
00201 
00202   if (_uvs) {
00203     out << "/* UV's for " << vpool->get_name() << " */\n"
00204         << "uv uvs_" << vpool->get_name() << "[" << highest_index
00205         << "] = {\n";
00206     for (i = 0; i < highest_index; i++) {
00207       EggVertex *vert = vpool->get_vertex(i);
00208       if (vert == (EggVertex *)NULL || !vert->has_uv()) {
00209         out << "  uv(),  /* " << i << " */\n";
00210       } else {
00211         LTexCoordd uv = vert->get_uv();
00212         out << "  uv(" << uv[0] << ", " << uv[1]
00213             << "),  /* " << i << " */\n";
00214       }
00215     }
00216     out << "};\n\n";
00217   }
00218 
00219   if (_vertex_normals) {
00220     out << "/* Vertex normals for " << vpool->get_name() << " */\n"
00221         << "normal normals_" << vpool->get_name() << "[" << highest_index
00222         << "] = {\n";
00223     for (i = 0; i < highest_index; i++) {
00224       EggVertex *vert = vpool->get_vertex(i);
00225       if (vert == (EggVertex *)NULL || !vert->has_normal()) {
00226         out << "  normal(),  /* " << i << " */\n";
00227       } else {
00228         LNormald n = vert->get_normal();
00229         out << "  normal(" << n[0] << ", " << n[1] << ", " << n[2]
00230             << "),  /* " << i << " */\n";
00231       }
00232     }
00233     out << "};\n\n";
00234   }
00235 
00236   if (_vertex_colors) {
00237     out << "/* Vertex colors for " << vpool->get_name() << " */\n"
00238         << "color colors_" << vpool->get_name() << "[" << highest_index
00239         << "] = {\n";
00240     for (i = 0; i < highest_index; i++) {
00241       EggVertex *vert = vpool->get_vertex(i);
00242       if (vert == (EggVertex *)NULL || !vert->has_color()) {
00243         out << "  color(),  /* " << i << " */\n";
00244       } else {
00245         LColor c = vert->get_color();
00246         out << "  color(" << c[0] << ", " << c[1] << ", " << c[2]
00247             << ", " << c[3] << "),  /* " << i << " */\n";
00248       }
00249     }
00250     out << "};\n\n";
00251   }
00252 }
00253 
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: EggToC::write_bin
00257 //       Access: Public
00258 //  Description:
00259 ////////////////////////////////////////////////////////////////////
00260 void EggToC::
00261 write_bin(EggBin *bin) {
00262   ostream &out = get_output();
00263   string bin_name = bin->get_name();
00264   if (bin_name.empty()) {
00265     bin_name = format_string(_next_bin_index);
00266     _next_bin_index++;
00267   }
00268 
00269   out << "/* Polygon group " << bin_name << " */\n";
00270 
00271   size_t num_children = bin->size();
00272 
00273   if (_polygons) {
00274     out << "/* Polygon definitions for " << bin_name << " */\n";
00275     string prim_type = "polygon";
00276     if (_triangulate_polygons) {
00277       prim_type = "triangle";
00278     }
00279 
00280     out << prim_type << " polys_" << bin_name << "[" << num_children
00281         << "] = {\n";
00282 
00283     if (_triangulate_polygons) {
00284       out << "  /* vpool index, vertex0, vertex1, vertex2 */\n";
00285     } else {
00286       out << "  /* vpool index, num vertices, vertex0, vertex1, vertex2, ... */\n";
00287     }
00288     
00289     EggGroupNode::const_iterator ci;
00290     size_t prim_index = 0;
00291     for (ci = bin->begin(); ci != bin->end(); ++ci) {
00292       EggNode *child = (*ci);
00293       if (!child->is_of_type(EggPrimitive::get_class_type())) {
00294         out << "  " << prim_type << "(),   /* error */\n";
00295       } else {
00296         EggPrimitive *prim = DCAST(EggPrimitive, child);
00297         EggVertexPool *vpool = prim->get_pool();
00298         int vpool_index = -1;
00299         VertexPools::const_iterator pi = _vertex_pools.find(vpool);
00300         if (pi != _vertex_pools.end()) {
00301           vpool_index = (*pi).second;
00302         }
00303 
00304         out << "  " << prim_type << "(" << vpool_index;
00305         if (!_triangulate_polygons) {
00306           out << ", " << prim->size();
00307         }
00308         EggPrimitive::const_iterator vi;
00309         for (vi = prim->begin(); vi != prim->end(); ++vi) {
00310           EggVertex *vert = (*vi);
00311           out << ", " << vert->get_index();
00312         }
00313         out << "),  /* " << prim_index << " */\n";
00314         prim_index++;
00315       }
00316     }
00317     out << "};\n\n";
00318   }
00319 
00320   if (_polygon_normals) {
00321     ostream &out = get_output();
00322     out << "/* Polygon normals for " << bin_name << " */\n";
00323     out << "normal polys_" << bin_name << "[" << num_children
00324         << "] = {\n";
00325     
00326     EggGroupNode::const_iterator ci;
00327     size_t prim_index = 0;
00328     for (ci = bin->begin(); ci != bin->end(); ++ci) {
00329       EggNode *child = (*ci);
00330       if (!child->is_of_type(EggPrimitive::get_class_type())) {
00331         out << "  normal(),   /* error */\n";
00332       } else {
00333         EggPrimitive *prim = DCAST(EggPrimitive, child);
00334         if (!prim->has_normal()) {
00335           out << "  normal(),   /* " << prim_index << " */\n";
00336         } else {
00337           LNormald n = prim->get_normal();
00338           out << "  normal(" << n[0] << ", " << n[1] << ", " << n[2]
00339               << "),  /* " << prim_index << " */\n";
00340         }
00341         prim_index++;
00342       }
00343     }
00344     out << "};\n\n";
00345   }
00346 
00347   if (_polygon_colors) {
00348     ostream &out = get_output();
00349     out << "/* Polygon colors for " << bin_name << " */\n";
00350     out << "color polys_" << bin_name << "[" << num_children
00351         << "] = {\n";
00352     
00353     EggGroupNode::const_iterator ci;
00354     size_t prim_index = 0;
00355     for (ci = bin->begin(); ci != bin->end(); ++ci) {
00356       EggNode *child = (*ci);
00357       if (!child->is_of_type(EggPrimitive::get_class_type())) {
00358         out << "  color(),   /* error */\n";
00359       } else {
00360         EggPrimitive *prim = DCAST(EggPrimitive, child);
00361         if (!prim->has_color()) {
00362           out << "  color(),   /* " << prim_index << " */\n";
00363         } else {
00364           LColor c = prim->get_color();
00365           out << "  color(" << c[0] << ", " << c[1] << ", " << c[2]
00366               << ", " << c[3] << "),  /* " << prim_index << " */\n";
00367         }
00368         prim_index++;
00369       }
00370     }
00371     out << "};\n\n";
00372   }
00373 }
00374 
00375 
00376 int main(int argc, char *argv[]) {
00377   // A call to pystub() to force libpystub.so to be linked in.
00378   pystub();
00379 
00380   EggToC prog;
00381   prog.parse_command_line(argc, argv);
00382   prog.run();
00383   return 0;
00384 }
 All Classes Functions Variables Enumerations