From 0cd95c8f8dc6c36b8c28e623110c0b7a68926129 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 4 May 2004 23:06:23 +0000 Subject: [PATCH] add egg2dxf --- pandatool/src/dxf/dxfFile.cxx | 9 +- pandatool/src/dxfprogs/Sources.pp | 3 +- pandatool/src/dxfprogs/eggToDXF.cxx | 167 ++++++++++++++++ pandatool/src/dxfprogs/eggToDXF.h | 50 +++++ pandatool/src/dxfprogs/eggToDXFLayer.cxx | 244 +++++++++++++++++++++++ pandatool/src/dxfprogs/eggToDXFLayer.h | 63 ++++++ 6 files changed, 534 insertions(+), 2 deletions(-) create mode 100644 pandatool/src/dxfprogs/eggToDXF.cxx create mode 100644 pandatool/src/dxfprogs/eggToDXF.h create mode 100644 pandatool/src/dxfprogs/eggToDXFLayer.cxx create mode 100644 pandatool/src/dxfprogs/eggToDXFLayer.h diff --git a/pandatool/src/dxf/dxfFile.cxx b/pandatool/src/dxf/dxfFile.cxx index 57959dc53a..0ace15fe0a 100644 --- a/pandatool/src/dxf/dxfFile.cxx +++ b/pandatool/src/dxf/dxfFile.cxx @@ -288,6 +288,7 @@ DXFFile:: DXFFile() { _layer = NULL; reset_entity(); + _color_index = -1; } //////////////////////////////////////////////////////////////////// @@ -697,7 +698,7 @@ reset_entity() { _s.set(0.0, 0.0, 0.0); _z.set(0.0, 0.0, 1.0); _vertices_follow = false; - _color_index = -1; + //_color_index = -1; _verts.erase(_verts.begin(), _verts.end()); } @@ -756,6 +757,8 @@ state_top() { //////////////////////////////////////////////////////////////////// void DXFFile:: state_section() { + string tail; + switch (_code) { case 0: if (_string == "ENDSEC") { @@ -783,6 +786,10 @@ state_section() { change_layer(_string); break; + case 62: // Color. + _color_index = string_to_int(_string, tail); + break; + default: break; } diff --git a/pandatool/src/dxfprogs/Sources.pp b/pandatool/src/dxfprogs/Sources.pp index 6b1c6780e0..c5302d85f0 100644 --- a/pandatool/src/dxfprogs/Sources.pp +++ b/pandatool/src/dxfprogs/Sources.pp @@ -40,6 +40,7 @@ dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub #define SOURCES \ - eggToDXF.cxx eggToDXF.h + eggToDXF.cxx eggToDXF.h \ + eggToDXFLayer.cxx eggToDXFLayer.h #end bin_target diff --git a/pandatool/src/dxfprogs/eggToDXF.cxx b/pandatool/src/dxfprogs/eggToDXF.cxx new file mode 100644 index 0000000000..704270554f --- /dev/null +++ b/pandatool/src/dxfprogs/eggToDXF.cxx @@ -0,0 +1,167 @@ +// Filename: eggToDXF.cxx +// Created by: drose (04May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "eggToDXF.h" +#include "eggPolygon.h" +#include "dcast.h" + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXF::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggToDXF:: +EggToDXF() : + EggToSomething("DXF", ".dxf", true, false) +{ + set_binary_output(true); + set_program_description + ("This program converts files from egg format to AutoCAD DXF format. " + "Since DXF does not support nested hierarchies, vertex normals, or any " + "fancy stuff you are probably used to, there is some information lost " + "in the conversion"); + + add_option + ("p", "", 0, + "Use POLYLINE to represent polygons instead of the default, 3DFACE.", + &EggToDXF::dispatch_none, &_use_polyline); + + _coordinate_system = CS_zup_right; + _got_coordinate_system = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXF::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void EggToDXF:: +run() { + get_layers(&_data); + if (_layers.empty()) { + nout << "Egg file contains no polygons. Output file not written.\n"; + exit(1); + } + + // uniquify_names("layer", _layers.begin(), _layers.end()); + + ostream &out = get_output(); + + // Autodesk says we don't need the header, but some DXF-reading + // programs might get confused if it's missing. We'll write an + // empty header. + out << "0\nSECTION\n" + << "2\nHEADER\n" + << "0\nENDSEC\n"; + + write_tables(out); + write_entities(out); + out << "0\nEOF\n"; // Mark end of file. + + if (!out) { + nout << "An error occurred while writing.\n"; + exit(1); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: get_layers +// Access: Private +// Description: Traverses the hierarchy, looking for groups that +// contain polygons. Any such groups are deemed to be +// layers, and are added to the layers set. +//////////////////////////////////////////////////////////////////// +void EggToDXF:: +get_layers(EggGroupNode *group) { + bool has_polys = false; + + EggToDXFLayer layer(this, group); + + EggGroupNode::iterator ci; + for (ci = group->begin(); ci != group->end(); ++ci) { + EggNode *child = (*ci); + if (child->is_of_type(EggPolygon::get_class_type())) { + EggPolygon *poly = DCAST(EggPolygon, child); + has_polys = true; + + layer.add_color(poly->get_color()); + + } else if (child->is_of_type(EggGroupNode::get_class_type())) { + get_layers(DCAST(EggGroupNode, child)); + } + } + + if (has_polys) { + layer.choose_overall_color(); + _layers.push_back(layer); + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: write_tables +// Access: Private +// Description: Writes out the "layers", e.g. groups. This is just +// the layers definition in the tables section at the +// beginning of the file; the actual geometry gets +// written later, in write_entities(). +//////////////////////////////////////////////////////////////////// +void EggToDXF:: +write_tables(ostream &out) { + out << "0\nSECTION\n" + << "2\nTABLES\n" // Begin TABLES section. + << "0\nTABLE\n" + << "2\nLAYER\n" // Define LAYERS. + << "70\n" << _layers.size() << "\n"; + + EggToDXFLayers::iterator li; + for (li = _layers.begin(); li != _layers.end(); ++li) { + (*li).write_layer(out); + } + + out << "0\nENDTAB\n" // End LAYERS definition. + << "0\nENDSEC\n"; // End TABLES section. +} + +//////////////////////////////////////////////////////////////////// +// Function: write_entities +// Access: Private +// Description: Writes out the "entities", e.g. polygons, defined for +// all layers. +//////////////////////////////////////////////////////////////////// +void EggToDXF:: +write_entities(ostream &out) { + out << "0\nSECTION\n" + << "2\nENTITIES\n"; // Begin ENTITIES section. + + EggToDXFLayers::iterator li; + for (li = _layers.begin(); li != _layers.end(); ++li) { + (*li).write_entities(out); + } + + out << "0\nENDSEC\n"; // End ENTITIES section. +} + + + +int main(int argc, char *argv[]) { + EggToDXF prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandatool/src/dxfprogs/eggToDXF.h b/pandatool/src/dxfprogs/eggToDXF.h new file mode 100644 index 0000000000..40db074504 --- /dev/null +++ b/pandatool/src/dxfprogs/eggToDXF.h @@ -0,0 +1,50 @@ +// Filename: eggToDXF.h +// Created by: drose (04May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGTODXF_H +#define EGGTODXF_H + +#include "pandatoolbase.h" + +#include "eggToSomething.h" +#include "eggToDXFLayer.h" + +class EggGroupNode; + +//////////////////////////////////////////////////////////////////// +// Class : EggToDXF +// Description : A program to read an egg file and write a DXF file. +//////////////////////////////////////////////////////////////////// +class EggToDXF : public EggToSomething { +public: + EggToDXF(); + + void run(); + + bool _use_polyline; + +private: + void get_layers(EggGroupNode *group); + void write_tables(ostream &out); + void write_entities(ostream &out); + + EggToDXFLayers _layers; +}; + +#endif + diff --git a/pandatool/src/dxfprogs/eggToDXFLayer.cxx b/pandatool/src/dxfprogs/eggToDXFLayer.cxx new file mode 100644 index 0000000000..4e4ee7fbe2 --- /dev/null +++ b/pandatool/src/dxfprogs/eggToDXFLayer.cxx @@ -0,0 +1,244 @@ +// Filename: eggToDXFLayer.cxx +// Created by: drose (04May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "eggToDXFLayer.h" +#include "eggToDXF.h" +#include "dxfFile.h" +#include "eggGroup.h" +#include "eggGroupNode.h" +#include "eggPolygon.h" +#include "dcast.h" + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggToDXFLayer:: +EggToDXFLayer(EggToDXF *egg2dxf, EggGroupNode *group) : + _egg2dxf(egg2dxf), _group(group) +{ + _layer_color = -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggToDXFLayer:: +EggToDXFLayer(const EggToDXFLayer ©) : + _egg2dxf(copy._egg2dxf), + _group(copy._group), + _layer_color(copy._layer_color) +{ + // The copy constructor doesn't bother with the ColorCounts. +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::Copy Assignment Operator +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +operator = (const EggToDXFLayer ©) { + _egg2dxf = copy._egg2dxf; + _group = copy._group; + _layer_color = copy._layer_color; + + // The copy constructor doesn't bother with the ColorCounts. +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::add_color +// Access: Public +// Description: Records that one polygon is defined using the +// indicated color. This will get accumulated; the +// color used by the majority of polygons will become +// the layer color. +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +add_color(const Colorf &color) { + int autocad_color = get_autocad_color(color); + + ColorCounts::iterator cci; + cci = _color_counts.find(autocad_color); + if (cci == _color_counts.end()) { + // The first time a particular color was used. Count it once. + _color_counts[autocad_color] = 1; + } else { + // This color has been used before. Count it again. + (*cci).second++; + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::choose_overall_color +// Access: Public +// Description: After all polygons have been accounted for, chooses +// the polygon color that occurred most often as the +// layer color. +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +choose_overall_color() { + int max_count = 0; + + ColorCounts::iterator cci; + for (cci = _color_counts.begin(); cci != _color_counts.end(); ++cci) { + int count = (*cci).second; + if (count > max_count) { + _layer_color = (*cci).first; + max_count = count; + } + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::write_layer +// Access: Public +// Description: Writes the layer definition into the table at the +// beginning of the DXF file. This does not write the +// actual geometry; that gets done later by +// write_entities(). +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +write_layer(ostream &out) { + out << "0\nLAYER\n" + << "2\n" << _group->get_name() << "\n" + << "70\n0\n" + << "62\n" << _layer_color << "\n" + << "6\nCONTINUOUS\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::write_polyline +// Access: Public +// Description: Writes a polygon as a POLYLINE entity. +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +write_polyline(EggPolygon *poly, ostream &out) { + out << "0\nPOLYLINE\n" + << "8\n" << _group->get_name() << "\n" + << "66\n1\n" + << "70\n1\n" + << "62\n" << get_autocad_color(poly->get_color()) << "\n"; + + // Since DXF uses a clockwise ordering convention, we must + // reverse the order in which we write out the vertices. + EggPolygon::reverse_iterator vi; + for (vi = poly->rbegin(); vi != poly->rend(); ++vi) { + EggVertex *vtx = (*vi); + LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame(); + out << "0\nVERTEX\n" + << "10\n" << pos[0] << "\n" + << "20\n" << pos[1] << "\n" + << "30\n" << pos[2] << "\n"; + } + out << "0\nSEQEND\n"; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::write_3d_face +// Access: Public +// Description: Writes a polygon as a 3DFACE entity. +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +write_3d_face(EggPolygon *poly, ostream &out) { + if (poly->size() > 4) { + // If we have a big polygon, we have to triangulate it, since + // 3DFaces can only be tris and quads. + PT(EggGroup) group = new EggGroup; + poly->triangulate_into(group, true); + + EggGroupNode::iterator ci; + for (ci = group->begin(); ci != group->end(); ++ci) { + EggNode *child = (*ci); + if (child->is_of_type(EggPolygon::get_class_type())) { + write_3d_face(DCAST(EggPolygon, child), out); + } + } + + } else if (poly->size() > 2) { + // Otherwise, if we have a tri or a quad, just write it out. + out << "0\n3DFACE\n" + << "8\n" << _group->get_name() << "\n"; + + int i; + EggPolygon::iterator vi; + for (i = 0, vi = poly->begin(); vi != poly->end(); ++i, ++vi) { + EggVertex *vtx = (*vi); + LVecBase3d pos = vtx->get_pos3() * _group->get_vertex_frame(); + out << 10 + i << "\n" << pos[0] << "\n" + << 20 + i << "\n" << pos[1] << "\n" + << 30 + i << "\n" << pos[2] << "\n"; + if (i == 2 && poly->size() == 3) { + // A special case for triangles: repeat the last vertex. + out << 11 + i << "\n" << pos[0] << "\n" + << 21 + i << "\n" << pos[1] << "\n" + << 31 + i << "\n" << pos[2] << "\n"; + } + } + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::write_entities +// Access: Public +// Description: Writes out the "entities", e.g. polygons, defined for +// the current layer. +//////////////////////////////////////////////////////////////////// +void EggToDXFLayer:: +write_entities(ostream &out) { + EggGroupNode::iterator ci; + for (ci = _group->begin(); ci != _group->end(); ++ci) { + EggNode *child = (*ci); + if (child->is_of_type(EggPolygon::get_class_type())) { + EggPolygon *poly = DCAST(EggPolygon, child); + if (_egg2dxf->_use_polyline) { + write_polyline(poly, out); + } else { + write_3d_face(poly, out); + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggToDXFLayer::get_autocad_color +// Access: Private +// Description: Returns the AutoCAD color index that most closely +// matches the indicated EggColor. +//////////////////////////////////////////////////////////////////// +int EggToDXFLayer:: +get_autocad_color(const Colorf &color) { + typedef pmap ColorMap; + static ColorMap _map; + + ColorMap::iterator cmi; + cmi = _map.find(color); + if (cmi != _map.end()) { + return (*cmi).second; + } + + int result = DXFFile::find_color(color[0], color[1], color[2]); + _map[color] = result; + return result; +} diff --git a/pandatool/src/dxfprogs/eggToDXFLayer.h b/pandatool/src/dxfprogs/eggToDXFLayer.h new file mode 100644 index 0000000000..5550ca539c --- /dev/null +++ b/pandatool/src/dxfprogs/eggToDXFLayer.h @@ -0,0 +1,63 @@ +// Filename: eggToDXFLayer.h +// Created by: drose (04May04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGTODXFLAYER_H +#define EGGTODXFLAYER_H + +#include "pandatoolbase.h" +#include "pmap.h" +#include "pvector.h" +#include "luse.h" + +class EggToDXF; +class EggPolygon; +class EggGroupNode; + +//////////////////////////////////////////////////////////////////// +// Class : EggToDXFLayer +// Description : A single layer in the DXF file to be written by +// EggToDXF. +//////////////////////////////////////////////////////////////////// +class EggToDXFLayer { +public: + EggToDXFLayer(EggToDXF *egg2dxf, EggGroupNode *group); + EggToDXFLayer(const EggToDXFLayer ©); + void operator = (const EggToDXFLayer ©); + + void add_color(const Colorf &color); + void choose_overall_color(); + + void write_layer(ostream &out); + void write_polyline(EggPolygon *poly, ostream &out); + void write_3d_face(EggPolygon *poly, ostream &out); + void write_entities(ostream &out); + +private: + int get_autocad_color(const Colorf &color); + + typedef pmap ColorCounts; + ColorCounts _color_counts; + + EggToDXF *_egg2dxf; + EggGroupNode *_group; + int _layer_color; +}; + +typedef pvector EggToDXFLayers; + +#endif