Panda3D
|
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 }