Browse Source

add egg2dxf

David Rose 21 years ago
parent
commit
0cd95c8f8d

+ 8 - 1
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;
   }

+ 2 - 1
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

+ 167 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}

+ 50 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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
+

+ 244 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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;
+}

+ 63 - 0
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
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#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