add egg2dxf

This commit is contained in:
David Rose 2004-05-04 23:06:23 +00:00
parent 01776f36c2
commit 0cd95c8f8d
6 changed files with 534 additions and 2 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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 &copy) :
_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 &copy) {
_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<Colorf, int> 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;
}

View File

@ -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 &copy);
void operator = (const EggToDXFLayer &copy);
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<int, int> ColorCounts;
ColorCounts _color_counts;
EggToDXF *_egg2dxf;
EggGroupNode *_group;
int _layer_color;
};
typedef pvector<EggToDXFLayer> EggToDXFLayers;
#endif