瀏覽代碼

fix some bam issues

David Rose 20 年之前
父節點
當前提交
c7d4e746fa

+ 36 - 0
panda/src/char/character.I

@@ -62,6 +62,42 @@ get_part(int n) const {
   return _parts[n];
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Character::find_joint
+//       Access: Published
+//  Description: Returns a pointer to the joint with the given name,
+//               if there is such a joint, or NULL if there is no such
+//               joint.  This will not return a pointer to a slider.
+////////////////////////////////////////////////////////////////////
+INLINE CharacterJoint *Character::
+find_joint(const string &name) const {
+  PartGroup *part = get_bundle()->find_child(name);
+  if (part != (PartGroup *)NULL &&
+      part->is_of_type(CharacterJoint::get_class_type())) {
+    return DCAST(CharacterJoint, part);
+  }
+
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Character::find_slider
+//       Access: Published
+//  Description: Returns a pointer to the slider with the given name,
+//               if there is such a slider, or NULL if there is no such
+//               slider.  This will not return a pointer to a joint.
+////////////////////////////////////////////////////////////////////
+INLINE CharacterSlider *Character::
+find_slider(const string &name) const {
+  PartGroup *part = get_bundle()->find_child(name);
+  if (part != (PartGroup *)NULL &&
+      part->is_of_type(CharacterSlider::get_class_type())) {
+    return DCAST(CharacterSlider, part);
+  }
+
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Character::write_parts
 //       Access: Published

+ 152 - 35
panda/src/char/character.cxx

@@ -377,49 +377,69 @@ r_copy_char(PandaNode *dest, const PandaNode *source,
 ////////////////////////////////////////////////////////////////////
 PT(Geom) Character::
 copy_geom(const Geom *source, const Character *from) {
-  GeomBindType bind;
-  PTA_ushort index;
+  if (source->is_of_type(qpGeom::get_class_type())) {
+    CPT(qpGeom) qpsource = DCAST(qpGeom, source);
+    CPT(qpGeomVertexFormat) format = qpsource->get_vertex_data()->get_format();
+    if (format->get_animation().get_animation_type() ==
+        qpGeomVertexAnimationSpec::AT_none) {
+      // Not animated, so never mind.
+      return (Geom *)source;
+    }
 
-  PTA_Vertexf coords;
-  PTA_Normalf norms;
-  PTA_Colorf colors;
-  PTA_TexCoordf texcoords;
+    PT(qpGeom) dest = new qpGeom(*qpsource);
+    PT(qpGeomVertexData) vdata = dest->modify_vertex_data();
 
-  PT(Geom) dest = (Geom *)source;
+    vdata->set_transform_palette(redirect_transform_palette(vdata->get_transform_palette()));
+    vdata->set_transform_blend_palette(redirect_transform_blend_palette(vdata->get_transform_blend_palette()));
+    vdata->set_slider_table(redirect_slider_table(vdata->get_slider_table()));
 
-  source->get_coords(coords, index);
-  if ((coords != (void *)NULL) && (coords == (from->_cv._coords))) {
-    if (dest == source) {
-      dest = source->make_copy();
-    }
-    dest->set_coords(_cv._coords, index);
-  }
+    return dest.p();
 
-  source->get_normals(norms, bind, index);
-  if (bind != G_OFF && norms == from->_cv._norms) {
-    if (dest == source) {
-      dest = source->make_copy();
+  } else {
+    GeomBindType bind;
+    PTA_ushort index;
+
+    PTA_Vertexf coords;
+    PTA_Normalf norms;
+    PTA_Colorf colors;
+    PTA_TexCoordf texcoords;
+    
+    PT(Geom) dest = (Geom *)source;
+    
+    source->get_coords(coords, index);
+    if ((coords != (void *)NULL) && (coords == (from->_cv._coords))) {
+      if (dest == source) {
+        dest = source->make_copy();
+      }
+      dest->set_coords(_cv._coords, index);
     }
-    dest->set_normals(_cv._norms, bind, index);
-  }
-
-  source->get_colors(colors, bind, index);
-  if (bind != G_OFF && colors == from->_cv._colors) {
-    if (dest == source) {
-      dest = source->make_copy();
+    
+    source->get_normals(norms, bind, index);
+    if (bind != G_OFF && norms == from->_cv._norms) {
+      if (dest == source) {
+        dest = source->make_copy();
+      }
+      dest->set_normals(_cv._norms, bind, index);
     }
-    dest->set_colors(_cv._colors, bind, index);
-  }
-
-  source->get_texcoords(texcoords, bind, index);
-  if (bind != G_OFF && texcoords == from->_cv._texcoords) {
-    if (dest == source) {
-      dest = source->make_copy();
+    
+    source->get_colors(colors, bind, index);
+    if (bind != G_OFF && colors == from->_cv._colors) {
+      if (dest == source) {
+        dest = source->make_copy();
+      }
+      dest->set_colors(_cv._colors, bind, index);
     }
-    dest->set_texcoords(_cv._texcoords, bind, index);
+    
+    source->get_texcoords(texcoords, bind, index);
+    if (bind != G_OFF && texcoords == from->_cv._texcoords) {
+      if (dest == source) {
+        dest = source->make_copy();
+      }
+      dest->set_texcoords(_cv._texcoords, bind, index);
+    }
+    
+    return dest;
   }
-
-  return dest;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -478,6 +498,103 @@ copy_node_pointers(const Character *from, const Character::NodeMap &node_map) {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Character::redirect_transform_palette
+//       Access: Public
+//  Description: Creates a new TransformPalette, similar to the
+//               indicated one, with the joint and slider pointers
+//               redirected into this object.
+////////////////////////////////////////////////////////////////////
+CPT(TransformPalette) Character::
+redirect_transform_palette(const TransformPalette *source) {
+  if (source == (TransformPalette *)NULL) {
+    return NULL;
+  }
+
+  PT(TransformPalette) dest = new TransformPalette(*source);
+
+  int num_transforms = dest->get_num_transforms();
+  for (int i = 0; i < num_transforms; ++i) {
+    const VertexTransform *vt = dest->get_transform(i);
+    if (vt->is_of_type(JointVertexTransform::get_class_type())) {
+      const JointVertexTransform *jvt = DCAST(JointVertexTransform, vt);
+      CharacterJoint *joint = find_joint(jvt->get_joint()->get_name());
+      if (joint != (CharacterJoint *)NULL) {
+        CPT(JointVertexTransform) new_jvt = new JointVertexTransform(joint);
+        dest->set_transform(i, new_jvt);
+      }
+    }
+  }
+
+  return TransformPalette::register_palette(dest);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Character::redirect_transform_blend_palette
+//       Access: Public
+//  Description: Creates a new TransformBlendPalette, similar to the
+//               indicated one, with the joint and slider pointers
+//               redirected into this object.
+////////////////////////////////////////////////////////////////////
+CPT(TransformBlendPalette) Character::
+redirect_transform_blend_palette(const TransformBlendPalette *source) {
+  if (source == (TransformBlendPalette *)NULL) {
+    return NULL;
+  }
+
+  PT(TransformBlendPalette) dest = new TransformBlendPalette(*source);
+
+  int num_blends = dest->get_num_blends();
+  for (int i = 0; i < num_blends; ++i) {
+    TransformBlend blend = dest->get_blend(i);
+    int num_transforms = blend.get_num_transforms();
+    for (int j = 0; j < num_transforms; ++j) {
+      const VertexTransform *vt = blend.get_transform(j);
+      if (vt->is_of_type(JointVertexTransform::get_class_type())) {
+        const JointVertexTransform *jvt = DCAST(JointVertexTransform, vt);
+        CharacterJoint *joint = find_joint(jvt->get_joint()->get_name());
+        if (joint != (CharacterJoint *)NULL) {
+          CPT(JointVertexTransform) new_jvt = new JointVertexTransform(joint);
+          blend.set_transform(j, new_jvt);
+        }
+      }
+    }
+    dest->set_blend(i, blend);
+  }
+
+  return dest;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: Character::redirect_slider_table
+//       Access: Public
+//  Description: Creates a new SliderTable, similar to the
+//               indicated one, with the joint and slider pointers
+//               redirected into this object.
+////////////////////////////////////////////////////////////////////
+CPT(SliderTable) Character::
+redirect_slider_table(const SliderTable *source) {
+  if (source == (SliderTable *)NULL) {
+    return NULL;
+  }
+
+  PT(SliderTable) dest = new SliderTable(*source);
+
+  int num_sliders = dest->get_num_sliders();
+  for (int i = 0; i < num_sliders; ++i) {
+    const VertexSlider *vs = dest->get_slider(i);
+    if (vs->is_of_type(CharacterVertexSlider::get_class_type())) {
+      const CharacterVertexSlider *cvs = DCAST(CharacterVertexSlider, vs);
+      CharacterSlider *slider = find_slider(cvs->get_char_slider()->get_name());
+      if (slider != (CharacterSlider *)NULL) {
+        CPT(CharacterVertexSlider) new_cvs = new CharacterVertexSlider(slider);
+        dest->set_slider(i, new_cvs);
+      }
+    }
+  }
+
+  return SliderTable::register_table(dest);
+}
 
 ////////////////////////////////////////////////////////////////////
 //     Function: Character::register_with_read_factory

+ 11 - 1
panda/src/char/character.h

@@ -22,12 +22,16 @@
 #include "pandabase.h"
 
 #include "computedVertices.h"
-
+#include "characterJoint.h"
+#include "characterSlider.h"
 #include "partBundleNode.h"
 #include "vector_PartGroupStar.h"
 #include "pointerTo.h"
 #include "geom.h"
 #include "pStatCollector.h"
+#include "transformPalette.h"
+#include "transformBlendPalette.h"
+#include "sliderTable.h"
 
 class CharacterJointBundle;
 class ComputedVertices;
@@ -59,6 +63,9 @@ PUBLISHED:
   INLINE int get_num_parts() const;
   INLINE PartGroup *get_part(int n) const;
 
+  INLINE CharacterJoint *find_joint(const string &name) const;
+  INLINE CharacterSlider *find_slider(const string &name) const;
+
   INLINE void write_parts(ostream &out) const;
   INLINE void write_part_values(ostream &out) const;
 
@@ -77,6 +84,9 @@ private:
                    const Character *from, NodeMap &node_map);
   PT(Geom) copy_geom(const Geom *source, const Character *from);
   void copy_node_pointers(const Character *from, const NodeMap &node_map);
+  CPT(TransformPalette) redirect_transform_palette(const TransformPalette *source);
+  CPT(TransformBlendPalette) redirect_transform_blend_palette(const TransformBlendPalette *source);
+  CPT(SliderTable) redirect_slider_table(const SliderTable *source);
 
   // These are the actual dynamic vertex pools for this Character's
   // ComputedVertices--the vertices that it will recompute each frame

+ 7 - 4
panda/src/egg2pg/characterMaker.cxx

@@ -168,12 +168,14 @@ part_to_node(PartGroup *part, const string &name) const {
     // GeomNode.  Look for a child of this node.  If it doesn't have a
     // child yet, add a GeomNode and return it.  Otherwise, if it
     // already has a child, return that.
-    if (node->is_geom_node() && node->get_name() == name) {
+    if (node->is_geom_node() && 
+        (name.empty() || node->get_name() == name)) {
       return node;
     }
     for (int i = 0; i < node->get_num_children(); i++) {
       PandaNode *child = node->get_child(i);
-      if (child->is_geom_node() && child->get_name() == name) {
+      if (child->is_geom_node() && 
+          (name.empty() || child->get_name() == name)) {
         return child;
       }
     }
@@ -683,8 +685,9 @@ determine_bin_home(EggBin *egg_bin) {
     CharacterJoint *joint;
     DCAST_INTO_R(joint, egg_to_part(egg_group), home);
     egg_group->set_dcs_type(EggGroup::DC_default);
-    PT(GeomNode) geom_node = new GeomNode(egg_group->get_name());
-    joint->_geom_node = geom_node.p();
+
+    PT(PandaNode) geom_node = new PandaNode(egg_group->get_name());
+    joint->_geom_node = geom_node;
   }
 
   return home;

+ 2 - 0
panda/src/gobj/qpgeomVertexData.I

@@ -430,7 +430,9 @@ CData() {
 INLINE qpGeomVertexData::CData::
 CData(const qpGeomVertexData::CData &copy) :
   _arrays(copy._arrays),
+  _transform_palette(copy._transform_palette),
   _transform_blend_palette(copy._transform_blend_palette),
+  _slider_table(copy._slider_table),
   _animated_vertices(copy._animated_vertices),
   _animated_vertices_modified(copy._animated_vertices_modified),
   _modified(copy._modified)

+ 1 - 1
panda/src/gobj/qpgeomVertexData.cxx

@@ -1174,7 +1174,7 @@ update_animated_vertices(qpGeomVertexData::CDWriter &cdata, bool from_app) {
     int num_morphs = _format->get_num_morphs();
     for (int mi = 0; mi < num_morphs; mi++) {
       CPT(InternalName) slider_name = _format->get_morph_slider(mi);
-      const VertexSlider *slider = table->get_slider(slider_name);
+      const VertexSlider *slider = table->find_slider(slider_name);
       if (slider != (VertexSlider *)NULL) {
         float slider_value = slider->get_slider();
         if (slider_value != 0.0f) {

+ 27 - 6
panda/src/gobj/sliderTable.I

@@ -61,18 +61,39 @@ register_table(const SliderTable *table) {
   return table;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: SliderTable::get_num_sliders
+//       Access: Published
+//  Description: Returns the number of sliders in the palette.
+////////////////////////////////////////////////////////////////////
+INLINE int SliderTable::
+get_num_sliders() const {
+  return _sliders.size();
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SliderTable::get_slider
 //       Access: Published
+//  Description: Returns the nth slider in the palette.
+////////////////////////////////////////////////////////////////////
+INLINE const VertexSlider *SliderTable::
+get_slider(int n) const {
+  nassertr(n >= 0 && n < (int)_sliders.size(), NULL);
+  return _sliders[n];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SliderTable::find_slider
+//       Access: Published
 //  Description: Returns the slider with the indicated name, or NULL
 //               if no slider in the table has that name.
 ////////////////////////////////////////////////////////////////////
 INLINE const VertexSlider *SliderTable::
-get_slider(const InternalName *name) const {
-  Sliders::const_iterator si;
-  si = _sliders.find(name);
-  if (si != _sliders.end()) {
-    return (*si).second;
+find_slider(const InternalName *name) const {
+  SlidersByName::const_iterator sni;
+  sni = _sliders_by_name.find(name);
+  if (sni != _sliders_by_name.end()) {
+    return (*sni).second;
   }
   return NULL;
 }
@@ -85,7 +106,7 @@ get_slider(const InternalName *name) const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool SliderTable::
 has_slider(const InternalName *name) const {
-  return (get_slider(name) != (VertexSlider *)NULL);
+  return (find_slider(name) != (VertexSlider *)NULL);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 71 - 23
panda/src/gobj/sliderTable.cxx

@@ -41,7 +41,8 @@ SliderTable() :
 SliderTable::
 SliderTable(const SliderTable &copy) :
   _is_registered(false),
-  _sliders(copy._sliders)
+  _sliders(copy._sliders),
+  _sliders_by_name(copy._sliders_by_name)
 {
 }
 
@@ -54,6 +55,7 @@ void SliderTable::
 operator = (const SliderTable &copy) {
   nassertv(!_is_registered);
   _sliders = copy._sliders;
+  _sliders_by_name = copy._sliders_by_name;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -69,33 +71,73 @@ SliderTable::
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: SliderTable::remove_slider
+//     Function: SliderTable::set_slider
 //       Access: Published
-//  Description: Removes the named slider.  Only valid for
+//  Description: Replaces the nth slider.  Only valid for
 //               unregistered tables.
 ////////////////////////////////////////////////////////////////////
 void SliderTable::
-remove_slider(const InternalName *name) {
+set_slider(int n, const VertexSlider *slider) {
   nassertv(!_is_registered);
+  nassertv(n >= 0 && n < (int)_sliders.size());
 
-  Sliders::iterator si = _sliders.find(name);
-  if (si != _sliders.end()) {
-    _sliders.erase(si);
+  if (_sliders[n]->get_name() != slider->get_name()) {
+    // Not allowed to move a slider this way.
+    nassertv(!has_slider(slider->get_name()));
   }
+
+  _sliders[n] = slider;
+  _sliders_by_name[slider->get_name()] = slider;
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: SliderTable::add_slider
+//     Function: SliderTable::remove_slider
 //       Access: Published
-//  Description: Adds a new slider to the table, or replaces an
-//               existing slider with the same name.  Only valid for
+//  Description: Removes the nth slider.  Only valid for
 //               unregistered tables.
 ////////////////////////////////////////////////////////////////////
 void SliderTable::
-add_slider(VertexSlider *slider) {
+remove_slider(int n) {
   nassertv(!_is_registered);
+  nassertv(n >= 0 && n < (int)_sliders.size());
+
+  SlidersByName::iterator si = _sliders_by_name.find(_sliders[n]->get_name());
+  nassertv(si != _sliders_by_name.end());
+  _sliders_by_name.erase(si);
 
-  _sliders[slider->get_name()] = slider;
+  _sliders.erase(_sliders.begin() + n);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: SliderTable::add_slider
+//       Access: Published
+//  Description: Adds a new slider to the table, or replaces an
+//               existing slider with the same name, and returns the
+//               index number of the new slider.  Only valid for
+//               unregistered tables.
+////////////////////////////////////////////////////////////////////
+int SliderTable::
+add_slider(const VertexSlider *slider) {
+  nassertr(!_is_registered, -1);
+
+  SlidersByName::iterator sni = _sliders_by_name.find(slider->get_name());
+  if (sni != _sliders_by_name.end()) {
+    // We've already got a slider with this name; replace it.
+    CPT(VertexSlider) orig_slider = (*sni).second;
+    Sliders::iterator si = find(_sliders.begin(), _sliders.end(), orig_slider);
+    nassertr(si != _sliders.end(), -1);
+    (*si) = slider;
+    (*sni).second = slider;
+    
+    return si - _sliders.begin();
+  }
+
+  // This is the first slider with this name.
+  int new_index = (int)_sliders.size();
+  _sliders.push_back(slider);
+  _sliders_by_name[slider->get_name()] = slider;
+
+  return new_index;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -105,9 +147,8 @@ add_slider(VertexSlider *slider) {
 ////////////////////////////////////////////////////////////////////
 void SliderTable::
 write(ostream &out) const {
-  Sliders::const_iterator si;
-  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
-    out << *(*si).second << "\n";
+  for (size_t i = 0; i < _sliders.size(); ++i) {
+    out << i << ". " << *_sliders[i] << "\n";
   }
 }
 
@@ -122,7 +163,8 @@ do_register() {
 
   Sliders::iterator si;
   for (si = _sliders.begin(); si != _sliders.end(); ++si) {
-    bool inserted = (*si).second->_tables.insert(this).second;
+    const VertexSlider *slider = (*si);
+    bool inserted = ((VertexSlider *)slider)->_tables.insert(this).second;
     nassertv(inserted);
   }
   _is_registered = true;
@@ -140,7 +182,8 @@ do_unregister() {
 
   Sliders::iterator si;
   for (si = _sliders.begin(); si != _sliders.end(); ++si) {
-    (*si).second->_tables.erase(this);
+    const VertexSlider *slider = (*si);
+    ((VertexSlider *)slider)->_tables.erase(this);
   }
   _is_registered = false;
 }
@@ -169,8 +212,8 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   dg.add_uint16(_sliders.size());
   Sliders::const_iterator si;
   for (si = _sliders.begin(); si != _sliders.end(); ++si) {
-    manager->write_pointer(dg, (*si).first);
-    manager->write_pointer(dg, (*si).second);
+    manager->write_pointer(dg, (*si)->get_name());
+    manager->write_pointer(dg, (*si));
   }
 
   manager->write_cdata(dg, _cycler);
@@ -187,11 +230,14 @@ int SliderTable::
 complete_pointers(TypedWritable **p_list, BamReader *manager) {
   int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager);
 
-  for (size_t i = 0; i < _num_sliders; ++i) {
+  Sliders::iterator si;
+  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
     CPT(InternalName) name = DCAST(InternalName, p_list[pi++]);
     PT(VertexSlider) slider = DCAST(VertexSlider, p_list[pi++]);
 
-    bool inserted = _sliders.insert(Sliders::value_type(name, slider)).second;
+    (*si) = slider;
+
+    bool inserted = _sliders_by_name.insert(SlidersByName::value_type(name, slider)).second;
     nassertr(inserted, pi);
   }
 
@@ -229,10 +275,12 @@ void SliderTable::
 fillin(DatagramIterator &scan, BamReader *manager) {
   TypedWritable::fillin(scan, manager);
 
-  _num_sliders = scan.get_uint16();
-  for (size_t i = 0; i < _num_sliders; ++i) {
+  size_t num_sliders = scan.get_uint16();
+  _sliders.reserve(num_sliders);
+  for (size_t i = 0; i < num_sliders; ++i) {
     manager->read_pointer(scan);
     manager->read_pointer(scan);
+    _sliders.push_back(NULL);
   }
 
   manager->read_cdata(scan, _cycler);

+ 10 - 6
panda/src/gobj/sliderTable.h

@@ -55,13 +55,17 @@ PUBLISHED:
   INLINE bool is_registered() const;
   INLINE static CPT(SliderTable) register_table(const SliderTable *table);
 
-  INLINE const VertexSlider *get_slider(const InternalName *name) const;
+  INLINE int get_num_sliders() const;
+  INLINE const VertexSlider *get_slider(int n) const;
+
+  INLINE const VertexSlider *find_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);
-  void add_slider(VertexSlider *slider);
+  void set_slider(int n, const VertexSlider *slider);
+  void remove_slider(int n);
+  int add_slider(const VertexSlider *slider);
 
   void write(ostream &out) const;
 
@@ -73,11 +77,11 @@ private:
 private:
   bool _is_registered;
 
-  typedef pmap< CPT(InternalName), PT(VertexSlider) > Sliders;
+  typedef pvector< CPT(VertexSlider) > Sliders;
   Sliders _sliders;
 
-  // This is only filled in while reading from the bam stream.
-  size_t _num_sliders;
+  typedef pmap< CPT(InternalName), const VertexSlider *> SlidersByName;
+  SlidersByName _sliders_by_name;
 
   // This is the data that must be cycled between pipeline stages.
   class EXPCL_PANDA CData : public CycleData {

+ 24 - 0
panda/src/gobj/transformBlend.I

@@ -177,6 +177,30 @@ get_weight(int n) const {
   return _entries[n]._weight;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: TransformBlend::set_transform
+//       Access: Published
+//  Description: Replaces the nth transform stored in the blend
+//               object.
+////////////////////////////////////////////////////////////////////
+INLINE void TransformBlend::
+set_transform(int n, const VertexTransform *transform) {
+  nassertv(n >= 0 && n < (int)_entries.size());
+  _entries[n]._transform = transform;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TransformBlend::set_weight
+//       Access: Published
+//  Description: Replaces the weight associated with the nth transform
+//               stored in the blend object.
+////////////////////////////////////////////////////////////////////
+INLINE void TransformBlend::
+set_weight(int n, float weight) {
+  nassertv(n >= 0 && n < (int)_entries.size());
+  _entries[n]._weight = weight;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: TransformBlend::update_blend
 //       Access: Published

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

@@ -69,6 +69,8 @@ PUBLISHED:
   INLINE int get_num_transforms() const;
   INLINE const VertexTransform *get_transform(int n) const;
   INLINE float get_weight(int n) const;
+  INLINE void set_transform(int n, const VertexTransform *transform);
+  INLINE void set_weight(int n, float weight);
 
   INLINE void update_blend() const;
 

+ 29 - 27
panda/src/particlesystem/spriteParticleRenderer.cxx

@@ -152,33 +152,35 @@ set_from_node(const NodePath &node_path, bool size_from_texels) {
     qpGeomVertexReader texcoord(qpgeom->get_vertex_data());
     qpGeomVertexReader vertex(qpgeom->get_vertex_data());
 
-    bool found_any = false;
-    for (int pi = 0; pi < qpgeom->get_num_primitives(); ++pi) {
-      const qpGeomPrimitive *primitive = qpgeom->get_primitive(pi);
-      for (int vi = 0; vi < primitive->get_num_vertices(); ++vi) {
-        int vert = primitive->get_vertex(vi);
-        texcoord.set_vertex(vert);
-        vertex.set_vertex(vert);
-
-        if (!found_any) {
-          min_uv = max_uv = texcoord.get_data2f();
-          min_xyz = max_xyz = vertex.get_data3f();
-
-        } else {
-          const LVecBase2f &uv = texcoord.get_data2f();
-          const LVecBase3f &xyz = vertex.get_data3f();
-
-          min_uv[0] = min(min_uv[0], uv[0]);
-          max_uv[0] = max(max_uv[0], uv[0]);
-          min_uv[1] = min(min_uv[1], uv[1]);
-          max_uv[1] = max(max_uv[1], uv[1]);
-
-          min_xyz[0] = min(min_xyz[0], xyz[0]);
-          max_xyz[0] = max(max_xyz[0], xyz[0]);
-          min_xyz[1] = min(min_xyz[1], xyz[1]);
-          max_xyz[1] = max(max_xyz[1], xyz[1]);
-          min_xyz[2] = min(min_xyz[2], xyz[2]);
-          max_xyz[2] = max(max_xyz[2], xyz[2]);
+    if (texcoord.has_column() && vertex.has_column()) {
+      bool found_any = false;
+      for (int pi = 0; pi < qpgeom->get_num_primitives(); ++pi) {
+        const qpGeomPrimitive *primitive = qpgeom->get_primitive(pi);
+        for (int vi = 0; vi < primitive->get_num_vertices(); ++vi) {
+          int vert = primitive->get_vertex(vi);
+          texcoord.set_vertex(vert);
+          vertex.set_vertex(vert);
+          
+          if (!found_any) {
+            min_uv = max_uv = texcoord.get_data2f();
+            min_xyz = max_xyz = vertex.get_data3f();
+            
+          } else {
+            const LVecBase2f &uv = texcoord.get_data2f();
+            const LVecBase3f &xyz = vertex.get_data3f();
+            
+            min_uv[0] = min(min_uv[0], uv[0]);
+            max_uv[0] = max(max_uv[0], uv[0]);
+            min_uv[1] = min(min_uv[1], uv[1]);
+            max_uv[1] = max(max_uv[1], uv[1]);
+            
+            min_xyz[0] = min(min_xyz[0], xyz[0]);
+            max_xyz[0] = max(max_xyz[0], xyz[0]);
+            min_xyz[1] = min(min_xyz[1], xyz[1]);
+            max_xyz[1] = max(max_xyz[1], xyz[1]);
+            min_xyz[2] = min(min_xyz[2], xyz[2]);
+            max_xyz[2] = max(max_xyz[2], xyz[2]);
+          }
         }
       }
     }