diff --git a/pandatool/src/converter/animationConvert.cxx b/pandatool/src/converter/animationConvert.cxx index 363f5410d0..fe08d684db 100644 --- a/pandatool/src/converter/animationConvert.cxx +++ b/pandatool/src/converter/animationConvert.cxx @@ -45,6 +45,9 @@ format_animation_convert(AnimationConvert convert) { case AC_chan: return "chan"; + + case AC_both: + return "both"; } nout << "**unexpected AnimationConvert value: (" << (int)convert << ")**"; return "**"; @@ -82,6 +85,9 @@ string_animation_convert(const string &str) { } else if (cmp_nocase(str, "chan") == 0) { return AC_chan; + } else if (cmp_nocase(str, "both") == 0) { + return AC_both; + } else { return AC_invalid; } diff --git a/pandatool/src/converter/animationConvert.h b/pandatool/src/converter/animationConvert.h index 52bf1b48c8..22bbce3379 100644 --- a/pandatool/src/converter/animationConvert.h +++ b/pandatool/src/converter/animationConvert.h @@ -34,6 +34,7 @@ enum AnimationConvert { AC_flip, // A flip (sequence) of static geometry models. AC_model, // A character model, with joints. AC_chan, // Animation tables for the above model. + AC_both, // A character model and tables in the same file. }; string format_animation_convert(AnimationConvert unit); diff --git a/pandatool/src/converter/somethingToEggConverter.I b/pandatool/src/converter/somethingToEggConverter.I index d3408c3071..df0fa25e98 100644 --- a/pandatool/src/converter/somethingToEggConverter.I +++ b/pandatool/src/converter/somethingToEggConverter.I @@ -274,6 +274,55 @@ clear_frame_inc() { _control_flags &= ~CF_frame_inc; } +//////////////////////////////////////////////////////////////////// +// Function: SomethingToEggConverter::set_neutral_frame +// Access: Public +// Description: Specifies the frame of animation to represent the +// neutral pose of the model. +//////////////////////////////////////////////////////////////////// +INLINE void SomethingToEggConverter:: +set_neutral_frame(double neutral_frame) { + _neutral_frame = neutral_frame; + _control_flags |= CF_neutral_frame; +} + +//////////////////////////////////////////////////////////////////// +// Function: SomethingToEggConverter::has_neutral_frame +// Access: Public +// Description: Returns true if the neutral frame has been +// explicitly specified via set_neutral_frame(), or +// false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool SomethingToEggConverter:: +has_neutral_frame() const { + return (_control_flags & CF_neutral_frame) != 0; +} + +//////////////////////////////////////////////////////////////////// +// Function: SomethingToEggConverter::get_neutral_frame +// Access: Public +// Description: Returns the value set by a previous call to +// set_neutral_frame(). It is an error to call this if +// has_neutral_frame() returns false. +//////////////////////////////////////////////////////////////////// +INLINE double SomethingToEggConverter:: +get_neutral_frame() const { + nassertr(has_neutral_frame(), 0.0); + return _neutral_frame; +} + +//////////////////////////////////////////////////////////////////// +// Function: SomethingToEggConverter::clear_neutral_frame +// Access: Public +// Description: Removes the value previously set by +// set_neutral_frame(). +//////////////////////////////////////////////////////////////////// +INLINE void SomethingToEggConverter:: +clear_neutral_frame() { + _neutral_frame = 0.0; + _control_flags &= ~CF_neutral_frame; +} + //////////////////////////////////////////////////////////////////// // Function: SomethingToEggConverter::set_input_frame_rate // Access: Public diff --git a/pandatool/src/converter/somethingToEggConverter.cxx b/pandatool/src/converter/somethingToEggConverter.cxx index 4697cde571..45f7600b1a 100644 --- a/pandatool/src/converter/somethingToEggConverter.cxx +++ b/pandatool/src/converter/somethingToEggConverter.cxx @@ -35,6 +35,7 @@ SomethingToEggConverter() { _start_frame = 0.0; _end_frame = 0.0; _frame_inc = 0.0; + _neutral_frame = 0.0; _input_frame_rate = 0.0; _output_frame_rate = 0.0; _control_flags = 0; diff --git a/pandatool/src/converter/somethingToEggConverter.h b/pandatool/src/converter/somethingToEggConverter.h index 5a6cfe7d23..061425d476 100644 --- a/pandatool/src/converter/somethingToEggConverter.h +++ b/pandatool/src/converter/somethingToEggConverter.h @@ -80,6 +80,11 @@ public: INLINE double get_frame_inc() const; INLINE void clear_frame_inc(); + INLINE void set_neutral_frame(double neutral_frame); + INLINE bool has_neutral_frame() const; + INLINE double get_neutral_frame() const; + INLINE void clear_neutral_frame(); + INLINE void set_input_frame_rate(double input_frame_rate); INLINE bool has_input_frame_rate() const; INLINE double get_input_frame_rate() const; @@ -139,14 +144,16 @@ protected: double _start_frame; double _end_frame; double _frame_inc; + double _neutral_frame; 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, + CF_neutral_frame = 0x0008, + CF_input_frame_rate = 0x0010, + CF_output_frame_rate = 0x0020, }; int _control_flags; diff --git a/pandatool/src/eggbase/somethingToEgg.cxx b/pandatool/src/eggbase/somethingToEgg.cxx index 76ba8fdd7f..6e81de47a8 100644 --- a/pandatool/src/eggbase/somethingToEgg.cxx +++ b/pandatool/src/eggbase/somethingToEgg.cxx @@ -62,6 +62,7 @@ SomethingToEgg(const string &format_name, _got_start_frame = false; _got_end_frame = false; _got_frame_inc = false; + _got_neutral_frame = false; _got_input_frame_rate = false; _got_output_frame_rate = false; _texture_path_convert = SomethingToEggConverter::PC_unchanged; @@ -107,7 +108,8 @@ add_animation_options() { ("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, pose, or flip.", + "are supported: none, pose, flip, model, chan, or both. The default " + "is none, which means not to convert animation.", &SomethingToEgg::dispatch_animation_convert, NULL, &_animation_convert); add_option @@ -120,7 +122,8 @@ add_animation_options() { 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.", + "the first frame of the time slider will be used. For -a pose, this " + "is the one frame of animation to extract.", &SomethingToEgg::dispatch_double, &_got_start_frame, &_start_frame); add_option @@ -136,6 +139,14 @@ add_animation_options() { "slider does not specify.", &SomethingToEgg::dispatch_double, &_got_frame_inc, &_frame_inc); + add_option + ("nf", "neutral-frame", 40, + "Specifies the frame number to use for the neutral pose. The model " + "will be set to this frame before extracting out the neutral character. " + "If omitted, the current frame of the model is used. This is only " + "relevant for -a model or -a both.", + &SomethingToEgg::dispatch_double, &_got_neutral_frame, &_neutral_frame); + add_option ("fri", "fps", 40, "Specify the frame rate (frames per second) of the input " + _format_name + diff --git a/pandatool/src/eggbase/somethingToEgg.h b/pandatool/src/eggbase/somethingToEgg.h index 47f058de08..5908fc0fdd 100644 --- a/pandatool/src/eggbase/somethingToEgg.h +++ b/pandatool/src/eggbase/somethingToEgg.h @@ -73,11 +73,13 @@ protected: double _start_frame; double _end_frame; double _frame_inc; + double _neutral_frame; double _input_frame_rate; double _output_frame_rate; bool _got_start_frame; bool _got_end_frame; bool _got_frame_inc; + bool _got_neutral_frame; bool _got_input_frame_rate; bool _got_output_frame_rate; diff --git a/pandatool/src/mayaegg/mayaToEggConverter.cxx b/pandatool/src/mayaegg/mayaToEggConverter.cxx index 1eeca253e2..f1509d3c1a 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.cxx +++ b/pandatool/src/mayaegg/mayaToEggConverter.cxx @@ -23,6 +23,7 @@ #include "eggData.h" #include "eggGroup.h" +#include "eggTable.h" #include "eggVertex.h" #include "eggVertexPool.h" #include "eggNurbsSurface.h" @@ -31,6 +32,7 @@ #include "eggPrimitive.h" #include "eggTexture.h" #include "eggTextureCollection.h" +#include "eggXfmSAnim.h" #include "string_utils.h" #include "pre_maya_include.h" @@ -180,6 +182,7 @@ convert_maya() { _textures.clear(); _shaders.clear(); _groups.clear(); + _tables.clear(); if (!open_api()) { mayaegg_cat.error() @@ -228,7 +231,8 @@ convert_maya() { switch (get_animation_convert()) { case AC_pose: // pose: set to a specific frame, then get out the static geometry. - nout << "frame " << start_frame << "\n"; + mayaegg_cat.info(false) + << "frame " << start_frame << "\n"; MGlobal::viewFrame(MTime(start_frame, MTime::uiUnit())); // fall through @@ -237,17 +241,36 @@ convert_maya() { all_ok = convert_hierarchy(&get_egg_data()); break; + case AC_flip: + // flip: get out a series of static models, one per frame, under a + // sequence node. + all_ok = convert_flip(start_frame, end_frame, frame_inc, + output_frame_rate); + break; + case AC_model: // model: get out an animatable model with joints and vertex // membership. all_ok = convert_char_model(); break; - case AC_flip: - // flip: get out a series of static models, one per frame, under a - // sequence node. - all_ok = convert_flip(start_frame, end_frame, frame_inc, - output_frame_rate); + case AC_chan: + // chan: get out a series of animation tables. + all_ok = convert_char_chan(start_frame, end_frame, frame_inc, + output_frame_rate); + break; + + case AC_both: + // both: Put a model and its animation into the same egg file. + _animation_convert = AC_model; + if (!convert_char_model()) { + all_ok = false; + } + _animation_convert = AC_chan; + if (!convert_char_chan(start_frame, end_frame, frame_inc, + output_frame_rate)) { + all_ok = false; + } break; }; @@ -291,21 +314,6 @@ close_api() { _maya.clear(); } -//////////////////////////////////////////////////////////////////// -// Function: MayaToEggConverter::convert_char_model -// Access: Private -// Description: Converts the animation as an animatable character -// model, with joints and vertex membership. -//////////////////////////////////////////////////////////////////// -bool MayaToEggConverter:: -convert_char_model() { - EggGroup *char_node = new EggGroup(_character_name); - get_egg_data().add_child(char_node); - char_node->set_dart_type(EggGroup::DT_default); - - return convert_hierarchy(char_node); -} - //////////////////////////////////////////////////////////////////// // Function: MayaToEggConverter::convert_flip // Access: Private @@ -330,7 +338,8 @@ convert_flip(double start_frame, double end_frame, double frame_inc, MTime frame(start_frame, MTime::uiUnit()); MTime frame_stop(end_frame, MTime::uiUnit()); while (frame <= frame_stop) { - nout << "frame " << frame.value() << "\n"; + mayaegg_cat.info(false) + << "frame " << frame.value() << "\n"; ostringstream name_strm; name_strm << "frame" << frame.value(); EggGroup *frame_root = new EggGroup(name_strm.str()); @@ -348,6 +357,123 @@ convert_flip(double start_frame, double end_frame, double frame_inc, return all_ok; } +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::convert_char_model +// Access: Private +// Description: Converts the file as an animatable character +// model, with joints and vertex membership. +//////////////////////////////////////////////////////////////////// +bool MayaToEggConverter:: +convert_char_model() { + if (has_neutral_frame()) { + MTime frame(get_neutral_frame(), MTime::uiUnit()); + mayaegg_cat.info(false) + << "neutral frame " << frame.value() << "\n"; + MGlobal::viewFrame(frame); + } + + EggGroup *char_node = new EggGroup(_character_name); + get_egg_data().add_child(char_node); + char_node->set_dart_type(EggGroup::DT_default); + + return convert_hierarchy(char_node); +} + +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::convert_char_chan +// Access: Private +// Description: Converts the animation as a series of tables to apply +// to the character model, as retrieved earlier via +// AC_model. +//////////////////////////////////////////////////////////////////// +bool MayaToEggConverter:: +convert_char_chan(double start_frame, double end_frame, double frame_inc, + double output_frame_rate) { + MStatus status; + + EggTable *root_table_node = new EggTable(); + get_egg_data().add_child(root_table_node); + EggTable *bundle_node = new EggTable(_character_name); + bundle_node->set_table_type(EggTable::TT_bundle); + root_table_node->add_child(bundle_node); + EggTable *skeleton_node = new EggTable(""); + bundle_node->add_child(skeleton_node); + + // First, walk through the scene graph and build up the table of + // joints. + MItDag dag_iterator(MItDag::kDepthFirst, MFn::kTransform, &status); + if (!status) { + status.perror("MItDag constructor"); + return false; + } + 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_chan_node(dag_path, skeleton_node)) { + all_ok = false; + } + } + + dag_iterator.next(); + } + + // Now walk through the joints in that table and make sure they're + // all set to use the correct frame frame. + double fps = output_frame_rate / frame_inc; + Tables::iterator ti; + for (ti = _tables.begin(); ti != _tables.end(); ++ti) { + JointAnim *joint_anim = (*ti).second; + nassertr(joint_anim != (JointAnim *)NULL && + joint_anim->_anim != (EggXfmSAnim *)NULL, false); + joint_anim->_anim->set_fps(fps); + } + + // Now we can get the animation data by walking through all of the + // frames, one at a time, and getting the joint angles at each + // frame. + + // This is just a temporary EggGroup to receive the transform for + // each joint each frame. + PT(EggGroup) tgroup = new EggGroup; + + MTime frame(start_frame, MTime::uiUnit()); + MTime frame_stop(end_frame, MTime::uiUnit()); + while (frame <= frame_stop) { + if (mayaegg_cat.is_debug()) { + mayaegg_cat.debug(false) + << "frame " << frame.value() << "\n"; + } else { + mayaegg_cat.info(false) + << "."; + } + MGlobal::viewFrame(frame); + + for (ti = _tables.begin(); ti != _tables.end(); ++ti) { + JointAnim *joint_anim = (*ti).second; + get_transform(joint_anim->_dag_path, tgroup); + joint_anim->_anim->add_data(tgroup->get_transform()); + } + + frame += frame_inc; + } + mayaegg_cat.info(false) + << "\n"; + + // Finally, clean up by deleting all of the JointAnim structures we + // created. + for (ti = _tables.begin(); ti != _tables.end(); ++ti) { + JointAnim *joint_anim = (*ti).second; + delete joint_anim; + } + _tables.clear(); + + return all_ok; +} + //////////////////////////////////////////////////////////////////// // Function: MayaToEggConverter::convert_hierarchy // Access: Private @@ -376,7 +502,7 @@ convert_hierarchy(EggGroupNode *egg_root) { if (!status) { status.perror("MItDag::getPath"); } else { - if (!process_node(dag_path, egg_root)) { + if (!process_model_node(dag_path, egg_root)) { all_ok = false; } } @@ -388,7 +514,7 @@ convert_hierarchy(EggGroupNode *egg_root) { } //////////////////////////////////////////////////////////////////// -// Function: MayaToEggConverter::process_node +// Function: MayaToEggConverter::process_model_node // Access: Private // Description: Converts the indicated Maya node (given a MDagPath, // similar in concept to Panda's NodePath) to the @@ -396,7 +522,7 @@ convert_hierarchy(EggGroupNode *egg_root) { // successful, false if an error was encountered. //////////////////////////////////////////////////////////////////// bool MayaToEggConverter:: -process_node(const MDagPath &dag_path, EggGroupNode *egg_root) { +process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root) { MStatus status; MFnDagNode dag_node(dag_path, &status); if (!status) { @@ -451,7 +577,9 @@ process_node(const MDagPath &dag_path, EggGroupNode *egg_root) { return false; } else { - get_transform(dag_path, egg_group); + if (_animation_convert != AC_model) { + get_transform(dag_path, egg_group); + } MFnNurbsSurface surface(dag_path, &status); if (!status) { @@ -471,7 +599,8 @@ process_node(const MDagPath &dag_path, EggGroupNode *egg_root) { EggGroup *egg_group = get_egg_group(dag_path, egg_root); if (egg_group == (EggGroup *)NULL) { - nout << "Cannot determine group node.\n"; + mayaegg_cat.error() + << "Cannot determine group node.\n"; } else { get_transform(dag_path, egg_group); @@ -496,7 +625,9 @@ process_node(const MDagPath &dag_path, EggGroupNode *egg_root) { return false; } else { - get_transform(dag_path, egg_group); + if (_animation_convert != AC_model) { + get_transform(dag_path, egg_group); + } MFnMesh mesh(dag_path, &status); if (!status) { @@ -513,13 +644,53 @@ process_node(const MDagPath &dag_path, EggGroupNode *egg_root) { EggGroup *egg_group = get_egg_group(dag_path, egg_root); if (egg_group != (EggGroup *)NULL) { - get_transform(dag_path, egg_group); + if (_animation_convert != AC_model) { + get_transform(dag_path, egg_group); + } } } return true; } +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::process_chan_node +// Access: Private +// Description: Similar to process_model_node(), but this code path +// is followed only when we are building a table of +// animation data (AC_chan). It just builds up the +// EggTable hierarchy according to the joint table. +//////////////////////////////////////////////////////////////////// +bool MayaToEggConverter:: +process_chan_node(const MDagPath &dag_path, EggGroupNode *egg_root) { + MStatus status; + MFnDagNode dag_node(dag_path, &status); + if (!status) { + status.perror("MFnDagNode constructor"); + return false; + } + + if (dag_path.hasFn(MFn::kJoint)) { + // A joint. + + if (mayaegg_cat.is_debug()) { + mayaegg_cat.debug() + << dag_path.fullPathName() << ": " << dag_node.typeName(); + + if (MAnimUtil::isAnimated(dag_path)) { + mayaegg_cat.debug(false) + << " (animated)"; + } + + mayaegg_cat.debug(false) << "\n"; + } + + get_egg_table(dag_path, egg_root); + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: MayaToEggConverter::get_transform // Access: Private @@ -762,7 +933,8 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface, if (segment.hasFn(MFn::kNurbsCurve)) { MFnNurbsCurve curve(segment, &status); if (!status) { - nout << "Trim curve appears to be a nurbs curve, but isn't.\n"; + mayaegg_cat.error() + << "Trim curve appears to be a nurbs curve, but isn't.\n"; } else { // Finally, we have a valid curve! EggNurbsCurve *egg_curve = @@ -773,7 +945,8 @@ make_nurbs_surface(const MDagPath &dag_path, MFnNurbsSurface &surface, } } } else { - nout << "Trim curve segment is not a nurbs curve.\n"; + mayaegg_cat.error() + << "Trim curve segment is not a nurbs curve.\n"; } } } @@ -1199,7 +1372,7 @@ get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh, status.perror("MFnSkinCluster::getWeights"); } else { if (influence_count != influence_objects.length()) { - maya_cat.error() + mayaegg_cat.error() << "MFnSkinCluster::influenceObjects() returns " << influence_objects.length() << " objects, but MFnSkinCluster::getWeights() reports " @@ -1289,6 +1462,74 @@ get_egg_group(const string &name, EggGroupNode *egg_root) { return egg_group; } +//////////////////////////////////////////////////////////////////// +// Function: MayaToEggConverter::get_egg_table +// Access: Private +// Description: Returns the EggTable corresponding to the indicated +// fully-qualified Maya path name. This is similar to +// get_egg_group(), but this variant is used only when +// we are building a channel file, which is just a +// hierarchical collection of animation tables. +//////////////////////////////////////////////////////////////////// +MayaToEggConverter::JointAnim *MayaToEggConverter:: +get_egg_table(const MDagPath &dag_path, EggGroupNode *egg_root) { + string name = dag_path.fullPathName().asChar(); + + // If we have already encountered this pathname, return the + // corresponding EggTable immediately. + Tables::const_iterator ti = _tables.find(name); + if (ti != _tables.end()) { + return (*ti).second; + } + + // Otherwise, we have to create it. + JointAnim *joint_anim; + + if (name.empty()) { + // This is the top. + joint_anim = (JointAnim *)NULL; + + } else { + // Maya uses vertical bars to separate path components. Remove + // everything from the rightmost bar on; this will give us the + // parent's path name. + size_t bar = name.rfind("|"); + string parent_name, local_name; + if (bar != string::npos) { + parent_name = name.substr(0, bar); + local_name = name.substr(bar + 1); + } else { + local_name = name; + } + + // Look only one level up for the parent. If it hasn't been + // defined yet, don't define it; instead, just start from the + // root. + JointAnim *parent_joint_anim = NULL; + if (!parent_name.empty()) { + ti = _tables.find(parent_name); + if (ti != _tables.end()) { + parent_joint_anim = (*ti).second; + } + } + + joint_anim = new JointAnim; + joint_anim->_dag_path = dag_path; + joint_anim->_table = new EggTable(local_name); + joint_anim->_anim = new EggXfmSAnim("xform", _egg_data->get_coordinate_system()); + joint_anim->_table->add_child(joint_anim->_anim); + + if (parent_joint_anim != (JointAnim *)NULL) { + parent_joint_anim->_table->add_child(joint_anim->_table); + } else { + egg_root->add_child(joint_anim->_table); + } + } + + _tables.insert(Tables::value_type(name, joint_anim)); + return joint_anim; +} + //////////////////////////////////////////////////////////////////// // Function: MayaShader::set_shader_attributes // Access: Public diff --git a/pandatool/src/mayaegg/mayaToEggConverter.h b/pandatool/src/mayaegg/mayaToEggConverter.h index bb776b5608..9adee93c7d 100644 --- a/pandatool/src/mayaegg/mayaToEggConverter.h +++ b/pandatool/src/mayaegg/mayaToEggConverter.h @@ -28,11 +28,17 @@ #include "distanceUnit.h" #include "coordinateSystem.h" +#include "pre_maya_include.h" +#include +#include "post_maya_include.h" + class EggData; class EggGroup; +class EggTable; class EggVertexPool; class EggNurbsCurve; class EggPrimitive; +class EggXfmSAnim; class MDagPath; class MFnNurbsSurface; @@ -69,11 +75,14 @@ public: void close_api(); private: + bool convert_flip(double start_frame, double end_frame, + double frame_inc, double output_frame_rate); bool convert_char_model(); - bool convert_flip(double start_frame, double end_frame, double frame_inc, - double output_frame_rate); + bool convert_char_chan(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); + bool process_model_node(const MDagPath &dag_path, EggGroupNode *egg_root); + bool process_chan_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 @@ -96,15 +105,26 @@ private: bool get_vertex_weights(const MDagPath &dag_path, const MFnMesh &mesh, EggGroupNode *egg_root, pvector &joints, MFloatArray &weights); + class JointAnim { + public: + MDagPath _dag_path; + EggTable *_table; + EggXfmSAnim *_anim; + }; EggGroup *get_egg_group(const MDagPath &dag_path, EggGroupNode *egg_root); EggGroup *get_egg_group(const string &name, EggGroupNode *egg_root); + JointAnim *get_egg_table(const MDagPath &dag_path, EggGroupNode *egg_root); + JointAnim *get_egg_table(const string &name, EggGroupNode *egg_root); void set_shader_attributes(EggPrimitive &primitive, const MayaShader &shader); typedef pmap Groups; Groups _groups; + typedef pmap Tables; + Tables _tables; + string _program_name; public: diff --git a/pandatool/src/mayaprogs/mayaToEgg.cxx b/pandatool/src/mayaprogs/mayaToEgg.cxx index 6a2ba455cf..69756ccb3f 100644 --- a/pandatool/src/mayaprogs/mayaToEgg.cxx +++ b/pandatool/src/mayaprogs/mayaToEgg.cxx @@ -110,6 +110,9 @@ run() { if (_got_frame_inc) { converter.set_frame_inc(_frame_inc); } + if (_got_neutral_frame) { + converter.set_neutral_frame(_neutral_frame); + } if (_got_input_frame_rate) { converter.set_input_frame_rate(_input_frame_rate); }