Browse Source

egg loader defines morphs

David Rose 21 years ago
parent
commit
bf68f75f91

+ 9 - 3
panda/src/char/Sources.pp

@@ -12,7 +12,9 @@
   #define SOURCES \
     character.I character.h \
     characterJoint.h characterJointBundle.I  \
-    characterJointBundle.h characterSlider.h computedVertices.I  \
+    characterJointBundle.h characterSlider.h \
+    characterVertexSlider.I characterVertexSlider.h \
+    computedVertices.I  \
     computedVertices.h computedVerticesMorph.I  \
     computedVerticesMorph.h config_char.h dynamicVertices.h \
     jointVertexTransform.I jointVertexTransform.h
@@ -20,7 +22,9 @@
   #define INCLUDED_SOURCES \
     character.cxx \
     characterJoint.cxx characterJointBundle.cxx  \
-    characterSlider.cxx computedVertices.cxx  \
+    characterSlider.cxx \
+    characterVertexSlider.cxx \
+    computedVertices.cxx  \
     computedVerticesMorph.cxx config_char.cxx  \
     dynamicVertices.cxx \
     jointVertexTransform.cxx
@@ -28,7 +32,9 @@
   #define INSTALL_HEADERS \
     character.I character.h \
     characterJoint.h characterJointBundle.I \
-    characterJointBundle.h characterSlider.h computedVertices.I \
+    characterJointBundle.h characterSlider.h \
+    characterVertexSlider.I characterVertexSlider.h \
+    computedVertices.I \
     computedVertices.h computedVerticesMorph.I computedVerticesMorph.h \
     config_char.h dynamicVertices.h \
     jointVertexTransform.I jointVertexTransform.h

+ 1 - 0
panda/src/char/char_composite2.cxx

@@ -1,5 +1,6 @@
 
 #include "characterSlider.cxx"
+#include "characterVertexSlider.cxx"
 #include "computedVertices.cxx"
 #include "computedVerticesMorph.cxx"
 #include "dynamicVertices.cxx"

+ 34 - 0
panda/src/char/characterSlider.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "characterSlider.h"
+#include "characterVertexSlider.h"
 #include "datagram.h"
 #include "datagramIterator.h"
 #include "bamReader.h"
@@ -54,6 +55,16 @@ CharacterSlider(PartGroup *parent, const string &name)
   : MovingPartScalar(parent, name) {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterSlider::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CharacterSlider::
+~CharacterSlider() {
+  nassertv(_vertex_sliders.empty());
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CharacterSlider::make_copy
 //       Access: Public, Virtual
@@ -65,6 +76,29 @@ make_copy() const {
   return new CharacterSlider(*this);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterSlider::update_internals
+//       Access: Public, Virtual
+//  Description: This is called by do_update() whenever the part or
+//               some ancestor has changed values.  It is a hook for
+//               derived classes to update whatever cache they may
+//               have that depends on these.
+//
+//               The return value is true if the part has changed as a
+//               result of the update, or false otherwise.
+////////////////////////////////////////////////////////////////////
+bool CharacterSlider::
+update_internals(PartGroup *, bool, bool) {
+  // Tell our related CharacterVertexSliders that they now need to
+  // recompute themselves.
+  VertexSliders::iterator vsi;
+  for (vsi = _vertex_sliders.begin(); vsi != _vertex_sliders.end(); ++vsi) {
+    (*vsi)->mark_modified();
+  }
+  
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: CharacterSlider::make_CharacterSlider
 //       Access: Protected

+ 13 - 0
panda/src/char/characterSlider.h

@@ -23,6 +23,8 @@
 
 #include "movingPartScalar.h"
 
+class CharacterVertexSlider;
+
 ////////////////////////////////////////////////////////////////////
 //       Class : CharacterSlider
 // Description : This is a morph slider within the character.  It's
@@ -37,9 +39,18 @@ protected:
 
 public:
   CharacterSlider(PartGroup *parent, const string &name);
+  virtual ~CharacterSlider();
 
   virtual PartGroup *make_copy() const;
 
+  virtual bool update_internals(PartGroup *parent, bool self_changed,
+                                bool parent_changed);
+
+private:
+  typedef pset<CharacterVertexSlider *> VertexSliders;
+  VertexSliders _vertex_sliders;
+
+public:
   static void register_with_read_factory();
 
   static TypedWritable *make_CharacterSlider(const FactoryParams &params);
@@ -60,6 +71,8 @@ public:
 
 private:
   static TypeHandle _type_handle;
+
+  friend class CharacterVertexSlider;
 };
 
 #endif

+ 29 - 0
panda/src/char/characterVertexSlider.I

@@ -0,0 +1,29 @@
+// Filename: characterVertexSlider.I
+// Created by:  drose (28Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::get_char_slider
+//       Access: Published
+//  Description: Returns the CharacterSlider object for which this
+//               object returns the slider value.
+////////////////////////////////////////////////////////////////////
+INLINE const CharacterSlider *CharacterVertexSlider::
+get_char_slider() const {
+  return _char_slider;
+}

+ 142 - 0
panda/src/char/characterVertexSlider.cxx

@@ -0,0 +1,142 @@
+// Filename: characterVertexSlider.cxx
+// Created by:  drose (28Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "characterVertexSlider.h"
+#include "datagram.h"
+#include "datagramIterator.h"
+#include "bamReader.h"
+#include "bamWriter.h"
+
+TypeHandle CharacterVertexSlider::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::Default Constructor
+//       Access: Private
+//  Description: Constructs an invalid object; used only by the bam
+//               loader.
+////////////////////////////////////////////////////////////////////
+CharacterVertexSlider::
+CharacterVertexSlider() :
+  VertexSlider(InternalName::get_root())
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::Constructor
+//       Access: Published
+//  Description: Constructs a new object that converts vertices from
+//               the indicated joint's coordinate space, into the
+//               other indicated joint's space.
+////////////////////////////////////////////////////////////////////
+CharacterVertexSlider::
+CharacterVertexSlider(CharacterSlider *char_slider) :
+  VertexSlider(InternalName::make(char_slider->get_name())),
+  _char_slider(char_slider)
+{
+  // Tell the char_slider that we need to be informed when it moves.
+  _char_slider->_vertex_sliders.insert(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::Destructor
+//       Access: Published, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CharacterVertexSlider::
+~CharacterVertexSlider() {
+  // Tell the char_slider to stop informing us about its motion.
+  _char_slider->_vertex_sliders.erase(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::get_slider
+//       Access: Published, Virtual
+//  Description: Returns the current slider value.
+////////////////////////////////////////////////////////////////////
+float CharacterVertexSlider::
+get_slider() const {
+  return _char_slider->_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               CharacterVertexSlider.
+////////////////////////////////////////////////////////////////////
+void CharacterVertexSlider::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void CharacterVertexSlider::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  VertexSlider::write_datagram(manager, dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::complete_pointers
+//       Access: Public, Virtual
+//  Description: Receives an array of pointers, one for each time
+//               manager->read_pointer() was called in fillin().
+//               Returns the number of pointers processed.
+////////////////////////////////////////////////////////////////////
+int CharacterVertexSlider::
+complete_pointers(TypedWritable **p_list, BamReader *manager) {
+  int pi = VertexSlider::complete_pointers(p_list, manager);
+
+  return pi;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type CharacterVertexSlider is encountered
+//               in the Bam file.  It should create the CharacterVertexSlider
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *CharacterVertexSlider::
+make_from_bam(const FactoryParams &params) {
+  CharacterVertexSlider *object = new CharacterVertexSlider;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  object->fillin(scan, manager);
+
+  return object;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterVertexSlider::fillin
+//       Access: Protected
+//  Description: This internal function is called by make_from_bam to
+//               read in all of the relevant data from the BamFile for
+//               the new CharacterVertexSlider.
+////////////////////////////////////////////////////////////////////
+void CharacterVertexSlider::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  VertexSlider::fillin(scan, manager);
+}

+ 81 - 0
panda/src/char/characterVertexSlider.h

@@ -0,0 +1,81 @@
+// Filename: characterVertexSlider.h
+// Created by:  drose (28Mar05)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CHARACTERVERTEXSLIDER_H
+#define CHARACTERVERTEXSLIDER_H
+
+#include "pandabase.h"
+#include "characterSlider.h"
+#include "vertexSlider.h"
+#include "pointerTo.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : CharacterVertexSlider
+// Description : This is a specialization on VertexSlider that
+//               returns the slider value associated with a particular
+//               CharacterSlider object.
+//
+//               This is part of the experimental Geom rewrite.
+////////////////////////////////////////////////////////////////////
+class EXPCL_PANDA CharacterVertexSlider : public VertexSlider {
+private:
+  CharacterVertexSlider();
+
+PUBLISHED:
+  CharacterVertexSlider(CharacterSlider *char_slider);
+  virtual ~CharacterVertexSlider();
+
+  INLINE const CharacterSlider *get_char_slider() const;
+
+  virtual float get_slider() const;
+
+private:
+  PT(CharacterSlider) _char_slider;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+  virtual int complete_pointers(TypedWritable **plist, BamReader *manager);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    VertexSlider::init_type();
+    register_type(_type_handle, "CharacterVertexSlider",
+                  VertexSlider::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+
+  friend class CharacterSlider;
+};
+
+#include "characterVertexSlider.I"
+
+#endif

+ 3 - 0
panda/src/char/config_char.cxx

@@ -22,6 +22,7 @@
 #include "characterJoint.h"
 #include "characterJointBundle.h"
 #include "characterSlider.h"
+#include "characterVertexSlider.h"
 #include "computedVertices.h"
 #include "dynamicVertices.h"
 #include "jointVertexTransform.h"
@@ -64,6 +65,7 @@ init_libchar() {
   CharacterJoint::init_type();
   CharacterJointBundle::init_type();
   CharacterSlider::init_type();
+  CharacterVertexSlider::init_type();
   ComputedVertices::init_type();
   DynamicVertices::init_type();
   JointVertexTransform::init_type();
@@ -80,6 +82,7 @@ init_libchar() {
   CharacterJoint::register_with_read_factory();
   CharacterJointBundle::register_with_read_factory();
   CharacterSlider::register_with_read_factory();
+  CharacterVertexSlider::register_with_read_factory();
   ComputedVertices::register_with_read_factory();
   JointVertexTransform::register_with_read_factory();
 }

+ 21 - 0
panda/src/egg2pg/characterMaker.cxx

@@ -34,6 +34,7 @@
 #include "eggSurface.h"
 #include "eggCurve.h"
 #include "modelNode.h"
+#include "characterVertexSlider.h"
 #include "jointVertexTransform.h"
 #include "userVertexTransform.h"
 
@@ -206,6 +207,26 @@ create_slider(const string &name) {
   return index;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: CharacterMaker::egg_to_slider
+//       Access: Public
+//  Description: Returns the VertexSlider corresponding to the
+//               indicated egg slider name.
+////////////////////////////////////////////////////////////////////
+VertexSlider *CharacterMaker::
+egg_to_slider(const string &name) {
+  VertexSliders::iterator vi = _vertex_sliders.find(name);
+  if (vi != _vertex_sliders.end()) {
+    return (*vi).second;
+  }
+
+  int index = create_slider(name);
+  PT(VertexSlider) slider = 
+    new CharacterVertexSlider(DCAST(CharacterSlider, _parts[index]));
+  _vertex_sliders[name] = slider;
+  return slider;
+}
+
 
 ////////////////////////////////////////////////////////////////////
 //     Function: CharacterMaker::make_bundle

+ 5 - 0
panda/src/egg2pg/characterMaker.h

@@ -23,6 +23,7 @@
 
 #include "computedVerticesMaker.h"
 #include "vertexTransform.h"
+#include "vertexSlider.h"
 #include "character.h"
 #include "vector_PartGroupStar.h"
 #include "typedef.h"
@@ -61,6 +62,7 @@ public:
   PandaNode *part_to_node(PartGroup *part) const;
 
   int create_slider(const string &name);
+  VertexSlider *egg_to_slider(const string &name);
 
 private:
   CharacterJointBundle *make_bundle();
@@ -88,6 +90,9 @@ private:
   VertexTransforms _vertex_transforms;
   PT(VertexTransform) _identity_transform;
 
+  typedef pmap<string, PT(VertexSlider) > VertexSliders;
+  VertexSliders _vertex_sliders;
+
   EggLoader &_loader;
   EggGroup *_egg_root;
   PT(Character) _character_node;

+ 138 - 20
panda/src/egg2pg/eggLoader.cxx

@@ -1952,17 +1952,78 @@ make_vertex_data(const EggRenderState *render_state,
   PT(qpGeomVertexFormat) temp_format = new qpGeomVertexFormat(array_format);
 
   PT(TransformBlendPalette) blend_palette;
-  string name;
+  PT(SliderTable) slider_table;
+  string name = _data->get_egg_filename().get_basename_wo_extension();
 
   if (is_dynamic) {
-    // If it's a dynamic object, we need a TransformBlendPalette, and
-    // another array that indexes into the palette per vertex.
+    // If it's a dynamic object, we need a TransformBlendPalette and
+    // maybe a SliderTable, and additional columns in the vertex data:
+    // one that indexes into the blend palette per vertex, and also
+    // one for each different type of morph delta.
     blend_palette = new TransformBlendPalette;
-    PT(qpGeomVertexArrayFormat) blend_array_format = new qpGeomVertexArrayFormat;
-    blend_array_format->add_data_type
+
+    PT(qpGeomVertexArrayFormat) anim_array_format = new qpGeomVertexArrayFormat;
+    anim_array_format->add_data_type
       (InternalName::get_transform_blend(), 1, 
        qpGeomVertexDataType::NT_uint16, qpGeomVertexDataType::C_index);
-    temp_format->add_array(blend_array_format);
+    temp_format->add_array(anim_array_format);
+
+    pset<string> slider_names;
+    EggVertexPool::const_iterator vi;
+    for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
+      EggVertex *vertex = (*vi);
+      
+      EggMorphVertexList::const_iterator mvi;
+      for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
+        slider_names.insert((*mvi).get_name());
+        record_morph(anim_array_format, character_maker, (*mvi).get_name(),
+                     InternalName::get_vertex(), 3);
+      }
+      if (vertex->has_normal()) {
+        EggMorphNormalList::const_iterator mni;
+        for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
+          slider_names.insert((*mni).get_name());
+          record_morph(anim_array_format, character_maker, (*mni).get_name(),
+                       InternalName::get_normal(), 3);
+        }
+      }
+      if (vertex->has_color()) {
+        EggMorphColorList::const_iterator mci;
+        for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
+          slider_names.insert((*mci).get_name());
+          record_morph(anim_array_format, character_maker, (*mci).get_name(),
+                       InternalName::get_color(), 4);
+        }
+      }
+      EggVertex::const_uv_iterator uvi;
+      for (uvi = vertex->uv_begin(); uvi != vertex->uv_end(); ++uvi) {
+        EggVertexUV *egg_uv = (*uvi);
+        string name = egg_uv->get_name();
+        if (name == "default") {
+          name = string();
+        }
+        PT(InternalName) iname = InternalName::get_texcoord_name(name);
+
+        EggMorphTexCoordList::const_iterator mti;
+        for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
+          slider_names.insert((*mti).get_name());
+          record_morph(anim_array_format, character_maker, (*mti).get_name(),
+                       iname, 2);
+        }
+      }
+    }
+
+    if (!slider_names.empty()) {
+      // If we have any sliders at all, create a table for them.
+
+      slider_table = new SliderTable;
+      
+      pset<string>::iterator si;
+      for (si = slider_names.begin(); si != slider_names.end(); ++si) {
+        VertexSlider *slider = character_maker->egg_to_slider(*si);
+        slider_table->add_slider(slider);
+      }
+    }
 
     // We'll also assign the character name to the vertex data, so it
     // will show up in PStats.
@@ -1980,28 +2041,56 @@ make_vertex_data(const EggRenderState *render_state,
   PT(qpGeomVertexData) vertex_data =
     new qpGeomVertexData(name, format, qpGeomUsageHint::UH_static);
 
-  if (is_dynamic) {
-    vertex_data->set_transform_blend_palette(blend_palette);
+  vertex_data->set_transform_blend_palette(blend_palette);
+  if (slider_table != (SliderTable *)NULL) {
+    vertex_data->set_slider_table(SliderTable::register_table(slider_table));
   }
 
   // And fill the data from the vertex pool.
   EggVertexPool::const_iterator vi;
   for (vi = vertex_pool->begin(); vi != vertex_pool->end(); ++vi) {
-    qpGeomVertexWriter gvi(vertex_data);
+    qpGeomVertexWriter gvw(vertex_data);
     EggVertex *vertex = (*vi);
-    gvi.set_vertex(vertex->get_index());
+    gvw.set_vertex(vertex->get_index());
 
-    gvi.set_data_type(InternalName::get_vertex());
-    gvi.add_data4f(LCAST(float, vertex->get_pos4() * transform));
+    gvw.set_data_type(InternalName::get_vertex());
+    gvw.add_data4f(LCAST(float, vertex->get_pos4() * transform));
+
+    EggMorphVertexList::const_iterator mvi;
+    for (mvi = vertex->_dxyzs.begin(); mvi != vertex->_dxyzs.end(); ++mvi) {
+      const EggMorphVertex &morph = (*mvi);
+      CPT(InternalName) delta_name = 
+        InternalName::get_morph(InternalName::get_vertex(), morph.get_name());
+      gvw.set_data_type(delta_name);
+      gvw.add_data3f(LCAST(float, morph.get_offset() * transform));
+    }
 
     if (vertex->has_normal()) {
-      gvi.set_data_type(InternalName::get_normal());
-      gvi.add_data3f(LCAST(float, vertex->get_normal() * transform));
+      gvw.set_data_type(InternalName::get_normal());
+      gvw.add_data3f(LCAST(float, vertex->get_normal() * transform));
+
+      EggMorphNormalList::const_iterator mni;
+      for (mni = vertex->_dnormals.begin(); mni != vertex->_dnormals.end(); ++mni) {
+        const EggMorphNormal &morph = (*mni);
+        CPT(InternalName) delta_name = 
+          InternalName::get_morph(InternalName::get_normal(), morph.get_name());
+        gvw.set_data_type(delta_name);
+        gvw.add_data3f(LCAST(float, morph.get_offset() * transform));
+      }
     }
 
     if (vertex->has_color()) {
-      gvi.set_data_type(InternalName::get_color());
-      gvi.add_data4f(vertex->get_color());
+      gvw.set_data_type(InternalName::get_color());
+      gvw.add_data4f(vertex->get_color());
+
+      EggMorphColorList::const_iterator mci;
+      for (mci = vertex->_drgbas.begin(); mci != vertex->_drgbas.end(); ++mci) {
+        const EggMorphColor &morph = (*mci);
+        CPT(InternalName) delta_name = 
+          InternalName::get_morph(InternalName::get_color(), morph.get_name());
+        gvw.set_data_type(delta_name);
+        gvw.add_data4f(morph.get_offset());
+      }
     }
 
     EggVertex::const_uv_iterator uvi;
@@ -2014,7 +2103,7 @@ make_vertex_data(const EggRenderState *render_state,
         name = string();
       }
       PT(InternalName) iname = InternalName::get_texcoord_name(name);
-      gvi.set_data_type(iname);
+      gvw.set_data_type(iname);
 
       BakeInUVs::const_iterator buv = render_state->_bake_in_uvs.find(iname);
       if (buv != render_state->_bake_in_uvs.end()) {
@@ -2022,7 +2111,16 @@ make_vertex_data(const EggRenderState *render_state,
         uv = uv * (*buv).second->get_transform();
       }
 
-      gvi.set_data2f(LCAST(float, uv));
+      gvw.set_data2f(LCAST(float, uv));
+
+      EggMorphTexCoordList::const_iterator mti;
+      for (mti = egg_uv->_duvs.begin(); mti != egg_uv->_duvs.end(); ++mti) {
+        const EggMorphTexCoord &morph = (*mti);
+        CPT(InternalName) delta_name = 
+          InternalName::get_morph(iname, morph.get_name());
+        gvw.set_data_type(delta_name);
+        gvw.add_data2f(LCAST(float, morph.get_offset()));
+      }
     }
 
     if (is_dynamic) {
@@ -2040,8 +2138,8 @@ make_vertex_data(const EggRenderState *render_state,
       blend.normalize_weights();
 
       int palette_index = blend_palette->add_blend(blend);
-      gvi.set_data_type(InternalName::get_transform_blend());
-      gvi.set_data1i(palette_index);
+      gvw.set_data_type(InternalName::get_transform_blend());
+      gvw.set_data1i(palette_index);
     }
   }
 
@@ -2052,6 +2150,26 @@ make_vertex_data(const EggRenderState *render_state,
   return vertex_data;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggLoader::record_morph
+//       Access: Private
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void EggLoader::
+record_morph(qpGeomVertexArrayFormat *array_format,
+             CharacterMaker *character_maker,
+             const string &morph_name, InternalName *data_type_name,
+             int num_components) {
+  CPT(InternalName) slider_name = InternalName::make(morph_name);
+  CPT(InternalName) delta_name = 
+    InternalName::get_morph(data_type_name, morph_name);
+  if (!array_format->has_data_type(delta_name)) {
+    array_format->add_data_type
+      (delta_name, num_components,
+       qpGeomVertexDataType::NT_float32, qpGeomVertexDataType::C_morph_delta);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: EggLoader::make_primitive
 //       Access: Private

+ 5 - 0
panda/src/egg2pg/eggLoader.h

@@ -146,6 +146,11 @@ private:
   (const EggRenderState *render_state, EggVertexPool *vertex_pool, 
    const LMatrix4d &transform, bool is_dynamic, 
    CharacterMaker *character_maker);
+  void record_morph
+  (qpGeomVertexArrayFormat *array_format,
+   CharacterMaker *character_maker, const string &morph_name, 
+   InternalName *data_type_name, int num_components);
+
   void make_primitive(const EggRenderState *render_state, 
                       EggPrimitive *egg_prim, Primitives &primitives);
 

+ 13 - 0
panda/src/gobj/internalName.I

@@ -191,6 +191,19 @@ get_transform_blend() {
   return _transform_blend;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: InternalName::get_morph
+//       Access: Published, Static
+//  Description: Returns an InternalName suitable for defining the
+//               morph deltas in the GeomVertexData to apply to the
+//               indicated data type name, using the named slider.
+////////////////////////////////////////////////////////////////////
+INLINE PT(InternalName) InternalName::
+get_morph(InternalName *data_type, const string &slider) {
+  // Returns data_type.morph.slider
+  return data_type->append("morph")->append(slider);
+}
+
 INLINE ostream &
 operator << (ostream &out, const InternalName &tcn) {
   tcn.output(out);

+ 1 - 0
panda/src/gobj/internalName.h

@@ -72,6 +72,7 @@ PUBLISHED:
   INLINE static PT(InternalName) get_texcoord_name(const string &name);
   INLINE static PT(InternalName) get_color();
   INLINE static PT(InternalName) get_transform_blend();
+  INLINE static PT(InternalName) get_morph(InternalName *data_type, const string &slider);
 
 private:
   PT(InternalName) _parent;

+ 11 - 0
panda/src/gobj/qpgeomVertexArrayFormat.I

@@ -102,6 +102,17 @@ get_data_type(int i) const {
   return _data_types[i];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexArrayFormat::has_data_type
+//       Access: Published
+//  Description: Returns true if the format has the named data type,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexArrayFormat::
+has_data_type(const InternalName *name) const {
+  return (get_data_type(name) != (qpGeomVertexDataType *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexArrayFormat::consider_sort_data_types
 //       Access: Private

+ 1 - 0
panda/src/gobj/qpgeomVertexArrayFormat.h

@@ -106,6 +106,7 @@ PUBLISHED:
 
   const qpGeomVertexDataType *get_data_type(const InternalName *name) const;
   const qpGeomVertexDataType *get_data_type(int start_byte, int num_bytes) const;
+  INLINE bool has_data_type(const InternalName *name) const;
 
   bool is_data_subset_of(const qpGeomVertexArrayFormat &other) const;
 

+ 11 - 0
panda/src/gobj/qpgeomVertexFormat.I

@@ -93,6 +93,17 @@ get_array(int array) const {
   return _arrays[array];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: qpGeomVertexFormat::has_data_type
+//       Access: Published
+//  Description: Returns true if the format has the named data type,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool qpGeomVertexFormat::
+has_data_type(const InternalName *name) const {
+  return (get_data_type(name) != (qpGeomVertexDataType *)NULL);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: qpGeomVertexFormat::get_num_morphs
 //       Access: Published

+ 1 - 0
panda/src/gobj/qpgeomVertexFormat.h

@@ -81,6 +81,7 @@ PUBLISHED:
 
   int get_array_with(const InternalName *name) const;
   const qpGeomVertexDataType *get_data_type(const InternalName *name) const;
+  INLINE bool has_data_type(const InternalName *name) const;
 
   void remove_data_type(const InternalName *name);
 

+ 22 - 0
panda/src/gobj/sliderTable.I

@@ -77,6 +77,28 @@ get_slider(const InternalName *name) const {
   return NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SliderTable::has_slider
+//       Access: Published
+//  Description: Returns true if the table has a slider by the
+//               indicated name, false otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool SliderTable::
+has_slider(const InternalName *name) const {
+  return (get_slider(name) != (VertexSlider *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SliderTable::is_empty
+//       Access: Published
+//  Description: Returns true if the table has no sliders, false if it
+//               has at least one.
+////////////////////////////////////////////////////////////////////
+INLINE bool SliderTable::
+is_empty() const {
+  return _sliders.empty();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SliderTable::get_modified
 //       Access: Published

+ 2 - 0
panda/src/gobj/sliderTable.h

@@ -56,6 +56,8 @@ PUBLISHED:
   INLINE static CPT(SliderTable) register_table(SliderTable *table);
 
   INLINE const VertexSlider *get_slider(const InternalName *name) const;
+  INLINE bool has_slider(const InternalName *name) const;
+  INLINE bool is_empty() const;
   INLINE UpdateSeq get_modified() const;
 
   void remove_slider(const InternalName *name);