374 lines
10 KiB
C++
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;
|
|
}
|