Browse Source

egg-optchar -defpose

David Rose 17 years ago
parent
commit
31d75582a3
37 changed files with 1567 additions and 1249 deletions
  1. 4 4
      panda/src/chan/config_chan.cxx
  2. 9 9
      panda/src/chan/movingPart.I
  3. 5 5
      panda/src/chan/movingPart.h
  4. 1 1
      panda/src/chan/movingPartBase.cxx
  5. 1 1
      panda/src/chan/movingPartBase.h
  6. 2 2
      panda/src/chan/movingPartMatrix.I
  7. 8 8
      panda/src/chan/movingPartMatrix.cxx
  8. 2 3
      panda/src/chan/movingPartMatrix.h
  9. 2 2
      panda/src/chan/movingPartScalar.I
  10. 2 2
      panda/src/chan/movingPartScalar.cxx
  11. 1 1
      panda/src/chan/movingPartScalar.h
  12. 4 2
      panda/src/chan/partBundle.cxx
  13. 2 2
      panda/src/char/characterJoint.cxx
  14. 1 1
      panda/src/char/characterJoint.h
  15. 2 0
      panda/src/char/jointVertexTransform.cxx
  16. 23 2
      panda/src/doc/eggSyntax.txt
  17. 55 0
      panda/src/egg/eggGroup.I
  18. 12 2
      panda/src/egg/eggGroup.cxx
  19. 11 0
      panda/src/egg/eggGroup.h
  20. 1 1
      panda/src/egg/eggTexture.cxx
  21. 2 2
      panda/src/egg/eggTransform.cxx
  22. 3 1
      panda/src/egg/eggTransform.h
  23. 388 388
      panda/src/egg/lexer.cxx.prebuilt
  24. 2 10
      panda/src/egg/lexer.lxx
  25. 739 720
      panda/src/egg/parser.cxx.prebuilt
  26. 61 63
      panda/src/egg/parser.h.prebuilt
  27. 41 15
      panda/src/egg/parser.yxx
  28. 19 2
      panda/src/egg2pg/characterMaker.cxx
  29. 1 0
      panda/src/gobj/transformBlend.cxx
  30. 94 0
      pandatool/src/egg-optchar/eggOptchar.cxx
  31. 3 0
      pandatool/src/egg-optchar/eggOptchar.h
  32. 31 0
      pandatool/src/eggcharbase/eggJointData.cxx
  33. 1 0
      pandatool/src/eggcharbase/eggJointData.h
  34. 21 0
      pandatool/src/eggcharbase/eggJointNodePointer.cxx
  35. 1 0
      pandatool/src/eggcharbase/eggJointNodePointer.h
  36. 11 0
      pandatool/src/eggcharbase/eggJointPointer.cxx
  37. 1 0
      pandatool/src/eggcharbase/eggJointPointer.h

+ 4 - 4
panda/src/chan/config_chan.cxx

@@ -90,10 +90,10 @@ PRC_DESC("Set this true to interpolate character animations between frames, "
 
 ConfigVariableBool restore_initial_pose
 ("restore-initial-pose", true,
-PRC_DESC("When this is true, stopping all animations on an Actor causes it "
-         "to return to its initial, unanimated pose.  When false, it retains "
-         "whatever its last-computed pose was (which may or may not be "
-         "the unanimated pose)."));
+PRC_DESC("When this is true, setting all control effects on an Actor to 0 "
+         "causes it to return to its default, unanimated pose.  When "
+         "false, it retains whatever its last-computed pose was "
+         "(which may or may not be the default pose)."));
 
 
 ConfigureFn(config_chan) {

+ 9 - 9
panda/src/chan/movingPart.I

@@ -38,7 +38,7 @@ INLINE MovingPart<SwitchType>::
 MovingPart(const MovingPart<SwitchType> &copy) :
   MovingPartBase(copy),
   _value(copy._value),
-  _initial_value(copy._initial_value)
+  _default_value(copy._default_value)
 {
 }
 
@@ -50,10 +50,10 @@ MovingPart(const MovingPart<SwitchType> &copy) :
 template<class SwitchType>
 INLINE MovingPart<SwitchType>::
 MovingPart(PartGroup *parent, const string &name,
-           const ValueType &initial_value) :
+           const ValueType &default_value) :
   MovingPartBase(parent, name),
-  _value(initial_value),
-  _initial_value(initial_value)
+  _value(default_value),
+  _default_value(default_value)
 {
 }
 
@@ -84,7 +84,7 @@ get_value_type() const {
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MovingPart::make_initial_channel
+//     Function: MovingPart::make_default_channel
 //       Access: Public, Virtual
 //  Description: Creates and returns a new AnimChannel that is not
 //               part of any hierarchy, but that returns the default
@@ -92,8 +92,8 @@ get_value_type() const {
 ////////////////////////////////////////////////////////////////////
 template<class SwitchType>
 AnimChannelBase *MovingPart<SwitchType>::
-make_initial_channel() const {
-  return new AnimChannelFixed<SwitchType>(get_name(), _initial_value);
+make_default_channel() const {
+  return new AnimChannelFixed<SwitchType>(get_name(), _default_value);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -119,7 +119,7 @@ void MovingPart<SwitchType>::
 write_datagram(BamWriter *manager, Datagram &me) {
   MovingPartBase::write_datagram(manager, me);
   SwitchType::write_datagram(me, _value);
-  SwitchType::write_datagram(me, _initial_value);
+  SwitchType::write_datagram(me, _default_value);
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -135,7 +135,7 @@ void MovingPart<SwitchType>::
 fillin(DatagramIterator &scan, BamReader *manager) {
   MovingPartBase::fillin(scan, manager);
   SwitchType::read_datagram(scan, _value);
-  SwitchType::read_datagram(scan, _initial_value);
+  SwitchType::read_datagram(scan, _default_value);
 }
 
 

+ 5 - 5
panda/src/chan/movingPart.h

@@ -37,14 +37,14 @@ protected:
 
 public:
   INLINE MovingPart(PartGroup *parent, const string &name,
-                    const ValueType &_initial_value);
+                    const ValueType &default_value);
 
   virtual TypeHandle get_value_type() const;
-  virtual AnimChannelBase *make_initial_channel() const;
+  virtual AnimChannelBase *make_default_channel() const;
   virtual void output_value(ostream &out) const;
 
   ValueType _value;
-  ValueType _initial_value;
+  ValueType _default_value;
 
 public:
   INLINE virtual void write_datagram(BamWriter* manager, Datagram &me);
@@ -65,8 +65,8 @@ PUBLISHED:
   INLINE ValueType get_value() const {
     return _value;
   }
-  INLINE ValueType get_initial_value() const {
-    return _initial_value;
+  INLINE ValueType get_default_value() const {
+    return _default_value;
   }
 public:
   static void init_type() {

+ 1 - 1
panda/src/chan/movingPartBase.cxx

@@ -282,7 +282,7 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index,
       // If we're binding to the NULL anim, it means actually to create
       // a default AnimChannel that just returns the part's initial
       // value.
-      _channels[channel_index] = make_initial_channel();
+      _channels[channel_index] = make_default_channel();
     } else {
       _channels[channel_index] = DCAST(AnimChannelBase, anim);
     }

+ 1 - 1
panda/src/chan/movingPartBase.h

@@ -44,7 +44,7 @@ PUBLISHED:
 
 public:
   virtual TypeHandle get_value_type() const=0;
-  virtual AnimChannelBase *make_initial_channel() const=0;
+  virtual AnimChannelBase *make_default_channel() const=0;
 
 PUBLISHED:
   virtual bool clear_forced_channel();

+ 2 - 2
panda/src/chan/movingPartMatrix.I

@@ -32,8 +32,8 @@ MovingPartMatrix(const MovingPartMatrix &copy) :
 ////////////////////////////////////////////////////////////////////
 INLINE MovingPartMatrix::
 MovingPartMatrix(PartGroup *parent, const string &name,
-                 const LMatrix4f &initial_value)
-  : MovingPart<ACMatrixSwitchType>(parent, name, initial_value) {
+                 const LMatrix4f &default_value)
+  : MovingPart<ACMatrixSwitchType>(parent, name, default_value) {
 }
 
 ////////////////////////////////////////////////////////////////////

+ 8 - 8
panda/src/chan/movingPartMatrix.cxx

@@ -40,16 +40,16 @@ MovingPartMatrix::
 
 
 ////////////////////////////////////////////////////////////////////
-//     Function: MovingPartMatrix::make_initial_channel
+//     Function: MovingPartMatrix::make_default_channel
 //       Access: Public, Virtual
 //  Description: Creates and returns a new AnimChannel that is not
 //               part of any hierarchy, but that returns the default
 //               value associated with this part.
 ////////////////////////////////////////////////////////////////////
 AnimChannelBase *MovingPartMatrix::
-make_initial_channel() const {
+make_default_channel() const {
   LVecBase3f pos, hpr, scale, shear;
-  decompose_matrix(_initial_value, pos, hpr, scale, shear);
+  decompose_matrix(_default_value, pos, hpr, scale, shear);
   return new AnimChannelMatrixFixed(get_name(), pos, hpr, scale);
 }
 
@@ -76,7 +76,7 @@ get_blend_value(const PartBundle *root) {
   if (cdata->_blend.empty()) {
     // No channel is bound; supply the default value.
     if (restore_initial_pose) {
-      _value = _initial_value;
+      _value = _default_value;
     }
 
   } else if (_effective_control != (AnimControl *)NULL && 
@@ -126,7 +126,7 @@ get_blend_value(const PartBundle *root) {
         
         if (net_effect == 0.0f) {
           if (restore_initial_pose) {
-            _value = _initial_value;
+            _value = _default_value;
           }
         } else {
           _value = net_value / net_effect;
@@ -194,7 +194,7 @@ get_blend_value(const PartBundle *root) {
         
         if (net_effect == 0.0f) {
           if (restore_initial_pose) {
-            _value = _initial_value;
+            _value = _default_value;
           }
 
         } else {
@@ -273,7 +273,7 @@ get_blend_value(const PartBundle *root) {
         
         if (net_effect == 0.0f) {
           if (restore_initial_pose) {
-            _value = _initial_value;
+            _value = _default_value;
           }
 
         } else {
@@ -352,7 +352,7 @@ get_blend_value(const PartBundle *root) {
         
         if (net_effect == 0.0f) {
           if (restore_initial_pose) {
-            _value = _initial_value;
+            _value = _default_value;
           }
 
         } else {

+ 2 - 3
panda/src/chan/movingPartMatrix.h

@@ -35,11 +35,10 @@ protected:
 
 public:
   INLINE MovingPartMatrix(PartGroup *parent, const string &name,
-                          const LMatrix4f &initial_value =
-                          LMatrix4f::ident_mat());
+                          const LMatrix4f &default_value);
   virtual ~MovingPartMatrix();
 
-  virtual AnimChannelBase *make_initial_channel() const;
+  virtual AnimChannelBase *make_default_channel() const;
   virtual void get_blend_value(const PartBundle *root);
 
   virtual bool apply_freeze_matrix(const LVecBase3f &pos, const LVecBase3f &hpr, const LVecBase3f &scale);

+ 2 - 2
panda/src/chan/movingPartScalar.I

@@ -32,8 +32,8 @@ MovingPartScalar(const MovingPartScalar &copy) :
 ////////////////////////////////////////////////////////////////////
 INLINE MovingPartScalar::
 MovingPartScalar(PartGroup *parent, const string &name,
-                 const float &initial_value)
-  : MovingPart<ACScalarSwitchType>(parent, name, initial_value) {
+                 const float &default_value)
+  : MovingPart<ACScalarSwitchType>(parent, name, default_value) {
 }
 
 ////////////////////////////////////////////////////////////////////

+ 2 - 2
panda/src/chan/movingPartScalar.cxx

@@ -59,7 +59,7 @@ get_blend_value(const PartBundle *root) {
   if (cdata->_blend.empty()) {
     // No channel is bound; supply the default value.
     if (restore_initial_pose) {
-      _value = _initial_value;
+      _value = _default_value;
     }
 
   } else if (_effective_control != (AnimControl *)NULL &&
@@ -105,7 +105,7 @@ get_blend_value(const PartBundle *root) {
 
     if (net == 0.0f) {
       if (restore_initial_pose) {
-        _value = _initial_value;
+        _value = _default_value;
       }
 
     } else {

+ 1 - 1
panda/src/chan/movingPartScalar.h

@@ -34,7 +34,7 @@ protected:
 
 public:
   INLINE MovingPartScalar(PartGroup *parent, const string &name,
-                          const float &initial_value = 0);
+                          const float &default_value = 0);
   virtual ~MovingPartScalar();
 
   virtual void get_blend_value(const PartBundle *root);

+ 4 - 2
panda/src/chan/partBundle.cxx

@@ -198,8 +198,8 @@ apply_transform(const TransformState *transform) {
 //  Description: Sets the control effect of all AnimControls to zero
 //               (but does not "stop" the AnimControls).  The
 //               character will no longer be affected by any
-//               animation, and will return to its original Jesus
-//               pose.
+//               animation, and will return to its default
+//               pose (unless restore-initial-pose is false).
 //
 //               The AnimControls which are no longer associated will
 //               not be using any CPU cycles, but they may still be in
@@ -217,6 +217,7 @@ clear_control_effects() {
     cdataw->_blend.clear();
     cdataw->_net_blend = 0.0f;
     cdataw->_anim_changed = true;
+    determine_effective_channels(cdata);
   }
 }
 
@@ -806,6 +807,7 @@ clear_and_stop_intersecting(AnimControl *control, CData *cdata) {
     cdata->_net_blend = new_net_blend;
     cdata->_blend.swap(new_blend);
     cdata->_anim_changed = true;
+    determine_effective_channels(cdata);
   }
 }
 

+ 2 - 2
panda/src/char/characterJoint.cxx

@@ -57,8 +57,8 @@ CharacterJoint(const CharacterJoint &copy) :
 CharacterJoint::
 CharacterJoint(Character *character,
                PartBundle *root, PartGroup *parent, const string &name,
-               const LMatrix4f &initial_value) :
-  MovingPartMatrix(parent, name, initial_value),
+               const LMatrix4f &default_value) :
+  MovingPartMatrix(parent, name, default_value),
   _character(character)
 {
   Thread *current_thread = Thread::get_current_thread();

+ 1 - 1
panda/src/char/characterJoint.h

@@ -38,7 +38,7 @@ protected:
 PUBLISHED:
   CharacterJoint(Character *character,
                  PartBundle *root, PartGroup *parent, const string &name,
-                 const LMatrix4f &initial_value);
+                 const LMatrix4f &default_value);
   virtual ~CharacterJoint();
 
 public:

+ 2 - 0
panda/src/char/jointVertexTransform.cxx

@@ -47,6 +47,7 @@ JointVertexTransform(CharacterJoint *joint) :
 {
   // Tell the joint that we need to be informed when it moves.
   _joint->_vertex_transforms.insert(this);
+  mark_modified(Thread::get_current_thread());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -219,4 +220,5 @@ fillin(DatagramIterator &scan, BamReader *manager) {
 
   manager->read_pointer(scan);
   _matrix_stale = true;
+  mark_modified(Thread::get_current_thread());
 }

+ 23 - 2
panda/src/doc/eggSyntax.txt

@@ -1508,6 +1508,26 @@ GROUPING ENTRIES
     may define either a 2-d or a 3-d transform when it appears within
     the body of a <Texture>.  See <Texture>, above.
 
+  <DefaultPose> { transform-definition }
+
+    This defines an optional default pose transform, which might be a
+    different transform from that defined by the <Transform> entry,
+    above.  This makes sense only for a <Joint>.  See the <Joint>
+    description, below.
+
+    The default pose transform defines the transform the joint will
+    maintain in the absence of any animation being applied.  This is
+    different from the <Transform> entry, which defines the coordinate
+    space the joint must have in order to keep its vertices in their
+    (global space) position as given in the egg file.  If this is
+    different from the <Transform> entry, the joint's vertices will
+    *not* be in their egg file position at initial load.  If there is
+    no <DefaultPose> entry for a particular joint, the implicit
+    default-pose transform is the same as the <Transform> entry.
+
+    Normally, the <DefaultPose> entry, if any, is created by the
+    egg-optchar -defpose option.  Most other software has little
+    reason to specify an explicit <DefaultPose>.
 
   <VertexRef> { indices <Ref> { pool-name } }
 
@@ -1768,8 +1788,9 @@ ANIMATION STRUCTURE
 
   It is not necessary for every joint to have vertices at all.  Every
   joint should include a transform entry, however, which defines the
-  initial, resting transform of the joint.  If a transform is omitted,
-  the identity transform is assumed.
+  initial, resting transform of the joint (but see also <DefaultPose>,
+  above).  If a transform is omitted, the identity transform is
+  assumed.
 
   Some of the vertex definitions may include morph entries, as
   described in MORPH DESCRIPTION ENTRIES, above.  These are meaningful

+ 55 - 0
panda/src/egg/eggGroup.I

@@ -904,6 +904,61 @@ clear_tag(const string &key) {
   _tag_data.erase(key);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::get_default_pose
+//       Access: Published
+//  Description: Returns a read-only accessor to the initial pose
+//               transform.  This is the <DefaultPose> entry for a
+//               Joint, and defines only the initial transform pose
+//               for the unanimated joint; it has nothing to do with
+//               the group's <Transform> entry, which defines the
+//               (eventual) space of the group's vertices.
+////////////////////////////////////////////////////////////////////
+INLINE const EggTransform &EggGroup::
+get_default_pose() const {
+  return _default_pose;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::modify_default_pose
+//       Access: Published
+//  Description: Returns a writable accessor to the initial pose
+//               transform.  This is the <DefaultPose> entry for a
+//               Joint, and defines only the initial transform pose
+//               for the unanimated joint; it has nothing to do with
+//               the group's <Transform> entry, which defines the
+//               (eventual) space of the group's vertices.
+////////////////////////////////////////////////////////////////////
+INLINE EggTransform &EggGroup::
+modify_default_pose() {
+  return _default_pose;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::set_default_pose
+//       Access: Published
+//  Description: Replaces the initial pose transform.  This is the
+//               <DefaultPose> entry for a Joint, and defines only the
+//               initial transform pose for the unanimated joint; it
+//               has nothing to do with the group's <Transform> entry,
+//               which defines the (eventual) space of the group's
+//               vertices.
+////////////////////////////////////////////////////////////////////
+INLINE void EggGroup::
+set_default_pose(const EggTransform &transform) {
+  _default_pose = transform;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::clear_default_pose
+//       Access: Published
+//  Description: Removes the initial pose transform.  See
+//               set_default_pose().
+////////////////////////////////////////////////////////////////////
+INLINE void EggGroup::
+clear_default_pose() {
+  _default_pose.clear_transform();
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: EggGroup::tag_begin

+ 12 - 2
panda/src/egg/eggGroup.cxx

@@ -74,8 +74,8 @@ operator = (const EggGroup &copy) {
   _blend_operand_a = copy._blend_operand_a;
   _blend_operand_b = copy._blend_operand_b;
   _blend_color = copy._blend_color;
-
   _tag_data = copy._tag_data;
+  _default_pose = copy._default_pose;
 
   unref_all_vertices();
   _vref = copy._vref;
@@ -219,7 +219,11 @@ write(ostream &out, int indent_level) const {
   write_switch_flags(out, indent_level + 2);
 
   if (has_transform()) {
-    EggTransform::write(out, indent_level + 2);
+    EggTransform::write(out, indent_level + 2, "<Transform>");
+  }
+
+  if (get_group_type() == GT_joint && _default_pose.has_transform()) {
+    _default_pose.write(out, indent_level + 2, "<DefaultPose>");
   }
 
   write_object_types(out, indent_level + 2);
@@ -1251,6 +1255,12 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
 
     internal_set_transform(inv1 * get_transform3d() * mat);
 
+    if (_default_pose.has_transform()) {
+      LMatrix4d t = _default_pose.get_transform3d();
+      _default_pose.clear_transform();
+      _default_pose.add_matrix4(inv1 * t * mat);
+    }
+
     EggGroupNode::r_transform(mat1, inv1, to_cs);
   } else {
     EggGroupNode::r_transform(mat, inv, to_cs);

+ 11 - 0
panda/src/egg/eggGroup.h

@@ -262,6 +262,11 @@ PUBLISHED:
   INLINE bool has_tag(const string &key) const;
   INLINE void clear_tag(const string &key);
 
+  INLINE const EggTransform &get_default_pose() const;
+  INLINE EggTransform &modify_default_pose();
+  INLINE void set_default_pose(const EggTransform &transform);
+  INLINE void clear_default_pose();
+
 public:
   INLINE TagData::const_iterator tag_begin() const;
   INLINE TagData::const_iterator tag_end() const;
@@ -360,6 +365,12 @@ private:
   double _fps;
   PT(EggSwitchCondition) _lod;
   TagData _tag_data;
+
+  // This is the <DefaultPose> entry for a <Joint>.  It is not the
+  // <Transform> entry (that is stored via inheritance, in the
+  // EggTransform class we inherit from).
+  EggTransform _default_pose;
+
   VertexRef _vref;
 
   typedef pvector< PT(EggGroup) > GroupRefs;

+ 1 - 1
panda/src/egg/eggTexture.cxx

@@ -290,7 +290,7 @@ write(ostream &out, int indent_level) const {
   EggRenderMode::write(out, indent_level + 2);
 
   if (has_transform()) {
-    EggTransform::write(out, indent_level + 2);
+    EggTransform::write(out, indent_level + 2, "<Transform>");
   }
 
   indent(out, indent_level) << "}\n";

+ 2 - 2
panda/src/egg/eggTransform.cxx

@@ -230,8 +230,8 @@ add_uniform_scale(double scale) {
 //               format.
 ////////////////////////////////////////////////////////////////////
 void EggTransform::
-write(ostream &out, int indent_level) const {
-  indent(out, indent_level) << "<Transform> {\n";
+write(ostream &out, int indent_level, const string &label) const {
+  indent(out, indent_level) << label << " {\n";
 
   int num_components = get_num_components();
   for (int i = 0; i < num_components; i++) {

+ 3 - 1
panda/src/egg/eggTransform.h

@@ -17,6 +17,7 @@
 
 #include "pandabase.h"
 #include "luse.h"
+#include "eggObject.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : EggTransform
@@ -85,7 +86,8 @@ PUBLISHED:
   INLINE const LMatrix3d &get_component_mat3(int n) const;
   INLINE const LMatrix4d &get_component_mat4(int n) const;
 
-  void write(ostream &out, int indent_level) const;
+  void write(ostream &out, int indent_level,
+             const string &label) const;
 
 protected:
   void internal_clear_transform();

File diff suppressed because it is too large
+ 388 - 388
panda/src/egg/lexer.cxx.prebuilt


+ 2 - 10
panda/src/egg/lexer.lxx

@@ -435,21 +435,13 @@ NUMERIC         ([+-]?(([0-9]+[.]?)|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
   accept();
   return EXTERNAL_FILE;
 }
-"<FLT_HEADER>" {
-  accept();
-  return FLIGHT;
-}
 "<GROUP>" {
   accept();
   return GROUP;
 }
-"<HIP>" {
-  accept();
-  return HIP;
-}
-"<IN>" {
+"<DEFAULTPOSE>" {
   accept();
-  return INTANGENT;
+  return DEFAULTPOSE;
 }
 "<JOINT>" {
   accept();

File diff suppressed because it is too large
+ 739 - 720
panda/src/egg/parser.cxx.prebuilt


+ 61 - 63
panda/src/egg/parser.h.prebuilt

@@ -24,69 +24,67 @@
 #define	DTREF	280
 #define	DYNAMICVERTEXPOOL	281
 #define	EXTERNAL_FILE	282
-#define	FLIGHT	283
-#define	GROUP	284
-#define	HIP	285
-#define	INTANGENT	286
-#define	JOINT	287
-#define	KNOTS	288
-#define	INCLUDE	289
-#define	INSTANCE	290
-#define	LINE	291
-#define	LOOP	292
-#define	MATERIAL	293
-#define	MATRIX3	294
-#define	MATRIX4	295
-#define	MODEL	296
-#define	MREF	297
-#define	NORMAL	298
-#define	NURBSCURVE	299
-#define	NURBSSURFACE	300
-#define	OBJECTTYPE	301
-#define	ORDER	302
-#define	OUTTANGENT	303
-#define	POINTLIGHT	304
-#define	POLYGON	305
-#define	REF	306
-#define	RGBA	307
-#define	ROTATE	308
-#define	ROTX	309
-#define	ROTY	310
-#define	ROTZ	311
-#define	SANIM	312
-#define	SCALAR	313
-#define	SCALE	314
-#define	SEQUENCE	315
-#define	SHADING	316
-#define	SWITCH	317
-#define	SWITCHCONDITION	318
-#define	TABLE	319
-#define	TABLE_V	320
-#define	TAG	321
-#define	TANGENT	322
-#define	TEXLIST	323
-#define	TEXTURE	324
-#define	TLENGTHS	325
-#define	TRANSFORM	326
-#define	TRANSLATE	327
-#define	TREF	328
-#define	TRIANGLEFAN	329
-#define	TRIANGLESTRIP	330
-#define	TRIM	331
-#define	TXT	332
-#define	UKNOTS	333
-#define	UV	334
-#define	VKNOTS	335
-#define	VERTEX	336
-#define	VERTEXANIM	337
-#define	VERTEXPOOL	338
-#define	VERTEXREF	339
-#define	XFMANIM	340
-#define	XFMSANIM	341
-#define	START_EGG	342
-#define	START_GROUP_BODY	343
-#define	START_TEXTURE_BODY	344
-#define	START_PRIMITIVE_BODY	345
+#define	GROUP	283
+#define	DEFAULTPOSE	284
+#define	JOINT	285
+#define	KNOTS	286
+#define	INCLUDE	287
+#define	INSTANCE	288
+#define	LINE	289
+#define	LOOP	290
+#define	MATERIAL	291
+#define	MATRIX3	292
+#define	MATRIX4	293
+#define	MODEL	294
+#define	MREF	295
+#define	NORMAL	296
+#define	NURBSCURVE	297
+#define	NURBSSURFACE	298
+#define	OBJECTTYPE	299
+#define	ORDER	300
+#define	OUTTANGENT	301
+#define	POINTLIGHT	302
+#define	POLYGON	303
+#define	REF	304
+#define	RGBA	305
+#define	ROTATE	306
+#define	ROTX	307
+#define	ROTY	308
+#define	ROTZ	309
+#define	SANIM	310
+#define	SCALAR	311
+#define	SCALE	312
+#define	SEQUENCE	313
+#define	SHADING	314
+#define	SWITCH	315
+#define	SWITCHCONDITION	316
+#define	TABLE	317
+#define	TABLE_V	318
+#define	TAG	319
+#define	TANGENT	320
+#define	TEXLIST	321
+#define	TEXTURE	322
+#define	TLENGTHS	323
+#define	TRANSFORM	324
+#define	TRANSLATE	325
+#define	TREF	326
+#define	TRIANGLEFAN	327
+#define	TRIANGLESTRIP	328
+#define	TRIM	329
+#define	TXT	330
+#define	UKNOTS	331
+#define	UV	332
+#define	VKNOTS	333
+#define	VERTEX	334
+#define	VERTEXANIM	335
+#define	VERTEXPOOL	336
+#define	VERTEXREF	337
+#define	XFMANIM	338
+#define	XFMSANIM	339
+#define	START_EGG	340
+#define	START_GROUP_BODY	341
+#define	START_TEXTURE_BODY	342
+#define	START_PRIMITIVE_BODY	343
 
 
 extern YYSTYPE eggyylval;

+ 41 - 15
panda/src/egg/parser.yxx

@@ -33,6 +33,7 @@
 #include "eggExternalReference.h"
 #include "eggData.h"
 #include "eggAnimPreload.h"
+#include "eggTransform.h"
 #include "pt_EggTexture.h"
 #include "pt_EggMaterial.h"
 
@@ -61,6 +62,9 @@
 typedef pvector< PT(EggObject) > EggStack;
 static EggStack egg_stack;
 
+// This is used just when parsing a <Transform> or <DefaultPose> entry.
+static EggTransform *egg_top_transform;
+
 // There's one "top-level" egg node, which is where we should parent
 // things (e.g. implicit textures) encountered in the egg file that
 // don't have an explicit place in the tree.  If this is NULL, such
@@ -160,7 +164,7 @@ egg_cleanup_parser() {
 %token COORDSYSTEM CV DART
 %token DNORMAL DRGBA DUV DXYZ DCS DISTANCE DTREF
 %token DYNAMICVERTEXPOOL EXTERNAL_FILE
-%token FLIGHT GROUP HIP INTANGENT
+%token GROUP DEFAULTPOSE 
 %token JOINT KNOTS INCLUDE
 %token INSTANCE LINE LOOP MATERIAL MATRIX3 MATRIX4 MODEL MREF NORMAL
 %token NURBSCURVE NURBSSURFACE OBJECTTYPE ORDER
@@ -1432,6 +1436,7 @@ group_body:
   group->set_texlist_flag(value!=0);
 }
         | group_body transform
+        | group_body default_pose
         | group_body group_vertex_ref
         | group_body switchcondition
         | group_body REF '{' group_name '}'
@@ -1512,7 +1517,28 @@ collide_flags:
 transform:
         TRANSFORM
 {
-  egg_stack.back()->as_transform()->clear_transform();
+  egg_top_transform = egg_stack.back()->as_transform();
+  egg_top_transform->clear_transform();
+}
+        '{' transform_body '}'
+        ;
+
+/*
+ * default_pose
+ *
+ * enter: TOS is an EggGroup
+ * exit: default_pose matrix has been set.
+ *
+ */
+default_pose:
+        DEFAULTPOSE
+{
+  EggGroup *group = DCAST(EggGroup, egg_stack.back());
+  if (group->get_group_type() != EggGroup::GT_joint) {
+    eggyywarning("Unexpected <DefaultPose> outside of <Joint>");
+  }
+  egg_top_transform = &group->modify_default_pose();
+  egg_top_transform->clear_transform();
 }
         '{' transform_body '}'
         ;
@@ -1521,7 +1547,7 @@ transform:
 /*
  * transform_body
  *
- * enter: TOS is some kind of EggTransform.
+ * enter: egg_top_transform has been assigned.
  * exit: transform has been filled in.
  *
  */
@@ -1544,70 +1570,70 @@ transform_body:
 translate2d:
         TRANSLATE '{' real real '}'
 {
-  egg_stack.back()->as_transform()->add_translate2d(LVector2d($3, $4));
+  egg_top_transform->add_translate2d(LVector2d($3, $4));
 }
         ;
 
 translate3d:
         TRANSLATE '{' real real real '}'
 {
-  egg_stack.back()->as_transform()->add_translate3d(LVector3d($3, $4, $5));
+  egg_top_transform->add_translate3d(LVector3d($3, $4, $5));
 }
         ;
 
 rotate2d:
         ROTATE '{' real '}'
 {
-  egg_stack.back()->as_transform()->add_rotate2d($3);
+  egg_top_transform->add_rotate2d($3);
 }
         ;
 
 rotx:
         ROTX '{' real '}'
 {
-  egg_stack.back()->as_transform()->add_rotx($3);
+  egg_top_transform->add_rotx($3);
 }
         ;
 
 roty:
         ROTY '{' real '}'
 {
-  egg_stack.back()->as_transform()->add_roty($3);
+  egg_top_transform->add_roty($3);
 }
         ;
 
 rotz:
         ROTZ '{' real '}'
 {
-  egg_stack.back()->as_transform()->add_rotz($3);
+  egg_top_transform->add_rotz($3);
 }
         ;
 
 rotate3d:
         ROTATE '{' real real real real '}'
 {
-  egg_stack.back()->as_transform()->add_rotate3d($3, LVector3d($4, $5, $6));
+  egg_top_transform->add_rotate3d($3, LVector3d($4, $5, $6));
 }
         ;
 
 scale2d:
         SCALE '{' real real '}'
 {
-  egg_stack.back()->as_transform()->add_scale2d(LVecBase2d($3, $4));
+  egg_top_transform->add_scale2d(LVecBase2d($3, $4));
 }
         ;
 
 scale3d:
         SCALE '{' real real real '}'
 {
-  egg_stack.back()->as_transform()->add_scale3d(LVecBase3d($3, $4, $5));
+  egg_top_transform->add_scale3d(LVecBase3d($3, $4, $5));
 }
         ;
 
 uniform_scale:
         SCALE '{' real '}'
 {
-  egg_stack.back()->as_transform()->add_uniform_scale($3);
+  egg_top_transform->add_uniform_scale($3);
 }
         ;
 
@@ -1621,7 +1647,7 @@ matrix3_body:
           real real real
           real real real
 {
-  egg_stack.back()->as_transform()->add_matrix3
+  egg_top_transform->add_matrix3
     (LMatrix3d($1, $2, $3,
                $4, $5, $6,
                $7, $8, $9));
@@ -1639,7 +1665,7 @@ matrix4_body:
           real real real real 
           real real real real 
 {
-  egg_stack.back()->as_transform()->add_matrix4
+  egg_top_transform->add_matrix4
     (LMatrix4d($1, $2, $3, $4,
                $5, $6, $7, $8,
                $9, $10, $11, $12,

+ 19 - 2
panda/src/egg2pg/characterMaker.cxx

@@ -224,17 +224,21 @@ egg_to_slider(const string &name) {
 CharacterJointBundle *CharacterMaker::
 make_bundle() {
   build_joint_hierarchy(_egg_root, _skeleton_root, -1);
-
   make_geometry(_egg_root);
 
   _bundle->sort_descendants();
   parent_joint_nodes(_skeleton_root);
 
+  // Now call update() one more time, to ensure that all of the joints
+  // have their correct transform (since we might have modified the
+  // default transform after construction).
+  _bundle->force_update();
+
   return _bundle;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: CharacterMaker::build_hierarchy
+//     Function: CharacterMaker::build_joint_hierarchy
 //       Access: Private
 //  Description:
 ////////////////////////////////////////////////////////////////////
@@ -271,6 +275,9 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) {
       // We need to get the transform of the joint, and then convert
       // it to single-precision.
       LMatrix4d matd;
+
+      // First, we get the original, initial transform from the
+      // <Transform> entry.
       if (egg_group->has_transform()) {
         matd = egg_group->get_transform3d();
       } else {
@@ -285,6 +292,16 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part, int index) {
       index = _parts.size();
       _parts.push_back(joint);
 
+      // Now that we have computed _net_transform (which we need to
+      // convert the vertices), update the default transform from the
+      // <DefaultPose> entry.
+      if (egg_group->get_default_pose().has_transform()) {
+        matd = egg_group->get_default_pose().get_transform3d();
+        matf = LCAST(float, matd);
+        joint->_default_value = matf;
+        joint->_value = matf;
+      }
+
       if (egg_group->has_dcs_type()) {
         // If the joint requested an explicit DCS, create a node for
         // it.

+ 1 - 0
panda/src/gobj/transformBlend.cxx

@@ -189,6 +189,7 @@ write(ostream &out, int indent_level) const {
     mat.write(out, indent_level + 4);
   }
   LMatrix4f blend;
+  update_blend(current_thread);
   get_blend(blend, current_thread);
   indent(out, indent_level)
     << "Blended result =\n";

+ 94 - 0
pandatool/src/egg-optchar/eggOptchar.cxx

@@ -112,6 +112,16 @@ EggOptchar() {
      "objects parented to this node will not inherit its animation.",
      &EggOptchar::dispatch_flag_groups, NULL, &_flag_groups);
 
+  add_option
+    ("defpose", "anim.egg,frame", 0,
+     "Specify the model's default pose.  The pose is taken "
+     "from the indicated frame of the named animation file (which must "
+     "also be named separately on the command line).  The "
+     "pose will be held by the model in "
+     "the absence of any animation, and need not be the same "
+     "pose in which the model was originally skinned.",
+     &EggOptchar::dispatch_string, NULL, &_defpose);
+
   add_option
     ("preload", "", 0,
      "Add an <AnimPreload> entry for each animation to the model file(s).  "
@@ -273,6 +283,13 @@ run() {
       do_preload();
     }
 
+    // Finally, set the default poses.  It's important not to do this
+    // until after we have adjusted all of the transforms for the
+    // various joints.
+    if (!_defpose.empty()) {
+      do_defpose();
+    }
+
     write_eggs();
   }
 }
@@ -1421,6 +1438,83 @@ do_preload() {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggOptchar::do_defpose
+//       Access: Private
+//  Description: Sets the initial pose for the character(s).
+////////////////////////////////////////////////////////////////////
+void EggOptchar::
+do_defpose() {
+  // Split out the defpose parameter.
+  Filename egg_filename;
+  size_t comma = _defpose.find(',');
+  egg_filename = _defpose.substr(0, comma);
+
+  string frame_str;
+  if (comma != string::npos) {
+    frame_str = _defpose.substr(comma + 1);
+  }
+  frame_str = trim(frame_str);
+  int frame = 0;
+  if (!frame_str.empty()) {
+    if (!string_to_int(frame_str, frame)) {
+      nout << "Invalid integer in -defpose: " << frame_str << "\n";
+      return;
+    }
+  }
+
+  // Now find the named animation file in our egg list.
+  int egg_index = -1;
+  int num_eggs = _collection->get_num_eggs();
+  int i;
+
+  // First, look for an exact match.
+  for (i = 0; i < num_eggs && egg_index == -1; ++i) {
+    if (_collection->get_egg(i)->get_egg_filename() == egg_filename) {
+      egg_index = i;
+    }
+  }
+
+  // Then, look for an inexact match.
+  string egg_basename = egg_filename.get_basename_wo_extension();
+  for (i = 0; i < num_eggs && egg_index == -1; ++i) {
+    if (_collection->get_egg(i)->get_egg_filename().get_basename_wo_extension() == egg_basename) {
+      egg_index = i;
+    }
+  }
+
+  if (egg_index == -1) {
+    // No joy.
+    nout << "Egg file " << egg_filename << " named in -defpose, but does not appear on command line.\n";
+    return;
+  }
+
+  EggData *egg_data = _collection->get_egg(egg_index);
+
+  if (_collection->get_num_models(egg_index) == 0) {
+    nout << "Egg file " << egg_filename << " does not include any model or animation.\n";
+    return;
+  }
+
+  // Now get the first model (or animation) named by this egg file.
+  int mi = _collection->get_first_model_index(egg_index);
+  EggCharacterData *ch = _collection->get_character_by_model_index(mi);
+  EggJointData *root_joint = ch->get_root_joint();
+
+  int anim_index = -1;
+  for (i = 0; i < ch->get_num_models() && anim_index == -1; ++i) {
+    if (ch->get_egg_data(i) == egg_data) {
+      anim_index = i;
+    }
+  }
+
+  // This couldn't possibly fail, since we already checked this above.
+  nassertv(anim_index != -1);
+
+  // Now we can recursively apply the default pose to the hierarchy.
+  ch->get_root_joint()->apply_default_pose(anim_index, frame);
+}
+
 int main(int argc, char *argv[]) {
   // A call to pystub() to force libpystub.so to be linked in.
   pystub();

+ 3 - 0
pandatool/src/egg-optchar/eggOptchar.h

@@ -78,6 +78,7 @@ private:
   void do_flag_groups(EggGroupNode *egg_group);
   void rename_primitives(EggGroupNode *egg_group, const string &name);
   void do_preload();
+  void do_defpose();
 
   bool _list_hierarchy;
   bool _list_hierarchy_v;
@@ -118,6 +119,8 @@ private:
   typedef pvector<FlagGroupsEntry> FlagGroups;
   FlagGroups _flag_groups;
 
+  string _defpose;
+
   bool _optimal_hierarchy;
   double _vref_quantum;
 };

+ 31 - 0
pandatool/src/eggcharbase/eggJointData.cxx

@@ -411,6 +411,37 @@ quantize_channels(const string &components, double quantum) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointData::apply_default_pose
+//       Access: Public
+//  Description: Applies the pose from the indicated frame of the
+//               indicated source model_index as the initial pose for
+//               this joint, and does this recursively on all joints
+//               below.
+////////////////////////////////////////////////////////////////////
+void EggJointData::
+apply_default_pose(int source_model, int frame) {
+  if (has_model(source_model)) {
+    EggJointPointer *source_joint;
+    DCAST_INTO_V(source_joint, _back_pointers[source_model]);
+    BackPointers::iterator bpi;
+    for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
+      EggBackPointer *back = (*bpi);
+      if (back != (EggBackPointer *)NULL) {
+        EggJointPointer *joint;
+        DCAST_INTO_V(joint, back);
+        joint->apply_default_pose(source_joint, frame);
+      }
+    }
+  }
+
+  Children::iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    EggJointData *child = (*ci);
+    child->apply_default_pose(source_model, frame);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggJointData::add_back_pointer
 //       Access: Public, Virtual

+ 1 - 0
pandatool/src/eggcharbase/eggJointData.h

@@ -59,6 +59,7 @@ public:
   void expose(EggGroup::DCSType dcs_type = EggGroup::DC_default);
   void zero_channels(const string &components);
   void quantize_channels(const string &components, double quantum);
+  void apply_default_pose(int source_model, int frame);
 
   virtual void add_back_pointer(int model_index, EggObject *egg_object);
   virtual void write(ostream &out, int indent_level = 0) const;

+ 21 - 0
pandatool/src/eggcharbase/eggJointNodePointer.cxx

@@ -178,6 +178,27 @@ expose(EggGroup::DCSType dcs_type) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointNodePointer::apply_default_pose
+//       Access: Public, Virtual
+//  Description: Applies the pose from the indicated frame of the
+//               indicated source joint as the initial pose for
+//               this joint.
+////////////////////////////////////////////////////////////////////
+void EggJointNodePointer::
+apply_default_pose(EggJointPointer *source_joint, int frame) {
+  if (_joint != (EggGroup *)NULL) {
+    LMatrix4d pose;
+    if (frame >= 0 && frame < source_joint->get_num_frames()) {
+      pose = source_joint->get_frame(frame);
+    } else {
+      pose = get_frame(0);
+    }
+    _joint->clear_default_pose();
+    _joint->modify_default_pose().add_matrix4(pose);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggJointNodePointer::has_vertices
 //       Access: Public, Virtual

+ 1 - 0
pandatool/src/eggcharbase/eggJointNodePointer.h

@@ -39,6 +39,7 @@ public:
 
   virtual bool do_rebuild(EggCharacterDb &db);
   virtual void expose(EggGroup::DCSType dcs_type);
+  virtual void apply_default_pose(EggJointPointer *source_joint, int frame);
 
   virtual bool has_vertices() const;
 

+ 11 - 0
pandatool/src/eggcharbase/eggJointPointer.cxx

@@ -98,3 +98,14 @@ zero_channels(const string &) {
 void EggJointPointer::
 quantize_channels(const string &, double) {
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointPointer::apply_default_pose
+//       Access: Public, Virtual
+//  Description: Applies the pose from the indicated frame of the
+//               indicated source joint as the initial pose for
+//               this joint.
+////////////////////////////////////////////////////////////////////
+void EggJointPointer::
+apply_default_pose(EggJointPointer *source_joint, int frame) {
+}

+ 1 - 0
pandatool/src/eggcharbase/eggJointPointer.h

@@ -47,6 +47,7 @@ public:
   virtual void expose(EggGroup::DCSType dcs_type);
   virtual void zero_channels(const string &components);
   virtual void quantize_channels(const string &components, double quantum);
+  virtual void apply_default_pose(EggJointPointer *source_joint, int frame);
 
   virtual EggJointPointer *make_new_joint(const string &name)=0;
 

Some files were not shown because too many files changed in this diff