فهرست منبع

new experimental client/server static maya init maya2egg

Chris Brunner 16 سال پیش
والد
کامیت
7da51c899f

+ 50 - 0
pandatool/src/mayaprogs/Sources.pp

@@ -8,6 +8,14 @@
     mayapath.cxx
 #end bin_target
 
+#begin bin_target
+  #define TARGET maya2egg_server
+  #define OTHER_LIBS \
+    dtoolbase:c dtoolutil:c dtool:m
+  #define SOURCES \
+    mayapath.cxx
+#end bin_target
+
 #begin bin_target
   #define USE_PACKAGES maya
   #define TARGET maya2egg_bin
@@ -29,6 +37,48 @@
 
 #end bin_target
 
+#begin bin_target
+  #define USE_PACKAGES maya
+  #define TARGET maya2egg_server_bin
+  #define LOCAL_LIBS \
+    mayabase mayaegg eggbase progbase
+  #define OTHER_LIBS \
+    egg:c pandaegg:m \
+    linmath:c putil:c panda:m \
+    express:c pandaexpress:m \
+    interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m $[if $[WINDOWS_PLATFORM],pystub,] \
+    pipeline:c pnmimage:c
+
+  // Irix requires this to be named explicitly.
+  #define UNIX_SYS_LIBS \
+    ExtensionLayer
+
+  #define SOURCES \
+    mayaToEgg_server.cxx mayaToEgg_server.h
+
+#end bin_target
+
+#begin bin_target
+  #define USE_PACKAGES maya
+  #define TARGET maya2egg_client
+  #define LOCAL_LIBS \
+    mayabase mayaegg eggbase progbase
+  #define OTHER_LIBS \
+    egg:c pandaegg:m \
+    linmath:c putil:c panda:m \
+    express:c pandaexpress:m \
+    interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m $[if $[WINDOWS_PLATFORM],pystub,] \
+    pipeline:c pnmimage:c
+
+  // Irix requires this to be named explicitly.
+  #define UNIX_SYS_LIBS \
+    ExtensionLayer
+
+  #define SOURCES \
+    mayaToEgg_client.cxx mayaToEgg_client.h
+
+#end bin_target
+
 #begin bin_target
   #define TARGET egg2maya
   #define OTHER_LIBS \

+ 19 - 31
pandatool/src/mayaprogs/mayaCopy.cxx

@@ -71,10 +71,16 @@ MayaCopy() {
 
   add_option
     ("omittex", "", 0,
-     "Character animation files do not need to copy the texures nor its references. "
-     "This option omits the textures and references of the models to be re-mayacopied",
+     "Character animation files do not need to copy the texures. "
+     "This option omits the textures of the models to be re-mayacopied",
      &CVSCopy::dispatch_none, &_omit_tex);
 
+  add_option
+    ("omitref", "", 0,
+     "Character animation files do not need to copy internal file references. "
+     "This option omits the references of the models to be re-mayacopied",
+     &CVSCopy::dispatch_none, &_omit_ref);
+
   add_option
     ("ma", "", 0,
      "Write a .ma file instead of a .mb file (regardless of input type)",
@@ -250,33 +256,13 @@ copy_maya_file(const Filename &source, const Filename &dest,
       maya_cat.debug() << "result = " << result3.asChar() << "\n";
     }
     _exec_string.push_back("file -loadReference \"" + string(result.asChar()) + "\" -type \"mayaBinary\" -options \"v=0\" \"" + new_filename.to_os_generic() + "\";");
-    //MGlobal::executeCommand("file -loadReference \"mtpRN\" -type \"mayaBinary\" -options \"v=0\" \"m_t_pear_zero.mb\";");
-    maya_cat.info() << "executing command: " << _exec_string[_curr_idx] << "\n";
-    status  = MGlobal::executeCommand(MString(_exec_string[_curr_idx].c_str()));
-    if (status != MStatus::kSuccess) {
-      status.perror("loadReference failed");
-    }
-    /*
-    Filename filename = 
-      _path_replace->convert_path(Filename::from_os_specific(lookup));
-
-    CVSSourceTree::FilePath path =
-      _tree.choose_directory(filename.get_basename(), dir, _force, _interactive);
-    Filename new_filename = path.get_rel_from(dir);
-
-    maya_cat.info() << "lookup filename: " << filename.to_os_generic() << "\n";
-    string cmdStr = "chdir " + string(dir->get_fullpath().to_os_generic().c_str()) + ";";
-    maya_cat.info() << "new filename (relative): " << new_filename.to_os_generic() << "\n";
-    //maya_cat.info() << "new filename (absolute): " << path.get_fullpath().to_os_generic() << "\n";
-    MString loadedFilename = MFileIO::loadReference(MString(new_filename.to_os_generic().c_str()), &status);
-    //MString loadedFilename = MFileIO::loadReference(MString(path.get_fullpath().to_os_generic().c_str()), &status);
-    //MString loadedFilename = MFileIO::loadReferenceByNode(result, &status);
-    maya_cat.info() << "loaded filename: " << loadedFilename << "\n";
-
-    if (status != MStatus::kSuccess) {
-      status.perror("loadReference failed");
-    }
-    */
+    if (!_omit_ref) {
+        maya_cat.info() << "executing command: " << _exec_string[_curr_idx] << "\n";
+        status  = MGlobal::executeCommand(MString(_exec_string[_curr_idx].c_str()));
+        if (status != MStatus::kSuccess) {
+          status.perror("loadReference failed");
+        }
+     }
     _curr_idx++;
   }
 
@@ -344,11 +330,13 @@ extract_texture(MayaShaderColorDef &color_def, CVSSourceDirectory *dir) {
   Filename texture_filename = 
     _path_replace->convert_path(color_def._texture_filename);
   if (!texture_filename.exists()) {
-    nout << "*** Warning: texture " << texture_filename
+    nout << "*** Error: texture " << texture_filename
          << " does not exist.\n";
+    return false;
   } else if (!texture_filename.is_regular_file()) {
-    nout << "*** Warning: texture " << texture_filename
+    nout << "*** Error: texture " << texture_filename
          << " is not a regular file.\n";
+    return false;
   } else {
     ExtraData ed;
     ed._type = FT_texture;

+ 1 - 0
pandatool/src/mayaprogs/mayaCopy.h

@@ -69,6 +69,7 @@ private:
 
   bool _keep_ver;
   bool _omit_tex;
+  bool _omit_ref;
   int _curr_idx;
   bool _maya_ascii;
   /*

+ 372 - 0
pandatool/src/mayaprogs/mayaToEgg_client.cxx

@@ -0,0 +1,372 @@
+// Filename: mayaToEgg.cxx
+// Created by:  drose (15Feb00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#include "mayaToEgg_client.h"
+#include "mayaToEggConverter.h"
+#include "config_mayaegg.h"
+#include "config_maya.h"  // for maya_cat
+#include "globPattern.h"
+#ifdef _WIN32
+  #include "pystub.h"
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+MayaToEgg::
+MayaToEgg() :
+  SomethingToEgg("Maya", ".mb")
+{
+  add_path_replace_options();
+  add_path_store_options();
+  add_animation_options();
+  add_units_options();
+  add_normals_options();
+  add_transform_options();
+
+  set_program_description
+    ("This program converts Maya model files to egg.  Static and animatable "
+     "models can be converted, with polygon or NURBS output.  Animation tables "
+     "can also be generated to apply to an animatable model.");
+
+  add_option
+    ("p", "", 0,
+     "Generate polygon output only.  Tesselate all NURBS surfaces to "
+     "polygons via the built-in Maya tesselator.  The tesselation will "
+     "be based on the tolerance factor given by -ptol.",
+     &MayaToEgg::dispatch_none, &_polygon_output);
+
+  add_option
+    ("ptol", "tolerance", 0,
+     "Specify the fit tolerance for Maya polygon tesselation.  The smaller "
+     "the number, the more polygons will be generated.  The default is "
+     "0.01.",
+     &MayaToEgg::dispatch_double, NULL, &_polygon_tolerance);
+
+  add_option
+    ("bface", "", 0,
+     "Respect the Maya \"double sided\" rendering flag to indicate whether "
+     "polygons should be double-sided or single-sided.  Since this flag "
+     "is set to double-sided by default in Maya, it is often better to "
+     "ignore this flag (unless your modelers are diligent in turning it "
+     "off where it is not desired).  If this flag is not specified, the "
+     "default is to treat all polygons as single-sided, unless an "
+     "egg object type of \"double-sided\" is set.",
+     &MayaToEgg::dispatch_none, &_respect_maya_double_sided);
+
+  add_option
+    ("suppress-vcolor", "", 0,
+     "Ignore vertex color for geometry that has a texture applied.  "
+     "(This is the way Maya normally renders internally.)  The egg flag "
+     "'vertex-color' may be applied to a particular model to override "
+     "this setting locally.",
+     &MayaToEgg::dispatch_none, &_suppress_vertex_color);
+
+  add_option
+    ("keep-uvs", "", 0,
+     "Convert all UV sets on all vertices, even those that do not appear "
+     "to be referenced by any textures.",
+     &MayaToEgg::dispatch_none, &_keep_all_uvsets);
+
+  add_option
+    ("round-uvs", "", 0,
+     "round up uv coordinates to the nearest 1/100th. i.e. -0.001 becomes"
+     "0.0; 0.444 becomes 0.44; 0.778 becomes 0.78.",
+     &MayaToEgg::dispatch_none, &_round_uvs);
+
+  add_option
+    ("trans", "type", 0,
+     "Specifies which transforms in the Maya file should be converted to "
+     "transforms in the egg file.  The option may be one of all, model, "
+     "dcs, or none.  The default is model, which means only transforms on "
+     "nodes that have the model flag or the dcs flag are preserved.",
+     &MayaToEgg::dispatch_transform_type, NULL, &_transform_type);
+
+  add_option
+    ("subroot", "name", 0,
+     "Specifies that only a subroot of the geometry in the Maya file should "
+     "be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.  If it is omitted altogether, the entire file is "
+     "converted.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_subroots);
+
+  add_option
+    ("subset", "name", 0,
+     "Specifies that only a subset of the geometry in the Maya file should "
+     "be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.  If it is omitted altogether, the entire file is "
+     "converted.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_subsets);
+
+  add_option
+    ("exclude", "name", 0,
+     "Specifies that a subset of the geometry in the Maya file should "
+     "not be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_excludes);
+
+  add_option
+    ("ignore-slider", "name", 0,
+     "Specifies the name of a slider (blend shape deformer) that maya2egg "
+     "should not process.  The slider will not be touched during conversion "
+     "and it will not become a part of the animation.  This "
+     "parameter may including globbing characters, and it may be repeated "
+     "as needed.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_ignore_sliders);
+
+  add_option
+    ("force-joint", "name", 0,
+     "Specifies the name of a DAG node that maya2egg "
+     "should treat as a joint, even if it does not appear to be a Maya joint "
+     "and does not appear to be animated.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_force_joints);
+
+  add_option
+    ("v", "", 0,
+     "Increase verbosity.  More v's means more verbose.",
+     &MayaToEgg::dispatch_count, NULL, &_verbose);
+
+  // Unfortunately, the Maya API doesn't allow us to differentiate
+  // between relative and absolute pathnames--everything comes out as
+  // an absolute pathname, even if it is stored in the Maya file as a
+  // relative path.  So we can't support -noabs.
+  remove_option("noabs");
+
+  _verbose = 0;
+  _polygon_tolerance = 0.01;
+  _transform_type = MayaToEggConverter::TT_model;
+  _got_tbnauto = true;
+  manager = new QueuedConnectionManager();
+  reader = new QueuedConnectionReader(manager, 0);
+  writer = new ConnectionWriter(manager, 0);
+  server.set_host("localhost", 4242);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void MayaToEgg::
+run() {
+  // Set the verbose level by using Notify.
+  if (_verbose >= 3) {
+    maya_cat->set_severity(NS_spam);
+    mayaegg_cat->set_severity(NS_spam);
+  } else if (_verbose >= 2) {
+    maya_cat->set_severity(NS_debug);
+    mayaegg_cat->set_severity(NS_debug);
+  } else if (_verbose >= 1) {
+    maya_cat->set_severity(NS_info);
+    mayaegg_cat->set_severity(NS_info);
+  }
+
+  // Let's convert the output file to a full path before we initialize
+  // Maya, since Maya now has a nasty habit of changing the current
+  // directory.
+  if (_got_output_filename) {
+    _output_filename.make_absolute();
+  }
+
+  nout << "Initializing Maya.\n";
+  MayaToEggConverter converter(_program_name);
+  if (!converter.open_api()) {
+    nout << "Unable to initialize Maya.\n";
+    exit(1);
+  }
+
+  // Copy in the command-line parameters.
+  converter._polygon_output = _polygon_output;
+  converter._polygon_tolerance = _polygon_tolerance;
+  converter._respect_maya_double_sided = _respect_maya_double_sided;
+  converter._always_show_vertex_color = !_suppress_vertex_color;
+  converter._keep_all_uvsets = _keep_all_uvsets;
+  converter._round_uvs = _round_uvs;
+  converter._transform_type = _transform_type;
+
+  vector_string::const_iterator si;
+  if (!_subroots.empty()) {
+    converter.clear_subroots();
+    for (si = _subroots.begin(); si != _subroots.end(); ++si) {
+      converter.add_subroot(GlobPattern(*si));
+    }
+  }
+
+  if (!_subsets.empty()) {
+    converter.clear_subsets();
+    for (si = _subsets.begin(); si != _subsets.end(); ++si) {
+      converter.add_subset(GlobPattern(*si));
+    }
+  }
+
+  if (!_excludes.empty()) {
+    converter.clear_excludes();
+    for (si = _excludes.begin(); si != _excludes.end(); ++si) {
+      converter.add_exclude(GlobPattern(*si));
+    }
+  }
+
+  if (!_ignore_sliders.empty()) {
+    converter.clear_ignore_sliders();
+    for (si = _ignore_sliders.begin(); si != _ignore_sliders.end(); ++si) {
+      converter.add_ignore_slider(GlobPattern(*si));
+    }
+  }
+
+  if (!_force_joints.empty()) {
+    converter.clear_force_joints();
+    for (si = _force_joints.begin(); si != _force_joints.end(); ++si) {
+      converter.add_force_joint(GlobPattern(*si));
+    }
+  }
+
+  // Copy in the path and animation parameters.
+  apply_parameters(converter);
+
+  // Set the coordinate system to match Maya's.
+  if (!_got_coordinate_system) {
+    _coordinate_system = converter._maya->get_coordinate_system();
+  }
+  _data->set_coordinate_system(_coordinate_system);
+
+  converter.set_egg_data(_data);
+
+  if (!converter.convert_file(_input_filename)) {
+    nout << "Errors in conversion.\n";
+    exit(1);
+  }
+
+  // Use the standard Maya units, if the user didn't specify
+  // otherwise.  This always returns centimeters, which is the way all
+  // Maya files are stored internally (and is the units returned by
+  // all of the API functions called here).
+  if (_input_units == DU_invalid) {
+    _input_units = converter.get_input_units();
+  }
+
+  write_egg_file();
+  nout << "\n";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::dispatch_transform_type
+//       Access: Protected, Static
+//  Description: Dispatches a parameter that expects a
+//               MayaToEggConverter::TransformType option.
+////////////////////////////////////////////////////////////////////
+bool MayaToEgg::
+dispatch_transform_type(const string &opt, const string &arg, void *var) {
+  MayaToEggConverter::TransformType *ip = (MayaToEggConverter::TransformType *)var;
+  (*ip) = MayaToEggConverter::string_transform_type(arg);
+
+  if ((*ip) == MayaToEggConverter::TT_invalid) {
+    nout << "Invalid type for -" << opt << ": " << arg << "\n"
+         << "Valid types are all, model, dcs, and none.\n";
+    return false;
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::poll
+//       Access: Public
+//  Description: Checks for any network activity and handles it, if
+//               appropriate, and then returns.  This must be called
+//               periodically
+////////////////////////////////////////////////////////////////////
+void MayaToEgg::
+poll() {
+  // Delete all the readers that we couldn't delete before.
+  while (!_lost_readers.empty()) {
+    QueuedConnectionReader *reader = _lost_readers.back();
+    _lost_readers.pop_back();
+
+    delete reader;
+  }
+  while (!_removed_readers.empty()) {
+    QueuedConnectionReader *reader = _removed_readers.back();
+    _removed_readers.pop_back();
+    delete reader;
+  }
+
+  // listener->poll();
+
+  Readers::const_iterator ri = _readers.begin();
+  while (ri != _readers.end()) {
+    // Preincrement the iterator, in case we remove it as a result of
+    // calling poll().
+    Readers::const_iterator rnext = ri;
+    ++rnext;
+    QueuedConnectionReader *reader = (*ri).second;
+
+    reader->poll();
+    
+    ri = rnext;
+  }
+}
+
+int main(int argc, char *argv[]) {
+  // We don't want pystub on linux, since it gives problems with Maya's python.
+#ifdef _WIN32
+  // A call to pystub() to force libpystub.so to be linked in.
+  pystub();
+#endif
+
+  MayaToEgg prog;
+  // prog.parse_command_line(argc, argv);
+  // prog.run();
+  
+  // TODO: 
+  //  - Open a socket and wait for communications
+  //  - When communication is received, send along argc and argv to 
+  //    prog.parase_command_line and prog.run()
+  //    [ see commented out section above ]
+  //  - Go back to waiting
+  PT(Connection) con = prog.manager->open_TCP_client_connection(prog.server,0);
+  if (con.is_null()) {
+    nout << "port opened fail";
+  }
+
+  prog.reader->add_connection(con);
+
+  Filename cwd = ExecutionEnvironment::get_cwd();
+  string s_cwd = (string)cwd.to_os_specific();
+  nout << "CWD: " << s_cwd << "\n";
+
+  nout << "building datagram\n";
+  NetDatagram datagram;
+  
+  datagram.add_uint8(argc);
+
+  int i;
+  for (i = 0; i < argc; i++) {
+    datagram.add_string(argv[i]);
+  }
+
+  datagram.add_string(s_cwd);
+  nout << "sending datagram\n";
+  prog.writer->send(datagram, con);
+  prog.manager->close_connection(con);
+  return 0;
+}
+

+ 64 - 0
pandatool/src/mayaprogs/mayaToEgg_client.h

@@ -0,0 +1,64 @@
+// Filename: mayaToEgg.h
+// Created by:  drose (15Feb00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MAYATOEGG_H
+#define MAYATOEGG_H
+
+#include "pandatoolbase.h"
+#include "somethingToEgg.h"
+#include "mayaToEggConverter.h"
+#include "queuedConnectionManager.h"
+#include "queuedConnectionReader.h"
+#include "connectionWriter.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : MayaToEgg
+// Description :
+////////////////////////////////////////////////////////////////////
+class MayaToEgg : public SomethingToEgg {
+public:
+  MayaToEgg();
+
+  void run();
+  void poll();
+  QueuedConnectionManager *manager;
+  QueuedConnectionReader *reader;
+  ConnectionWriter *writer;
+  NetAddress server;
+
+protected:
+  static bool dispatch_transform_type(const string &opt, const string &arg, void *var);
+
+  int _verbose;
+  bool _polygon_output;
+  double _polygon_tolerance;
+  bool _respect_maya_double_sided;
+  bool _suppress_vertex_color;
+  bool _keep_all_uvsets;
+  bool _round_uvs;
+  MayaToEggConverter::TransformType _transform_type;
+  vector_string _subroots; 
+  vector_string _subsets;
+  vector_string _excludes;
+  vector_string _ignore_sliders;
+  vector_string _force_joints;
+
+  typedef pmap<PT(Connection), QueuedConnectionReader *> Readers;
+  Readers _readers;
+  typedef pvector<QueuedConnectionReader *> LostReaders;
+  LostReaders _lost_readers;
+  LostReaders _removed_readers;
+};
+
+#endif

+ 432 - 0
pandatool/src/mayaprogs/mayaToEgg_server.cxx

@@ -0,0 +1,432 @@
+// Filename: mayaToEgg.cxx
+// Created by:  drose (15Feb00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32_VC
+#include <direct.h>  // for chdir
+#endif
+#include "mayaToEgg_server.h"
+#include "mayaToEggConverter.h"
+#include "config_mayaegg.h"
+#include "config_maya.h"  // for maya_cat
+#include "globPattern.h"
+#ifdef _WIN32
+  #include "pystub.h"
+#endif
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+MayaToEgg::
+MayaToEgg() :
+  SomethingToEgg("Maya", ".mb")
+{
+  add_path_replace_options();
+  add_path_store_options();
+  add_animation_options();
+  add_units_options();
+  add_normals_options();
+  add_transform_options();
+
+  set_program_description
+    ("This program converts Maya model files to egg.  Static and animatable "
+     "models can be converted, with polygon or NURBS output.  Animation tables "
+     "can also be generated to apply to an animatable model.");
+
+  add_option
+    ("p", "", 0,
+     "Generate polygon output only.  Tesselate all NURBS surfaces to "
+     "polygons via the built-in Maya tesselator.  The tesselation will "
+     "be based on the tolerance factor given by -ptol.",
+     &MayaToEgg::dispatch_none, &_polygon_output);
+
+  add_option
+    ("ptol", "tolerance", 0,
+     "Specify the fit tolerance for Maya polygon tesselation.  The smaller "
+     "the number, the more polygons will be generated.  The default is "
+     "0.01.",
+     &MayaToEgg::dispatch_double, NULL, &_polygon_tolerance);
+
+  add_option
+    ("bface", "", 0,
+     "Respect the Maya \"double sided\" rendering flag to indicate whether "
+     "polygons should be double-sided or single-sided.  Since this flag "
+     "is set to double-sided by default in Maya, it is often better to "
+     "ignore this flag (unless your modelers are diligent in turning it "
+     "off where it is not desired).  If this flag is not specified, the "
+     "default is to treat all polygons as single-sided, unless an "
+     "egg object type of \"double-sided\" is set.",
+     &MayaToEgg::dispatch_none, &_respect_maya_double_sided);
+
+  add_option
+    ("suppress-vcolor", "", 0,
+     "Ignore vertex color for geometry that has a texture applied.  "
+     "(This is the way Maya normally renders internally.)  The egg flag "
+     "'vertex-color' may be applied to a particular model to override "
+     "this setting locally.",
+     &MayaToEgg::dispatch_none, &_suppress_vertex_color);
+
+  add_option
+    ("keep-uvs", "", 0,
+     "Convert all UV sets on all vertices, even those that do not appear "
+     "to be referenced by any textures.",
+     &MayaToEgg::dispatch_none, &_keep_all_uvsets);
+
+  add_option
+    ("round-uvs", "", 0,
+     "round up uv coordinates to the nearest 1/100th. i.e. -0.001 becomes"
+     "0.0; 0.444 becomes 0.44; 0.778 becomes 0.78.",
+     &MayaToEgg::dispatch_none, &_round_uvs);
+
+  add_option
+    ("trans", "type", 0,
+     "Specifies which transforms in the Maya file should be converted to "
+     "transforms in the egg file.  The option may be one of all, model, "
+     "dcs, or none.  The default is model, which means only transforms on "
+     "nodes that have the model flag or the dcs flag are preserved.",
+     &MayaToEgg::dispatch_transform_type, NULL, &_transform_type);
+
+  add_option
+    ("subroot", "name", 0,
+     "Specifies that only a subroot of the geometry in the Maya file should "
+     "be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.  If it is omitted altogether, the entire file is "
+     "converted.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_subroots);
+
+  add_option
+    ("subset", "name", 0,
+     "Specifies that only a subset of the geometry in the Maya file should "
+     "be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.  If it is omitted altogether, the entire file is "
+     "converted.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_subsets);
+
+  add_option
+    ("exclude", "name", 0,
+     "Specifies that a subset of the geometry in the Maya file should "
+     "not be converted; specifically, the geometry under the node or nodes whose "
+     "name matches the parameter (which may include globbing characters "
+     "like * or ?).  This parameter may be repeated multiple times to name "
+     "multiple roots.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_excludes);
+
+  add_option
+    ("ignore-slider", "name", 0,
+     "Specifies the name of a slider (blend shape deformer) that maya2egg "
+     "should not process.  The slider will not be touched during conversion "
+     "and it will not become a part of the animation.  This "
+     "parameter may including globbing characters, and it may be repeated "
+     "as needed.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_ignore_sliders);
+
+  add_option
+    ("force-joint", "name", 0,
+     "Specifies the name of a DAG node that maya2egg "
+     "should treat as a joint, even if it does not appear to be a Maya joint "
+     "and does not appear to be animated.",
+     &MayaToEgg::dispatch_vector_string, NULL, &_force_joints);
+
+  add_option
+    ("v", "", 0,
+     "Increase verbosity.  More v's means more verbose.",
+     &MayaToEgg::dispatch_count, NULL, &_verbose);
+
+  // Unfortunately, the Maya API doesn't allow us to differentiate
+  // between relative and absolute pathnames--everything comes out as
+  // an absolute pathname, even if it is stored in the Maya file as a
+  // relative path.  So we can't support -noabs.
+  remove_option("noabs");
+
+  _verbose = 0;
+  _polygon_tolerance = 0.01;
+  _transform_type = MayaToEggConverter::TT_model;
+  _got_tbnauto = true;
+  qManager = new QueuedConnectionManager();
+  qListener = new QueuedConnectionListener(qManager, 0);
+  qReader = new QueuedConnectionReader(qManager, 0);
+  dummy = new MayaToEggConverter();
+  nout << "Initializing Maya...\n";
+  if (!dummy->open_api()) {
+    nout << "Unable to initialize May.\n";
+    exit(1);
+  }
+}
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+MayaToEgg::
+~MayaToEgg() {
+  delete qManager;
+  delete qReader;
+  delete qListener;
+  delete dummy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void MayaToEgg::
+run() {
+  // Set the verbose level by using Notify.
+  if (_verbose >= 3) {
+    maya_cat->set_severity(NS_spam);
+    mayaegg_cat->set_severity(NS_spam);
+  } else if (_verbose >= 2) {
+    maya_cat->set_severity(NS_debug);
+    mayaegg_cat->set_severity(NS_debug);
+  } else if (_verbose >= 1) {
+    maya_cat->set_severity(NS_info);
+    mayaegg_cat->set_severity(NS_info);
+  }
+
+  // Let's convert the output file to a full path before we initialize
+  // Maya, since Maya now has a nasty habit of changing the current
+  // directory.
+  if (_got_output_filename) {
+    _output_filename.make_absolute();
+  }
+
+  // Make sure we have good clean data to start with
+  _data = new EggData();
+
+  // So our relative path names come out correctly
+  _path_replace->_path_directory = get_output_filename().get_dirname();
+
+  MayaToEggConverter converter(_program_name);
+
+  // Copy in the command-line parameters.
+  converter._polygon_output = _polygon_output;
+  converter._polygon_tolerance = _polygon_tolerance;
+  converter._respect_maya_double_sided = _respect_maya_double_sided;
+  converter._always_show_vertex_color = !_suppress_vertex_color;
+  converter._keep_all_uvsets = _keep_all_uvsets;
+  converter._round_uvs = _round_uvs;
+  converter._transform_type = _transform_type;
+
+  vector_string::const_iterator si;
+  if (!_subroots.empty()) {
+    converter.clear_subroots();
+    for (si = _subroots.begin(); si != _subroots.end(); ++si) {
+      converter.add_subroot(GlobPattern(*si));
+    }
+  }
+
+  if (!_subsets.empty()) {
+    converter.clear_subsets();
+    for (si = _subsets.begin(); si != _subsets.end(); ++si) {
+      converter.add_subset(GlobPattern(*si));
+    }
+  }
+
+  if (!_excludes.empty()) {
+    converter.clear_excludes();
+    for (si = _excludes.begin(); si != _excludes.end(); ++si) {
+      converter.add_exclude(GlobPattern(*si));
+    }
+  }
+
+  if (!_ignore_sliders.empty()) {
+    converter.clear_ignore_sliders();
+    for (si = _ignore_sliders.begin(); si != _ignore_sliders.end(); ++si) {
+      converter.add_ignore_slider(GlobPattern(*si));
+    }
+  }
+
+  if (!_force_joints.empty()) {
+    converter.clear_force_joints();
+    for (si = _force_joints.begin(); si != _force_joints.end(); ++si) {
+      converter.add_force_joint(GlobPattern(*si));
+    }
+  }
+
+  // Copy in the path and animation parameters.
+  apply_parameters(converter);
+
+  // Set the coordinate system to match Maya's.
+  if (!_got_coordinate_system) {
+    _coordinate_system = converter._maya->get_coordinate_system();
+  }
+  _data->set_coordinate_system(_coordinate_system);
+
+  converter.set_egg_data(_data);
+
+  if (!converter.convert_file(_input_filename)) {
+    nout << "Errors in conversion.\n";
+    exit(1);
+  }
+
+  // Use the standard Maya units, if the user didn't specify
+  // otherwise.  This always returns centimeters, which is the way all
+  // Maya files are stored internally (and is the units returned by
+  // all of the API functions called here).
+  if (_input_units == DU_invalid) {
+    _input_units = converter.get_input_units();
+  }
+  write_egg_file();
+  
+  // Clean and out
+  close_output();
+  _data->clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::dispatch_transform_type
+//       Access: Protected, Static
+//  Description: Dispatches a parameter that expects a
+//               MayaToEggConverter::TransformType option.
+////////////////////////////////////////////////////////////////////
+bool MayaToEgg::
+dispatch_transform_type(const string &opt, const string &arg, void *var) {
+  MayaToEggConverter::TransformType *ip = (MayaToEggConverter::TransformType *)var;
+  (*ip) = MayaToEggConverter::string_transform_type(arg);
+
+  if ((*ip) == MayaToEggConverter::TT_invalid) {
+    nout << "Invalid type for -" << opt << ": " << arg << "\n"
+         << "Valid types are all, model, dcs, and none.\n";
+    return false;
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEgg::poll
+//       Access: Public
+//  Description: Checks for any network activity and handles it, if
+//               appropriate, and then returns.  This must be called
+//               periodically
+////////////////////////////////////////////////////////////////////
+void MayaToEgg::
+poll() {
+  // Listen for new connections
+  qListener->poll();
+
+  // If we have a new connection from a client create a new connection
+  // pointer and add it to the reader list
+  if (qListener->new_connection_available()) {
+    PT(Connection) con;
+    if (qListener->get_new_connection(con)) {
+      qReader->add_connection(con);
+    }
+  }
+  
+  // Poll the readers (created above) and if they have data process it
+  qReader->poll();
+  if (qReader->data_available()) {
+    // Grab the incomming data and unpack it
+    NetDatagram datagram;
+    if (qReader->get_data(datagram)) {
+      DatagramIterator data(datagram);
+      nout << "receiving data\n";
+      // First data should be the "argc" (argument count) from the client
+      int argc = data.get_uint8();
+
+      // Now we have to get clever because the rest of the data comes as strings
+      // and parse_command_line() expects arguments of the standard argc, argv*[]
+      // variety.
+      // First, we need a string vector to hold all the strings from the datagram.
+      // We also need a char * array to keep track of all the pointers we're gonna
+      // malloc.  Needed later for cleanup.
+      vector_string vargv;
+      vector<char *> buffers;
+
+      // Get the strings from the datagram and put them into the string vector
+      int i;
+      for ( i = 0; i < argc; i++ ) {
+        vargv.push_back(data.get_string());
+      }
+
+      // Last string is the current directory the client was run from. Not part of
+      // the argument list, but we still need it
+      string cwd = data.get_string();
+
+      // We allocate some memory to hold the pointers to the pointers we're going to
+      // pass in to parse_command_line().
+      char ** cargv = (char**) malloc(sizeof(char**) * argc);
+
+      // Loop through the string arguments we got from the datagram and convert
+      // them to const char *'s.  parse_command_line() expects char *'s, so we have
+      // to copy these const versions into fresh char *, since there is no casting
+      // from const char * to char *.
+      for ( i = 0; i < argc; i++) {
+        // string to const char *
+        const char * cptr = vargv[i].c_str();
+        // memory allocated for a new char * of size of the string
+        char * buffer = (char*) malloc(vargv[i].capacity()+1);
+        // Copy the const char * to the char *
+        strcpy(buffer, cptr);
+        // put this into the arry we defined above.  This is what will eventually
+        // be passed to parse_command_line()
+        cargv[i] = buffer;
+        // keep track of the pointers to the  allocated memory for cleanup later
+        buffers.push_back(buffer);
+      }
+      // Change to the client's current dir
+      chdir(cwd.c_str());
+
+      // Pass in the 'new' argc and argv we got from the client
+      this->parse_command_line(argc, cargv);
+      // Actually run the damn thing
+      this->run();
+
+      // Cleanup
+      // First, release the string vector
+      vargv.clear();
+      // No, iterate through the char * vector and cleanup the malloc'd
+      // pointers
+      vector<char *>::iterator vi;
+      for ( vi = buffers.begin() ; vi != buffers.end(); vi++) {
+        free(*vi);
+      }
+      // Clean up the malloc'd pointer pointer
+      free(cargv);
+    } // qReader->get_data
+  } // qReader->data_available
+} // poll
+
+int main(int argc, char *argv[]) {
+  // We don't want pystub on linux, since it gives problems with Maya's python.
+#ifdef _WIN32
+  // A call to pystub() to force libpystub.so to be linked in.
+  pystub();
+#endif
+
+  MayaToEgg prog;
+  // Open a rendezvous port for receiving new connections from the client
+  PT(Connection) rend = prog.qManager->open_TCP_server_rendezvous(4242, 50);
+  if (rend.is_null()) {
+    nout << "port opened fail";
+  }
+
+  // Add this connection to the listeners list
+  prog.qListener->add_connection(rend);
+
+  // Main loop.  Keep polling for connections, but don't eat up all the CPU.
+  while (true) {
+    prog.poll();
+    Thread::force_yield();
+  }
+  return 0;
+}
+

+ 63 - 0
pandatool/src/mayaprogs/mayaToEgg_server.h

@@ -0,0 +1,63 @@
+// Filename: mayaToEgg.h
+// Created by:  drose (15Feb00)
+//
+////////////////////////////////////////////////////////////////////
+//
+// 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."
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef MAYATOEGG_H
+#define MAYATOEGG_H
+
+#include "pandatoolbase.h"
+#include "somethingToEgg.h"
+#include "mayaToEggConverter.h"
+#include "queuedConnectionManager.h"
+#include "queuedConnectionListener.h"
+#include "queuedConnectionReader.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : MayaToEgg
+// Description :
+////////////////////////////////////////////////////////////////////
+class MayaToEgg : public SomethingToEgg {
+public:
+  MayaToEgg();
+  ~MayaToEgg();
+
+  void run();
+  void poll();
+
+  void add_reader(Connection *connection, QueuedConnectionReader *reader);
+  void remove_reader(Connection *connection, QueuedConnectionReader *reader);
+  QueuedConnectionManager *qManager;
+  QueuedConnectionListener *qListener;
+  QueuedConnectionReader *qReader;
+  MayaToEggConverter *dummy;
+
+
+protected:
+  static bool dispatch_transform_type(const string &opt, const string &arg, void *var);
+
+  int _verbose;
+  bool _polygon_output;
+  double _polygon_tolerance;
+  bool _respect_maya_double_sided;
+  bool _suppress_vertex_color;
+  bool _keep_all_uvsets;
+  bool _round_uvs;
+  MayaToEggConverter::TransformType _transform_type;
+  vector_string _subroots; 
+  vector_string _subsets;
+  vector_string _excludes;
+  vector_string _ignore_sliders;
+  vector_string _force_joints;
+};
+
+#endif