Browse Source

beginning animation stuff in maya

David Rose 23 years ago
parent
commit
41828cfea9

+ 2 - 0
pandatool/src/converter/Sources.pp

@@ -8,11 +8,13 @@
     m
 
   #define SOURCES \
+    animationConvert.cxx animationConvert.h \
     distanceUnit.cxx distanceUnit.h \
     somethingToEggConverter.I somethingToEggConverter.cxx \
     somethingToEggConverter.h
 
   #define INSTALL_HEADERS \
+    animationConvert.h \
     distanceUnit.h \
     somethingToEggConverter.I somethingToEggConverter.h
 

+ 70 - 0
pandatool/src/converter/animationConvert.cxx

@@ -0,0 +1,70 @@
+// Filename: animationConvert.cxx
+// Created by:  drose (21Jan03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "animationConvert.h"
+
+#include "string_utils.h"
+#include "notify.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: format_animation_convert
+//  Description: Returns the string corresponding to this method.
+////////////////////////////////////////////////////////////////////
+string
+format_animation_convert(AnimationConvert convert) {
+  switch (convert) {
+  case AC_invalid:
+    return "invalid";
+
+  case AC_none:
+    return "none";
+
+  case AC_flip:
+    return "flip";
+  }
+  nout << "**unexpected AnimationConvert value: (" << (int)convert << ")**";
+  return "**";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimationConvert output operator
+//  Description:
+////////////////////////////////////////////////////////////////////
+ostream &
+operator << (ostream &out, AnimationConvert convert) {
+  return out << format_animation_convert(convert);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: string_animation_convert
+//  Description: Converts from a string, as might be input by the
+//               user, to one of the known AnimationConvert types.
+//               Returns AC_invalid if the string is unknown.
+////////////////////////////////////////////////////////////////////
+AnimationConvert
+string_animation_convert(const string &str) {
+  if (cmp_nocase(str, "none") == 0) {
+    return AC_none;
+
+  } else if (cmp_nocase(str, "flip") == 0) {
+    return AC_flip;
+
+  } else {
+    return AC_invalid;
+  }
+}

+ 41 - 0
pandatool/src/converter/animationConvert.h

@@ -0,0 +1,41 @@
+// Filename: animationConvert.h
+// Created by:  drose (21Jan03)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef ANIMATIONCONVERT_H
+#define ANIMATIONCONVERT_H
+
+#include "pandatoolbase.h"
+
+////////////////////////////////////////////////////////////////////
+//        Enum : AnimationConvert
+// Description : This enumerated type lists the methods by which
+//               animation from an animation package might be
+//               represented in egg format.
+////////////////////////////////////////////////////////////////////
+enum AnimationConvert {
+  AC_invalid,
+  AC_none,
+  AC_flip,
+};
+
+string format_animation_convert(AnimationConvert unit);
+
+ostream &operator << (ostream &out, AnimationConvert unit);
+AnimationConvert string_animation_convert(const string &str);
+
+#endif

+ 303 - 0
pandatool/src/converter/somethingToEggConverter.I

@@ -65,6 +65,309 @@ set_model_path_convert(PathConvert mpc,
   _mpc_directory = mpc_directory;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_animation_convert
+//       Access: Public
+//  Description: Specifies how source animation will be converted into
+//               egg structures.  The default is AC_none, which means
+//               animation tables will be ignored.  This is only
+//               meaningful for converters that understand animation.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_animation_convert(AnimationConvert animation_convert) {
+  _animation_convert = animation_convert;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_animation_convert
+//       Access: Public
+//  Description: Returns how source animation will be converted into
+//               egg structures.
+////////////////////////////////////////////////////////////////////
+INLINE AnimationConvert SomethingToEggConverter::
+get_animation_convert() const {
+  return _animation_convert;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_start_frame
+//       Access: Public
+//  Description: Specifies the starting frame of the animation to
+//               convert, in the units specified by
+//               set_input_frame_rate().  If this is unspecified, the
+//               starting frame is taken from the source, for instance
+//               from the first frame of the animation slider.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_start_frame(double start_frame) {
+  _start_frame = start_frame;
+  _control_flags |= CF_start_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::has_start_frame
+//       Access: Public
+//  Description: Returns true if the starting frame has been
+//               explicitly specified via set_start_frame(), or false
+//               if the starting frame should be implicit based on the
+//               source.
+////////////////////////////////////////////////////////////////////
+INLINE bool SomethingToEggConverter::
+has_start_frame() const {
+  return (_control_flags & CF_start_frame) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_start_frame
+//       Access: Public
+//  Description: Returns the value set by a previous call to
+//               set_start_frame().  It is an error to call this if
+//               has_start_frame() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_start_frame() const {
+  nassertr(has_start_frame(), 0.0);
+  return _start_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::clear_start_frame
+//       Access: Public
+//  Description: Removes the value previously set by
+//               set_start_frame().
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+clear_start_frame() {
+  _start_frame = 0.0;
+  _control_flags &= ~CF_start_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_end_frame
+//       Access: Public
+//  Description: Specifies the ending frame of the animation to
+//               convert, in the units specified by
+//               set_input_frame_rate().  If this is unspecified, the
+//               ending frame is taken from the source, for instance
+//               from the last frame of the animation slider.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_end_frame(double end_frame) {
+  _end_frame = end_frame;
+  _control_flags |= CF_end_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::has_end_frame
+//       Access: Public
+//  Description: Returns true if the ending frame has been
+//               explicitly specified via set_end_frame(), or false
+//               if the ending frame should be implicit based on the
+//               source.
+////////////////////////////////////////////////////////////////////
+INLINE bool SomethingToEggConverter::
+has_end_frame() const {
+  return (_control_flags & CF_end_frame) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_end_frame
+//       Access: Public
+//  Description: Returns the value set by a previous call to
+//               set_end_frame().  It is an error to call this if
+//               has_end_frame() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_end_frame() const {
+  nassertr(has_end_frame(), 0.0);
+  return _end_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::clear_end_frame
+//       Access: Public
+//  Description: Removes the value previously set by
+//               set_end_frame().
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+clear_end_frame() {
+  _end_frame = 0.0;
+  _control_flags &= ~CF_end_frame;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_frame_inc
+//       Access: Public
+//  Description: Specifies the increment between frames to extract.
+//               This is the amount to increment the time slider (in
+//               units of internal_frame_rate) between extracting each
+//               frame.  If this is not specified, the default is
+//               taken from the animation package, or 1.0 if the
+//               animation package does not specified a frame
+//               increment.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_frame_inc(double frame_inc) {
+  _frame_inc = frame_inc;
+  _control_flags |= CF_frame_inc;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::has_frame_inc
+//       Access: Public
+//  Description: Returns true if the frame increment has been
+//               explicitly specified via set_frame_inc(), or false
+//               if the ending frame should be implicit based on the
+//               source.
+////////////////////////////////////////////////////////////////////
+INLINE bool SomethingToEggConverter::
+has_frame_inc() const {
+  return (_control_flags & CF_frame_inc) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_frame_inc
+//       Access: Public
+//  Description: Returns the value set by a previous call to
+//               set_frame_inc().  It is an error to call this if
+//               has_frame_inc() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_frame_inc() const {
+  nassertr(has_frame_inc(), 0.0);
+  return _frame_inc;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::clear_frame_inc
+//       Access: Public
+//  Description: Removes the value previously set by
+//               set_frame_inc().
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+clear_frame_inc() {
+  _frame_inc = 0.0;
+  _control_flags &= ~CF_frame_inc;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_input_frame_rate
+//       Access: Public
+//  Description: Specifies the number of frames per second that is
+//               represented by the "frame" unit in the animation
+//               package.  If this is omitted, it is taken from
+//               whatever the file header indicates.  Some animation
+//               packages do not encode a frame rate, in which case
+//               the default if this is omitted is the same as the
+//               output frame rate.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_input_frame_rate(double input_frame_rate) {
+  _input_frame_rate = input_frame_rate;
+  _control_flags |= CF_input_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::has_input_frame_rate
+//       Access: Public
+//  Description: Returns true if the frame rate has been
+//               explicitly specified via set_input_frame_rate(), or
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool SomethingToEggConverter::
+has_input_frame_rate() const {
+  return (_control_flags & CF_input_frame_rate) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_input_frame_rate
+//       Access: Public
+//  Description: Returns the value set by a previous call to
+//               set_input_frame_rate().  It is an error to call this
+//               if has_input_frame_rate() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_input_frame_rate() const {
+  nassertr(has_input_frame_rate(), 0.0);
+  return _input_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::clear_input_frame_rate
+//       Access: Public
+//  Description: Removes the value previously set by
+//               set_input_frame_rate().
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+clear_input_frame_rate() {
+  _input_frame_rate = 0.0;
+  _control_flags &= ~CF_input_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::set_output_frame_rate
+//       Access: Public
+//  Description: Specifies the number of frames per second that the
+//               resulting animation should be played at.  If this is
+//               omitted, it is taken to be the same as the input
+//               frame rate.
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+set_output_frame_rate(double output_frame_rate) {
+  _output_frame_rate = output_frame_rate;
+  _control_flags |= CF_output_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::has_output_frame_rate
+//       Access: Public
+//  Description: Returns true if the frame rate has been
+//               explicitly specified via set_output_frame_rate(), or
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool SomethingToEggConverter::
+has_output_frame_rate() const {
+  return (_control_flags & CF_output_frame_rate) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_output_frame_rate
+//       Access: Public
+//  Description: Returns the value set by a previous call to
+//               set_output_frame_rate().  It is an error to call this
+//               if has_output_frame_rate() returns false.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_output_frame_rate() const {
+  nassertr(has_output_frame_rate(), 0.0);
+  return _output_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::clear_output_frame_rate
+//       Access: Public
+//  Description: Removes the value previously set by
+//               set_output_frame_rate().
+////////////////////////////////////////////////////////////////////
+INLINE void SomethingToEggConverter::
+clear_output_frame_rate() {
+  _output_frame_rate = 0.0;
+  _control_flags &= ~CF_output_frame_rate;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEggConverter::get_default_frame_rate
+//       Access: Public, Static
+//  Description: Returns the default frame rate if nothing is
+//               specified for input_frame_rate or output_frame_rate,
+//               and the animation package does not have an implicit
+//               frame rate.
+////////////////////////////////////////////////////////////////////
+INLINE double SomethingToEggConverter::
+get_default_frame_rate() {
+  return 24.0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SomethingToEggConverter::set_merge_externals
 //       Access: Public

+ 7 - 0
pandatool/src/converter/somethingToEggConverter.cxx

@@ -31,6 +31,13 @@ SomethingToEggConverter() {
   _allow_errors = false;
   _tpc = PC_absolute;
   _mpc = PC_absolute;
+  _animation_convert = AC_none;
+  _start_frame = 0.0;
+  _end_frame = 0.0;
+  _frame_inc = 0.0;
+  _input_frame_rate = 0.0;
+  _output_frame_rate = 0.0;
+  _control_flags = 0;
   _merge_externals = false;
   _egg_data = (EggData *)NULL;
   _owns_egg_data = false;

+ 51 - 4
pandatool/src/converter/somethingToEggConverter.h

@@ -19,10 +19,11 @@
 #ifndef SOMETHINGTOEGGCONVERTER_H
 #define SOMETHINGTOEGGCONVERTER_H
 
-#include <pandatoolbase.h>
+#include "pandatoolbase.h"
 
-#include <filename.h>
-#include <config_util.h>  // for get_texture_path() and get_model_path()
+#include "filename.h"
+#include "config_util.h"  // for get_texture_path() and get_model_path()
+#include "animationConvert.h"
 
 class EggData;
 class EggGroupNode;
@@ -56,7 +57,38 @@ public:
                                        const Filename &tpc_directory = Filename());
   INLINE void set_model_path_convert(PathConvert mpc,
                                      const Filename &mpc_directory = Filename());
-
+  // These methods dealing with animation and frame rate are only
+  // relevant to converter types that understand animation.
+  INLINE void set_animation_convert(AnimationConvert animation_convert);
+  INLINE AnimationConvert get_animation_convert() const;
+
+  INLINE void set_start_frame(double start_frame);
+  INLINE bool has_start_frame() const;
+  INLINE double get_start_frame() const;
+  INLINE void clear_start_frame();
+
+  INLINE void set_end_frame(double end_frame);
+  INLINE bool has_end_frame() const;
+  INLINE double get_end_frame() const;
+  INLINE void clear_end_frame();
+
+  INLINE void set_frame_inc(double frame_inc);
+  INLINE bool has_frame_inc() const;
+  INLINE double get_frame_inc() const;
+  INLINE void clear_frame_inc();
+
+  INLINE void set_input_frame_rate(double input_frame_rate);
+  INLINE bool has_input_frame_rate() const;
+  INLINE double get_input_frame_rate() const;
+  INLINE void clear_input_frame_rate();
+
+  INLINE void set_output_frame_rate(double output_frame_rate);
+  INLINE bool has_output_frame_rate() const;
+  INLINE double get_output_frame_rate() const;
+  INLINE void clear_output_frame_rate();
+
+  INLINE static double get_default_frame_rate();
+  
   INLINE void set_merge_externals(bool merge_externals);
   INLINE bool get_merge_externals() const;
 
@@ -99,6 +131,21 @@ protected:
   PathConvert _mpc;
   Filename _mpc_directory;
 
+  AnimationConvert _animation_convert;
+  double _start_frame;
+  double _end_frame;
+  double _frame_inc;
+  double _input_frame_rate;   // frames per second
+  double _output_frame_rate;  // frames per second
+  enum ControlFlags {
+    CF_start_frame        = 0x0001,
+    CF_end_frame          = 0x0002,
+    CF_frame_inc          = 0x0004,
+    CF_input_frame_rate   = 0x0008,
+    CF_output_frame_rate  = 0x0010,
+  };
+  int _control_flags;
+
   bool _merge_externals;
 
   EggData *_egg_data;

+ 72 - 0
pandatool/src/eggbase/somethingToEgg.cxx

@@ -58,6 +58,12 @@ SomethingToEgg(const string &format_name,
 
   _input_units = DU_invalid;
   _output_units = DU_invalid;
+  _animation_convert = AC_none;
+  _got_start_frame = false;
+  _got_end_frame = false;
+  _got_frame_inc = false;
+  _got_input_frame_rate = false;
+  _got_output_frame_rate = false;
   _texture_path_convert = SomethingToEggConverter::PC_unchanged;
   _model_path_convert = SomethingToEggConverter::PC_unchanged;
   _append_to_sys_paths = false;
@@ -90,6 +96,53 @@ add_units_options() {
      &SomethingToEgg::dispatch_units, NULL, &_output_units);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEgg::add_animation_options
+//       Access: Public
+//  Description: Adds options appropriate to animation packages.
+////////////////////////////////////////////////////////////////////
+void SomethingToEgg::
+add_animation_options() {
+  add_option
+    ("a", "animation-mode", 40,
+     "Specifies how animation from the " + _format_name + " file is "
+     "converted to egg, if at all.  At present, the following keywords "
+     "are supported: none and flip.",
+     &SomethingToEgg::dispatch_animation_convert, NULL, &_animation_convert);
+
+  add_option
+    ("sf", "start-frame", 40,
+     "Specifies the starting frame of animation to extract.  If omitted, "
+     "the first frame of the time slider will be used.",
+     &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame);
+
+  add_option
+    ("ef", "end-frame", 40,
+     "Specifies the ending frame of animation to extract.  If omitted, "
+     "the last frame of the time slider will be used.",
+     &SomethingToEgg::dispatch_double, &_got_end_frame, &_end_frame);
+
+  add_option
+    ("if", "frame-inc", 40,
+     "Specifies the increment between successive frames.  If omitted, "
+     "this is taken from the time slider settings, or 1.0 if the time "
+     "slider does not specify.",
+     &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc);
+
+  add_option
+    ("fri", "fps", 40,
+     "Specify the frame rate (frames per second) of the input " + _format_name +
+     " file.  Normally, this can be inferred from the file itself.",
+     &SomethingToEgg::dispatch_double, &_got_input_frame_rate, &_input_frame_rate);
+
+  add_option
+    ("fro", "fps", 40,
+     "Specify the frame rate (frames per second) of the generated animation.  "
+     "If this is specified, the animation speed is scaled by the appropriate "
+     "factor based on the frame rate of the input file (see -ri).",
+     &SomethingToEgg::dispatch_double, &_got_output_frame_rate, &_output_frame_rate);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SomethingToEgg::add_texture_path_options
 //       Access: Public
@@ -354,6 +407,25 @@ post_process_egg_file() {
   EggConverter::post_process_egg_file();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SomethingToEgg::dispatch_animation_convert
+//       Access: Protected, Static
+//  Description: Dispatch function to set the given animation convert mode
+//               according to the specified parameter.  var is a
+//               pointer to an AnimationConvert variable.
+////////////////////////////////////////////////////////////////////
+bool SomethingToEgg::
+dispatch_animation_convert(const string &opt, const string &arg, void *var) {
+  AnimationConvert *ip = (AnimationConvert *)var;
+  (*ip) = string_animation_convert(arg);
+  if ((*ip) == AC_invalid) {
+    nout << "Invalid keyword for -" << opt << ": " << arg << "\n";
+    return false;
+  }    
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SomethingToEgg::dispatch_path_convert_relative
 //       Access: Protected, Static

+ 14 - 0
pandatool/src/eggbase/somethingToEgg.h

@@ -41,6 +41,7 @@ public:
                  bool allow_stdout = true);
 
   void add_units_options();
+  void add_animation_options();
   void add_texture_path_options();
   void add_model_path_options();
   void add_rel_dir_options();
@@ -54,6 +55,7 @@ protected:
   virtual bool post_command_line();
   virtual void post_process_egg_file();
 
+  static bool dispatch_animation_convert(const string &opt, const string &arg, void *var);
   static bool dispatch_path_convert_relative(const string &opt, const string &arg, void *var);
   static bool dispatch_path_convert_absolute(const string &opt, const string &arg, void *var);
   static bool dispatch_path_convert_rel_abs(const string &opt, const string &arg, void *var);
@@ -66,6 +68,18 @@ protected:
   DistanceUnit _input_units;
   DistanceUnit _output_units;
 
+  AnimationConvert _animation_convert;
+  double _start_frame;
+  double _end_frame;
+  double _frame_inc;
+  double _input_frame_rate;
+  double _output_frame_rate;
+  bool _got_start_frame;
+  bool _got_end_frame;
+  bool _got_frame_inc;
+  bool _got_input_frame_rate;
+  bool _got_output_frame_rate;
+
   SomethingToEggConverter::PathConvert _texture_path_convert;
   SomethingToEggConverter::PathConvert _model_path_convert;
 

+ 1 - 1
pandatool/src/maya/mayaShaders.cxx

@@ -95,7 +95,7 @@ find_shader_for_node(MObject node) {
   }
 
   // Well, we didn't find a ShadingEngine after all.  Huh.
-  maya_cat.info()
+  maya_cat.debug()
     << node_fn.name() << " : no shading engine found.\n";
   return (MayaShader *)NULL;
 }

+ 131 - 33
pandatool/src/mayaegg/mayaToEggConverter.cxx

@@ -60,6 +60,8 @@
 #include <maya/MTransformationMatrix.h>
 #include <maya/MVector.h>
 #include <maya/MTesselationParams.h>
+#include <maya/MAnimControl.h>
+#include <maya/MGlobal.h>
 #include "post_maya_include.h"
 
 ////////////////////////////////////////////////////////////////////
@@ -138,8 +140,7 @@ get_extension() const {
 //
 //               This is designed to be as generic as possible,
 //               generally in support of run-time loading.
-//               Command-line converters may choose to use
-//               convert_maya() instead, as it provides more control.
+//               Also see convert_maya().
 ////////////////////////////////////////////////////////////////////
 bool MayaToEggConverter::
 convert_file(const Filename &filename) {
@@ -179,34 +180,50 @@ convert_maya() {
     _egg_data->set_coordinate_system(_maya->get_coordinate_system());
   }
 
-  MStatus status;
-
-  MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
-  if (!status) {
-    status.perror("MItDag constructor");
-    return false;
-  }
-
   mayaegg_cat.info()
     << "Converting from Maya.\n";
 
-  // This while loop walks through the entire Maya hierarchy, one node
-  // at a time.  Maya's MItDag object automatically performs a
-  // depth-first traversal of its scene graph.
+  // Figure out the animation parameters.
+  double start_frame, end_frame, frame_inc, input_frame_rate, output_frame_rate;
+  if (has_start_frame()) {
+    start_frame = get_start_frame();
+  } else {
+    start_frame = MAnimControl::minTime().value();
+  }
+  if (has_end_frame()) {
+    end_frame = get_end_frame();
+  } else {
+    end_frame = MAnimControl::maxTime().value();
+  }
+  if (has_frame_inc()) {
+    frame_inc = get_frame_inc();
+  } else {
+    frame_inc = 1.0;
+  }
+  if (has_input_frame_rate()) {
+    input_frame_rate = get_input_frame_rate();
+  } else {
+    MTime time(1.0, MTime::kSeconds);
+    input_frame_rate = time.as(MTime::uiUnit());
+  }
+  if (has_output_frame_rate()) {
+    output_frame_rate = get_output_frame_rate();
+  } else {
+    output_frame_rate = input_frame_rate;
+  }
+
   bool all_ok = true;
-  while (!dag_iterator.isDone()) {
-    MDagPath dag_path;
-    status = dag_iterator.getPath(dag_path);
-    if (!status) {
-      status.perror("MItDag::getPath");
-    } else {
-      if (!process_node(dag_path, get_egg_data())) {
-        all_ok = false;
-      }
-    }
 
-    dag_iterator.next();
-  }
+  switch (get_animation_convert()) {
+  case AC_none:
+    all_ok = convert_hierarchy(&get_egg_data());
+    break;
+
+  case AC_flip:
+    all_ok = convert_flip(start_frame, end_frame, frame_inc,
+                          output_frame_rate);
+    break;
+  };
 
   if (all_ok) {
     mayaegg_cat.info()
@@ -248,6 +265,87 @@ close_api() {
   _maya.clear();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEggConverter::convert_flip
+//       Access: Private
+//  Description: Converts the animation as a series of models that
+//               cycle (flip) from one to the next at the appropriate
+//               frame rate.  This is the most likely to convert
+//               precisely (since we ask Maya to tell us the vertex
+//               position each time) but it is the most wasteful in
+//               terms of memory utilization (since a complete of the
+//               model is stored for each frame).
+////////////////////////////////////////////////////////////////////
+bool MayaToEggConverter::
+convert_flip(double start_frame, double end_frame, double frame_inc,
+             double output_frame_rate) {
+  bool all_ok = true;
+
+  EggGroup *sequence_node = new EggGroup("model");
+  get_egg_data().add_child(sequence_node);
+  sequence_node->set_switch_flag(true);
+  sequence_node->set_switch_fps(output_frame_rate / frame_inc);
+
+  MTime frame(start_frame, MTime::uiUnit());
+  MTime frame_stop(end_frame, MTime::uiUnit());
+  while (frame <= frame_stop) {
+    nout << "frame " << frame.value() << "\n";
+    ostringstream name_strm;
+    name_strm << "frame" << frame.value();
+    EggGroup *frame_root = new EggGroup(name_strm.str());
+    sequence_node->add_child(frame_root);
+
+    MGlobal::viewFrame(frame);
+    if (!convert_hierarchy(frame_root)) {
+      all_ok = false;
+    }
+    _groups.clear();
+
+    frame += frame_inc;
+  }
+
+  return all_ok;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MayaToEggConverter::convert_hierarchy
+//       Access: Private
+//  Description: Walks the entire Maya hierarchy, converting it to a
+//               corresponding egg hierarchy under the indicated root
+//               node.
+////////////////////////////////////////////////////////////////////
+bool MayaToEggConverter::
+convert_hierarchy(EggGroupNode *egg_root) {
+  MStatus status;
+
+  MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status);
+  if (!status) {
+    status.perror("MItDag constructor");
+    return false;
+  }
+
+  // This while loop walks through the entire Maya hierarchy, one node
+  // at a time.  Maya's MItDag object automatically performs a
+  // depth-first traversal of its scene graph.
+
+  bool all_ok = true;
+  while (!dag_iterator.isDone()) {
+    MDagPath dag_path;
+    status = dag_iterator.getPath(dag_path);
+    if (!status) {
+      status.perror("MItDag::getPath");
+    } else {
+      if (!process_node(dag_path, egg_root)) {
+        all_ok = false;
+      }
+    }
+
+    dag_iterator.next();
+  }
+
+  return all_ok;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: MayaToEggConverter::process_node
 //       Access: Private
@@ -257,7 +355,7 @@ close_api() {
 //               successful, false if an error was encountered.
 ////////////////////////////////////////////////////////////////////
 bool MayaToEggConverter::
-process_node(const MDagPath &dag_path, EggData &data) {
+process_node(const MDagPath &dag_path, EggGroupNode *egg_root) {
   MStatus status;
   MFnDagNode dag_node(dag_path, &status);
   if (!status) {
@@ -285,7 +383,7 @@ process_node(const MDagPath &dag_path, EggData &data) {
 
   } else if (dag_path.hasFn(MFn::kNurbsSurface)) {
     EggGroup *egg_group =
-      get_egg_group(dag_path.fullPathName().asChar(), data);
+      get_egg_group(dag_path.fullPathName().asChar(), egg_root);
 
     if (egg_group == (EggGroup *)NULL) {
       mayaegg_cat.error()
@@ -307,7 +405,7 @@ process_node(const MDagPath &dag_path, EggData &data) {
 
   } else if (dag_path.hasFn(MFn::kNurbsCurve)) {
     EggGroup *egg_group =
-      get_egg_group(dag_path.fullPathName().asChar(), data);
+      get_egg_group(dag_path.fullPathName().asChar(), egg_root);
 
     if (egg_group == (EggGroup *)NULL) {
       nout << "Cannot determine group node.\n";
@@ -327,7 +425,7 @@ process_node(const MDagPath &dag_path, EggData &data) {
 
   } else if (dag_path.hasFn(MFn::kMesh)) {
     EggGroup *egg_group =
-      get_egg_group(dag_path.fullPathName().asChar(), data);
+      get_egg_group(dag_path.fullPathName().asChar(), egg_root);
 
     if (egg_group == (EggGroup *)NULL) {
       mayaegg_cat.error()
@@ -350,7 +448,7 @@ process_node(const MDagPath &dag_path, EggData &data) {
   } else {
     // Get the translation/rotation/scale data
     EggGroup *egg_group =
-      get_egg_group(dag_path.fullPathName().asChar(), data);
+      get_egg_group(dag_path.fullPathName().asChar(), egg_root);
 
     if (egg_group != (EggGroup *)NULL) {
       get_transform(dag_path, egg_group);
@@ -938,7 +1036,7 @@ make_polyset(const MDagPath &dag_path, const MFnMesh &mesh,
 //               Maya hierarchy sensibly.
 ////////////////////////////////////////////////////////////////////
 EggGroup *MayaToEggConverter::
-get_egg_group(const string &name, EggData &data) {
+get_egg_group(const string &name, EggGroupNode *egg_root) {
   // If we have already encountered this pathname, return the
   // corresponding EggGroup immediately.
   Groups::const_iterator gi = _groups.find(name);
@@ -967,13 +1065,13 @@ get_egg_group(const string &name, EggData &data) {
       local_name = name;
     }
 
-    EggGroup *parent_egg_group = get_egg_group(parent_name, data);
+    EggGroup *parent_egg_group = get_egg_group(parent_name, egg_root);
     egg_group = new EggGroup(local_name);
 
     if (parent_egg_group != (EggGroup *)NULL) {
       parent_egg_group->add_child(egg_group);
     } else {
-      data.add_child(egg_group);
+      egg_root->add_child(egg_group);
     }
   }
 

+ 5 - 2
pandatool/src/mayaegg/mayaToEggConverter.h

@@ -68,7 +68,10 @@ public:
   void close_api();
 
 private:
-  bool process_node(const MDagPath &dag_path, EggData &data);
+  bool convert_flip(double start_frame, double end_frame, double frame_inc,
+                    double output_frame_rate);
+  bool convert_hierarchy(EggGroupNode *egg_root);
+  bool process_node(const MDagPath &dag_path, EggGroupNode *egg_root);
   void get_transform(const MDagPath &dag_path, EggGroup *egg_group);
 
   // I ran into core dumps trying to pass around a MFnMesh object by
@@ -89,7 +92,7 @@ private:
                     EggGroup *egg_group,
                     MayaShader *default_shader = NULL);
 
-  EggGroup *get_egg_group(const string &name, EggData &data);
+  EggGroup *get_egg_group(const string &name, EggGroupNode *egg_root);
   void set_shader_attributes(EggPrimitive &primitive,
                              const MayaShader &shader);
 

+ 19 - 0
pandatool/src/mayaprogs/mayaToEgg.cxx

@@ -29,6 +29,7 @@ MayaToEgg::
 MayaToEgg() :
   SomethingToEgg("Maya", ".mb")
 {
+  add_animation_options();
   add_units_options();
   add_normals_options();
   add_transform_options();
@@ -97,6 +98,24 @@ run() {
   converter._polygon_tolerance = _polygon_tolerance;
   converter._ignore_transforms = _ignore_transforms;
 
+  // Copy in the animation parameters.
+  converter.set_animation_convert(_animation_convert);
+  if (_got_start_frame) {
+    converter.set_start_frame(_start_frame);
+  }
+  if (_got_end_frame) {
+    converter.set_end_frame(_end_frame);
+  }
+  if (_got_frame_inc) {
+    converter.set_frame_inc(_frame_inc);
+  }
+  if (_got_input_frame_rate) {
+    converter.set_input_frame_rate(_input_frame_rate);
+  }
+  if (_got_output_frame_rate) {
+    converter.set_output_frame_rate(_output_frame_rate);
+  }
+
   // Set the coordinate system to match Maya's.
   if (!_got_coordinate_system) {
     _coordinate_system = converter._maya->get_coordinate_system();