open_toontown_panda3d/pandatool/src/eggprogs/eggToC.cxx

374 lines
10 KiB
C++

/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file eggToC.cxx
* @author drose
* @date 2001-08-03
*/
#include "eggToC.h"
#include "eggVertexPool.h"
#include "eggVertex.h"
#include "eggPolygon.h"
#include "eggPrimitive.h"
#include "eggGroupNode.h"
#include "eggPolysetMaker.h"
#include "eggBin.h"
#include "string_utils.h"
using std::ostream;
using std::string;
/**
*
*/
EggToC::
EggToC() :
EggToSomething("C", ".c", true, true)
{
set_program_brief("convert .egg geometry into compilable C tables");
set_program_description
("This program reads Egg files and outputs code that will almost "
"compile as a C or C++ program. You get to define the data structures "
"for the program after the fact; the program only generates tables "
"of vertices and polygons.");
// -f is always in effect for egg2c. It doesn't make sense to provide it as
// an option to the user.
remove_option("f");
add_option
("v", "", 0,
"Generate a table of vertex positions.",
&EggToC::dispatch_none, &_vertices);
add_option
("u", "", 0,
"Generate a table of UV's per each vertex.",
&EggToC::dispatch_none, &_uvs);
add_option
("vn", "", 0,
"Generate a table of normals per each vertex.",
&EggToC::dispatch_none, &_vertex_normals);
add_option
("vc", "", 0,
"Generate a table of colors per each vertex.",
&EggToC::dispatch_none, &_vertex_colors);
add_option
("p", "", 0,
"Generate a table of polygons that index into the above tables.",
&EggToC::dispatch_none, &_polygons);
add_option
("pn", "", 0,
"Generate a table of normals per each polygon.",
&EggToC::dispatch_none, &_polygon_normals);
add_option
("pc", "", 0,
"Generate a table of colors per each polygon.",
&EggToC::dispatch_none, &_polygon_colors);
add_option
("t", "", 0,
"Output only triangles by subdividing higher-order polygons.",
&EggToC::dispatch_none, &_triangulate_polygons);
}
/**
*
*/
void EggToC::
run() {
nout << "Removing invalid primitives.\n";
int num_removed = _data->remove_invalid_primitives(true);
nout << " (" << num_removed << " removed.)\n";
if (_triangulate_polygons) {
nout << "Triangulating polygons.\n";
int num_produced = _data->triangulate_polygons(~0);
nout << " (" << num_produced << " triangles produced.)\n";
}
_data->apply_texmats();
_data->flatten_transforms();
_data->remove_unused_vertices(true);
// Collect all the polygons together into polysets.
EggPolysetMaker pmaker;
pmaker.set_properties(0);
pmaker.make_bins(_data);
get_output()
<< "/*\n"
<< " * Generated by:\n"
<< " * " << get_exec_command() << "\n"
<< " *\n"
<< " */\n\n";
_next_vpool_index = 0;
_next_bin_index = 0;
traverse(_data);
}
/**
*
*/
void EggToC::
traverse(EggNode *node) {
if (node->is_of_type(EggVertexPool::get_class_type())) {
write_vertex_pool(DCAST(EggVertexPool, node));
} else if (node->is_of_type(EggBin::get_class_type())) {
write_bin(DCAST(EggBin, node));
} else if (node->is_of_type(EggGroupNode::get_class_type())) {
EggGroupNode *group = DCAST(EggGroupNode, node);
EggGroupNode::const_iterator ci;
for (ci = group->begin(); ci != group->end(); ++ci) {
traverse(*ci);
}
}
}
/**
*
*/
void EggToC::
write_vertex_pool(EggVertexPool *vpool) {
int highest_index = vpool->get_highest_index();
int i;
ostream &out = get_output();
out << "/* Vertex pool index " << _next_vpool_index
<< ": " << vpool->get_name() << " */\n";
_vertex_pools[vpool] = _next_vpool_index;
_next_vpool_index++;
if (_vertices) {
out << "/* Vertex definition for " << vpool->get_name() << " */\n"
<< "vertex vertices_" << vpool->get_name() << "[" << highest_index
<< "] = {\n";
for (i = 0; i < highest_index; i++) {
EggVertex *vert = vpool->get_vertex(i);
if (vert == nullptr) {
out << " vertex(), /* " << i << " */\n";
} else {
LPoint4d p = vert->get_pos4();
switch (vert->get_num_dimensions()) {
case 1:
out << " vertex(" << p[0] << "), /* " << i << " */\n";
break;
case 2:
out << " vertex(" << p[0] << ", " << p[1]
<< "), /* " << i << " */\n";
break;
case 3:
out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2]
<< "), /* " << i << " */\n";
break;
case 4:
out << " vertex(" << p[0] << ", " << p[1] << ", " << p[2]
<< ", " << p[3] << "), /* " << i << " */\n";
break;
default:
out << " vertex(), /* error */\n";
}
}
}
out << "};\n\n";
}
if (_uvs) {
out << "/* UV's for " << vpool->get_name() << " */\n"
<< "uv uvs_" << vpool->get_name() << "[" << highest_index
<< "] = {\n";
for (i = 0; i < highest_index; i++) {
EggVertex *vert = vpool->get_vertex(i);
if (vert == nullptr || !vert->has_uv()) {
out << " uv(), /* " << i << " */\n";
} else {
LTexCoordd uv = vert->get_uv();
out << " uv(" << uv[0] << ", " << uv[1]
<< "), /* " << i << " */\n";
}
}
out << "};\n\n";
}
if (_vertex_normals) {
out << "/* Vertex normals for " << vpool->get_name() << " */\n"
<< "normal normals_" << vpool->get_name() << "[" << highest_index
<< "] = {\n";
for (i = 0; i < highest_index; i++) {
EggVertex *vert = vpool->get_vertex(i);
if (vert == nullptr || !vert->has_normal()) {
out << " normal(), /* " << i << " */\n";
} else {
LNormald n = vert->get_normal();
out << " normal(" << n[0] << ", " << n[1] << ", " << n[2]
<< "), /* " << i << " */\n";
}
}
out << "};\n\n";
}
if (_vertex_colors) {
out << "/* Vertex colors for " << vpool->get_name() << " */\n"
<< "color colors_" << vpool->get_name() << "[" << highest_index
<< "] = {\n";
for (i = 0; i < highest_index; i++) {
EggVertex *vert = vpool->get_vertex(i);
if (vert == nullptr || !vert->has_color()) {
out << " color(), /* " << i << " */\n";
} else {
LColor c = vert->get_color();
out << " color(" << c[0] << ", " << c[1] << ", " << c[2]
<< ", " << c[3] << "), /* " << i << " */\n";
}
}
out << "};\n\n";
}
}
/**
*
*/
void EggToC::
write_bin(EggBin *bin) {
ostream &out = get_output();
string bin_name = bin->get_name();
if (bin_name.empty()) {
bin_name = format_string(_next_bin_index);
_next_bin_index++;
}
out << "/* Polygon group " << bin_name << " */\n";
size_t num_children = bin->size();
if (_polygons) {
out << "/* Polygon definitions for " << bin_name << " */\n";
string prim_type = "polygon";
if (_triangulate_polygons) {
prim_type = "triangle";
}
out << prim_type << " polys_" << bin_name << "[" << num_children
<< "] = {\n";
if (_triangulate_polygons) {
out << " /* vpool index, vertex0, vertex1, vertex2 */\n";
} else {
out << " /* vpool index, num vertices, vertex0, vertex1, vertex2, ... */\n";
}
EggGroupNode::const_iterator ci;
size_t prim_index = 0;
for (ci = bin->begin(); ci != bin->end(); ++ci) {
EggNode *child = (*ci);
if (!child->is_of_type(EggPrimitive::get_class_type())) {
out << " " << prim_type << "(), /* error */\n";
} else {
EggPrimitive *prim = DCAST(EggPrimitive, child);
EggVertexPool *vpool = prim->get_pool();
int vpool_index = -1;
VertexPools::const_iterator pi = _vertex_pools.find(vpool);
if (pi != _vertex_pools.end()) {
vpool_index = (*pi).second;
}
out << " " << prim_type << "(" << vpool_index;
if (!_triangulate_polygons) {
out << ", " << prim->size();
}
EggPrimitive::const_iterator vi;
for (vi = prim->begin(); vi != prim->end(); ++vi) {
EggVertex *vert = (*vi);
out << ", " << vert->get_index();
}
out << "), /* " << prim_index << " */\n";
prim_index++;
}
}
out << "};\n\n";
}
if (_polygon_normals) {
ostream &out = get_output();
out << "/* Polygon normals for " << bin_name << " */\n";
out << "normal polys_" << bin_name << "[" << num_children
<< "] = {\n";
EggGroupNode::const_iterator ci;
size_t prim_index = 0;
for (ci = bin->begin(); ci != bin->end(); ++ci) {
EggNode *child = (*ci);
if (!child->is_of_type(EggPrimitive::get_class_type())) {
out << " normal(), /* error */\n";
} else {
EggPrimitive *prim = DCAST(EggPrimitive, child);
if (!prim->has_normal()) {
out << " normal(), /* " << prim_index << " */\n";
} else {
LNormald n = prim->get_normal();
out << " normal(" << n[0] << ", " << n[1] << ", " << n[2]
<< "), /* " << prim_index << " */\n";
}
prim_index++;
}
}
out << "};\n\n";
}
if (_polygon_colors) {
ostream &out = get_output();
out << "/* Polygon colors for " << bin_name << " */\n";
out << "color polys_" << bin_name << "[" << num_children
<< "] = {\n";
EggGroupNode::const_iterator ci;
size_t prim_index = 0;
for (ci = bin->begin(); ci != bin->end(); ++ci) {
EggNode *child = (*ci);
if (!child->is_of_type(EggPrimitive::get_class_type())) {
out << " color(), /* error */\n";
} else {
EggPrimitive *prim = DCAST(EggPrimitive, child);
if (!prim->has_color()) {
out << " color(), /* " << prim_index << " */\n";
} else {
LColor c = prim->get_color();
out << " color(" << c[0] << ", " << c[1] << ", " << c[2]
<< ", " << c[3] << "), /* " << prim_index << " */\n";
}
prim_index++;
}
}
out << "};\n\n";
}
}
int main(int argc, char *argv[]) {
EggToC prog;
prog.parse_command_line(argc, argv);
prog.run();
return 0;
}