Procházet zdrojové kódy

pipeline BoundedObject

David Rose před 24 roky
rodič
revize
da79251b45
46 změnil soubory, kde provedl 296 přidání a 176 odebrání
  1. 8 5
      panda/src/collide/collisionNode.cxx
  2. 1 1
      panda/src/collide/collisionNode.h
  3. 3 3
      panda/src/collide/collisionPlane.cxx
  4. 1 1
      panda/src/collide/collisionPlane.h
  5. 6 4
      panda/src/collide/collisionPolygon.cxx
  6. 1 1
      panda/src/collide/collisionPolygon.h
  7. 2 2
      panda/src/collide/collisionRay.cxx
  8. 1 1
      panda/src/collide/collisionRay.h
  9. 7 5
      panda/src/collide/collisionSegment.cxx
  10. 1 1
      panda/src/collide/collisionSegment.h
  11. 7 5
      panda/src/collide/collisionSphere.cxx
  12. 1 1
      panda/src/collide/collisionSphere.h
  13. 6 4
      panda/src/gobj/geom.cxx
  14. 1 1
      panda/src/gobj/geom.h
  15. 85 28
      panda/src/graph/boundedObject.I
  16. 38 8
      panda/src/graph/boundedObject.cxx
  17. 26 9
      panda/src/graph/boundedObject.h
  18. 9 7
      panda/src/graph/nodeRelation.cxx
  19. 1 1
      panda/src/graph/nodeRelation.h
  20. 0 18
      panda/src/pgraph/Sources.pp
  21. 0 6
      panda/src/pgraph/pgraph_composite2.cxx
  22. 71 52
      panda/src/putil/Sources.pp
  23. 0 0
      panda/src/putil/cycleData.I
  24. 0 0
      panda/src/putil/cycleData.cxx
  25. 0 0
      panda/src/putil/cycleData.h
  26. 0 0
      panda/src/putil/cycleDataReader.I
  27. 0 0
      panda/src/putil/cycleDataReader.cxx
  28. 0 0
      panda/src/putil/cycleDataReader.h
  29. 0 0
      panda/src/putil/cycleDataWriter.I
  30. 0 0
      panda/src/putil/cycleDataWriter.cxx
  31. 0 0
      panda/src/putil/cycleDataWriter.h
  32. 0 0
      panda/src/putil/pipeline.I
  33. 0 0
      panda/src/putil/pipeline.cxx
  34. 0 0
      panda/src/putil/pipeline.h
  35. 0 0
      panda/src/putil/pipelineCycler.I
  36. 0 0
      panda/src/putil/pipelineCycler.cxx
  37. 0 0
      panda/src/putil/pipelineCycler.h
  38. 0 0
      panda/src/putil/pipelineCyclerBase.I
  39. 0 0
      panda/src/putil/pipelineCyclerBase.cxx
  40. 0 0
      panda/src/putil/pipelineCyclerBase.h
  41. 3 1
      panda/src/putil/putil_composite1.cxx
  42. 3 1
      panda/src/putil/putil_composite2.cxx
  43. 6 4
      panda/src/sgattrib/renderRelation.cxx
  44. 1 1
      panda/src/sgattrib/renderRelation.h
  45. 6 4
      panda/src/sgraph/geomNode.cxx
  46. 1 1
      panda/src/sgraph/geomNode.h

+ 8 - 5
panda/src/collide/collisionNode.cxx

@@ -209,11 +209,11 @@ output(ostream &out) const {
 //       Access: Protected, Virtual
 //  Description: Recomputes the dynamic bounding volume for this node.
 ////////////////////////////////////////////////////////////////////
-void CollisionNode::
+BoundingVolume *CollisionNode::
 recompute_bound() {
   // First, get ourselves a fresh, empty bounding volume.
-  BoundedObject::recompute_bound();
-  nassertv(_bound != (BoundingVolume *)NULL);
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume *)NULL, bound);
 
   // Now actually compute the bounding volume by putting it around all
   // of our solids' bounding volumes.
@@ -226,20 +226,23 @@ recompute_bound() {
 
   const BoundingVolume **child_begin = &child_volumes[0];
   const BoundingVolume **child_end = child_begin + child_volumes.size();
+
   bool success =
-    _bound->around(child_begin, child_end);
+    bound->around(child_begin, child_end);
 
 #ifdef NOTIFY_DEBUG
   if (!success) {
     collide_cat.error()
       << "Unable to generate bounding volume for " << *this << ":\n"
-      << "Cannot put " << _bound->get_type() << " around:\n";
+      << "Cannot put " << bound->get_type() << " around:\n";
     for (int i = 0; i < (int)child_volumes.size(); i++) {
       collide_cat.error(false)
         << "  " << *child_volumes[i] << "\n";
     }
   }
 #endif
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionNode.h

@@ -67,7 +67,7 @@ public:
   virtual void output(ostream &out) const;
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 private:
   CollideMask _from_collide_mask;

+ 3 - 3
panda/src/collide/collisionPlane.cxx

@@ -104,13 +104,13 @@ output(ostream &out) const {
 //       Access: Protected, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void CollisionPlane::
+BoundingVolume *CollisionPlane::
 recompute_bound() {
-  // Planes have an infinite bounding volume.
+  // Planes always have an infinite bounding volume.
   BoundedObject::recompute_bound();
   // Less than ideal: we throw away whatever we just allocated in
   // BoundedObject.
-  _bound = new OmniBoundingVolume;
+  return set_bound_ptr(new OmniBoundingVolume);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionPlane.h

@@ -59,7 +59,7 @@ PUBLISHED:
   INLINE const Planef &get_plane() const;
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
   virtual int

+ 6 - 4
panda/src/collide/collisionPolygon.cxx

@@ -202,13 +202,13 @@ output(ostream &out) const {
 //       Access: Protected, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void CollisionPolygon::
+BoundingVolume *CollisionPolygon::
 recompute_bound() {
   // First, get ourselves a fresh, empty bounding volume.
-  BoundedObject::recompute_bound();
-  assert(_bound != (BoundingVolume*)0L);
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume*)0L, bound);
 
-  GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, _bound);
+  GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
 
   // Now actually compute the bounding volume by putting it around all
   // of our vertices.
@@ -221,6 +221,8 @@ recompute_bound() {
   const LPoint3f *vertices_begin = &vertices[0];
   const LPoint3f *vertices_end = vertices_begin + vertices.size();
   gbv->around(vertices_begin, vertices_end);
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionPolygon.h

@@ -61,7 +61,7 @@ public:
 
 protected:
   INLINE CollisionPolygon(void);
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
   virtual int

+ 2 - 2
panda/src/collide/collisionRay.cxx

@@ -125,12 +125,12 @@ set_from_lens(LensNode *camera, const LPoint2f &point) {
 //       Access: Protected, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void CollisionRay::
+BoundingVolume *CollisionRay::
 recompute_bound() {
   BoundedObject::recompute_bound();
   // Less than ideal: we throw away whatever we just allocated in
   // BoundedObject.
-  _bound = new BoundingLine(_origin, _origin + _direction);
+  return set_bound_ptr(new BoundingLine(_origin, _origin + _direction));
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionRay.h

@@ -67,7 +67,7 @@ PUBLISHED:
   INLINE bool set_from_lens(LensNode *camera, float px, float py);
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
   virtual void recompute_viz(Node *parent);

+ 7 - 5
panda/src/collide/collisionSegment.cxx

@@ -124,20 +124,22 @@ set_from_lens(LensNode *camera, const LPoint2f &point) {
 //       Access: Protected, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void CollisionSegment::
+BoundingVolume *CollisionSegment::
 recompute_bound() {
-  BoundedObject::recompute_bound();
+  BoundingVolume *bound = BoundedObject::recompute_bound();
 
-  if (_bound->is_of_type(GeometricBoundingVolume::get_class_type())) {
+  if (bound->is_of_type(GeometricBoundingVolume::get_class_type())) {
     GeometricBoundingVolume *gbound;
-    DCAST_INTO_V(gbound, _bound);
+    DCAST_INTO_R(gbound, bound, bound);
 
     // This makes the assumption that _a and _b are laid out
     // sequentially in memory.  It works because that's they way
     // they're defined in the class.
-    nassertv(&_a + 1 == &_b);
+    nassertr(&_a + 1 == &_b, bound);
     gbound->around(&_a, &_b + 1);
   }
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionSegment.h

@@ -70,7 +70,7 @@ PUBLISHED:
   INLINE bool set_from_lens(LensNode *camera, float px, float py);
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
   virtual void recompute_viz(Node *parent);

+ 7 - 5
panda/src/collide/collisionSphere.cxx

@@ -103,13 +103,15 @@ output(ostream &out) const {
 //       Access: Protected, Virtual
 //  Description:
 ////////////////////////////////////////////////////////////////////
-void CollisionSphere::
+BoundingVolume *CollisionSphere::
 recompute_bound() {
-  BoundedObject::recompute_bound();
-  nassertv(_bound != (BoundingVolume*)0L);
-  nassertv(!_center.is_nan() && !cnan(_radius));
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume*)0L, bound);
+  nassertr(!_center.is_nan() && !cnan(_radius), bound);
   BoundingSphere sphere(_center, _radius);
-  _bound->extend_by(&sphere);
+  bound->extend_by(&sphere);
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/collide/collisionSphere.h

@@ -56,7 +56,7 @@ PUBLISHED:
 
 protected:
   INLINE CollisionSphere(void);
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
   virtual int

+ 6 - 4
panda/src/gobj/geom.cxx

@@ -613,13 +613,13 @@ init() {
 //  Description: Recomputes the dynamic bounding volume for this Geom.
 //               This includes all of the vertices.
 ////////////////////////////////////////////////////////////////////
-void Geom::
+BoundingVolume *Geom::
 recompute_bound() {
   // First, get ourselves a fresh, empty bounding volume.
-  BoundedObject::recompute_bound();
-  assert(_bound != (BoundingVolume*)0L);
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume*)0L, bound);
 
-  GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, _bound);
+  GeometricBoundingVolume *gbv = DCAST(GeometricBoundingVolume, bound);
 
   // Now actually compute the bounding volume by putting it around all
   // of our vertices.
@@ -636,6 +636,8 @@ recompute_bound() {
   const LPoint3f *vertices_end = vertices_begin + vertices.size();
 
   gbv->around(vertices_begin, vertices_end);
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/gobj/geom.h

@@ -232,7 +232,7 @@ public:
 
 protected:
   void init();
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 protected:
 

+ 85 - 28
panda/src/graph/boundedObject.I

@@ -19,23 +19,17 @@
 #include <notify.h>
 
 ////////////////////////////////////////////////////////////////////
-//     Function: BoundedObject::is_bound_stale
-//       Access: Published
-//  Description: Returns true if the bound is currently marked stale
-//               and will be recomputed the next time get_bound() is
-//               called.
-//
-//               This function is defined up at the top of this file,
-//               because several of the inline functions below
-//               reference it.
+//     Function: BoundedObject::CData::Constructor
+//       Access: Public
+//  Description:
 ////////////////////////////////////////////////////////////////////
-INLINE_GRAPH bool BoundedObject::
-is_bound_stale() const {
-  return (_flags & F_bound_stale) != 0;
+INLINE_GRAPH BoundedObject::CData::
+CData() {
+  _bound_type = BoundedObject::BVT_dynamic_sphere;
+  _flags = F_bound_stale;
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::Constructor
 //       Access: Published
@@ -43,8 +37,6 @@ is_bound_stale() const {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH BoundedObject::
 BoundedObject() {
-  _bound_type = BVT_dynamic_sphere;
-  _flags = F_bound_stale;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -57,8 +49,9 @@ BoundedObject() {
 INLINE_GRAPH void BoundedObject::
 set_bound(BoundedObject::BoundingVolumeType type) {
   nassertv(type != BVT_static);
+  CDWriter cdata(_cycler);
   mark_bound_stale();
-  _bound_type = type;
+  cdata->_bound_type = type;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -70,10 +63,11 @@ set_bound(BoundedObject::BoundingVolumeType type) {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH void BoundedObject::
 set_bound(const BoundingVolume &bound) {
+  CDWriter cdata(_cycler);
   mark_bound_stale();
-  _bound_type = BVT_static;
-  _flags &= ~F_bound_stale;  
-  _bound = bound.make_copy();
+  cdata->_bound_type = BVT_static;
+  cdata->_flags &= ~F_bound_stale;  
+  cdata->_bound = bound.make_copy();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -88,12 +82,14 @@ set_bound(const BoundingVolume &bound) {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH const BoundingVolume &BoundedObject::
 get_bound() const {
-  if (_bound_type == BVT_static) {
-    ((BoundedObject *)this)->_flags &= ~F_bound_stale;
-  } else if (is_bound_stale() || _bound == (BoundingVolume *)NULL) {
+  CDReader cdata(_cycler);
+  if (cdata->_bound_type == BVT_static) {
+    CDWriter cdata_w(((BoundedObject *)this)->_cycler);
+    cdata_w->_flags &= ~F_bound_stale;
+  } else if (is_bound_stale() || cdata->_bound == (BoundingVolume *)NULL) {
     ((BoundedObject *)this)->recompute_bound();
   }
-  return *_bound;
+  return *cdata->_bound;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -111,7 +107,8 @@ mark_bound_stale() {
   if (is_bound_stale()) {
     return false;
   }
-  _flags |= F_bound_stale;
+  CDWriter cdata(_cycler);
+  cdata->_flags |= F_bound_stale;
   propagate_stale_bound();
 
   return true;
@@ -126,10 +123,29 @@ mark_bound_stale() {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH void BoundedObject::
 force_bound_stale() {
-  _flags |= F_bound_stale;
+  CDWriter cdata(_cycler);
+  cdata->_flags |= F_bound_stale;
   propagate_stale_bound();
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BoundedObject::is_bound_stale
+//       Access: Published
+//  Description: Returns true if the bound is currently marked stale
+//               and will be recomputed the next time get_bound() is
+//               called.
+//
+//               This function is defined up at the top of this file,
+//               because several of the inline functions below
+//               reference it.
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH bool BoundedObject::
+is_bound_stale() const {
+  CDReader cdata(_cycler);
+  return (cdata->_flags & F_bound_stale) != 0;
+}
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::set_final
 //       Access: Published
@@ -149,10 +165,11 @@ force_bound_stale() {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH void BoundedObject::
 set_final(bool flag) {
+  CDWriter cdata(_cycler);
   if (flag) {
-    _flags |= F_final;
+    cdata->_flags |= F_final;
   } else {
-    _flags &= ~F_final;
+    cdata->_flags &= ~F_final;
   }
 }
 
@@ -166,5 +183,45 @@ set_final(bool flag) {
 ////////////////////////////////////////////////////////////////////
 INLINE_GRAPH bool BoundedObject::
 is_final() const {
-  return (_flags & F_final) != 0;
+  CDReader cdata(_cycler);
+  return (cdata->_flags & F_final) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BoundedObject::get_bound_ptr
+//       Access: Protected
+//  Description: Returns the state of the _bound pointer.  To be used
+//               only internally by derived classes.
+//
+//               This returns a const pointer only; the bounding
+//               volume should not be modified directly, because that
+//               might interfere with pipelining.  Instead, create a
+//               new copy with make_copy(), modify the copy, and
+//               set_bound_ptr() with the copy.
+//
+//               Alternatively, if you have just called
+//               recompute_bound(), which is guaranteed to reset the
+//               pointer, just use the return value from that as a
+//               non-const BoundingVolume pointer.
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH const BoundingVolume *BoundedObject::
+get_bound_ptr() const {
+  CDReader cdata(_cycler);
+  return cdata->_bound;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BoundedObject::set_bound_ptr
+//       Access: Protected
+//  Description: Changes the _bound pointer.  To be used only
+//               internally by derived classes, usually in
+//               recompute_bound().  The return value is the same
+//               pointer passed in, as a convenience (it will now be
+//               reference counted).
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH BoundingVolume *BoundedObject::
+set_bound_ptr(BoundingVolume *bound) {
+  CDWriter cdata(_cycler);
+  cdata->_bound = bound;
+  return bound;
 }

+ 38 - 8
panda/src/graph/boundedObject.cxx

@@ -23,6 +23,19 @@
 
 TypeHandle BoundedObject::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: BoundedObject::CData::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+BoundedObject::CData::
+CData(const BoundedObject::CData &copy) :
+  _flags(copy._flags),
+  _bound_type(copy._bound_type),
+  _bound(copy._bound)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::Destructor
 //       Access: Public, Virtual
@@ -32,6 +45,16 @@ BoundedObject::
 ~BoundedObject() {
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BoundedObject::CData::make_copy
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+CycleData *BoundedObject::CData::
+make_copy() const {
+  return new CData(*this);
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BoundedObject::propagate_stale_bound
 //       Access: Protected, Virtual
@@ -49,22 +72,29 @@ propagate_stale_bound() {
 //  Description: Recomputes the dynamic bounding volume for this
 //               object.  The default behavior is the compute an empty
 //               bounding volume; this may be overridden to extend it
-//               to create a nonempty bounding volume.
+//               to create a nonempty bounding volume.  However, after
+//               calling this function, it is guaranteed that the
+//               _bound pointer will not be shared with any other
+//               stage of the pipeline, and this new pointer is
+//               returned.
 ////////////////////////////////////////////////////////////////////
-void BoundedObject::
+BoundingVolume *BoundedObject::
 recompute_bound() {
-  switch (_bound_type) {
+  CDWriter cdata(_cycler);
+  switch (cdata->_bound_type) {
   case BVT_dynamic_sphere:
-    _bound = new BoundingSphere;
+    cdata->_bound = new BoundingSphere;
     break;
 
   default:
     graph_cat.error()
-      << "Unexpected _bound_type: " << (int)_bound_type
+      << "Unexpected _bound_type: " << (int)cdata->_bound_type
       << " in BoundedObject::recompute_bound()\n";
-    _bound = NULL;
+    cdata->_bound = new BoundingSphere;
   }
 
-  _flags &= ~F_bound_stale;
-  // By default, the bound is empty.
+  cdata->_flags &= ~F_bound_stale;
+
+  // Now the _bound is new and empty.
+  return cdata->_bound;
 }

+ 26 - 9
panda/src/graph/boundedObject.h

@@ -19,12 +19,15 @@
 #ifndef BOUNDEDOBJECT_H
 #define BOUNDEDOBJECT_H
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 #include "boundingVolume.h"
-
-#include <typedObject.h>
-#include <pointerTo.h>
+#include "cycleData.h"
+#include "cycleDataReader.h"
+#include "cycleDataWriter.h"
+#include "pipelineCycler.h"
+#include "typedObject.h"
+#include "pointerTo.h"
 
 ////////////////////////////////////////////////////////////////////
 //       Class : BoundedObject
@@ -58,18 +61,32 @@ PUBLISHED:
 
 protected:
   virtual void propagate_stale_bound();
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
+
+  INLINE_GRAPH const BoundingVolume *get_bound_ptr() const;
+  INLINE_GRAPH BoundingVolume *set_bound_ptr(BoundingVolume *bound);
 
 private:
   enum Flags {
     F_bound_stale  = 0x0001,
     F_final        = 0x0002,
   };
-  int _flags;
-  BoundingVolumeType _bound_type;
 
-protected:
-  PT(BoundingVolume) _bound;
+  // This is the data that must be cycled between pipeline stages.
+  class EXPCL_PANDA CData : public CycleData {
+  public:
+    INLINE_GRAPH CData();
+    CData(const CData &copy);
+    virtual CycleData *make_copy() const;
+
+    int _flags;
+    BoundingVolumeType _bound_type;
+    PT(BoundingVolume) _bound;
+  };
+
+  PipelineCycler<CData> _cycler;
+  typedef CycleDataReader<CData> CDReader;
+  typedef CycleDataWriter<CData> CDWriter;
 
 public:
   static TypeHandle get_class_type() {

+ 9 - 7
panda/src/graph/nodeRelation.cxx

@@ -817,18 +817,18 @@ propagate_stale_bound() {
 //  Description: Recomputes the dynamic bounding volume for this arc
 //               (and all of its descendants).
 ////////////////////////////////////////////////////////////////////
-void NodeRelation::
+BoundingVolume *NodeRelation::
 recompute_bound() {
   // First, get ourselves a fresh, empty bounding volume.
-  BoundedObject::recompute_bound();
-  nassertv(_bound != (BoundingVolume*)NULL);
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume*)NULL, bound);
 
   // Now actually compute the bounding volume by putting it around all
   // of our child bounding volumes.
   pvector<const BoundingVolume *> child_volumes;
 
   Node *node = _child;
-  nassertv(node != (Node*)NULL);
+  nassertr(node != (Node*)NULL, bound);
 
   child_volumes.push_back(&node->get_bound());
 
@@ -841,21 +841,23 @@ recompute_bound() {
 
   const BoundingVolume **child_begin = &child_volumes[0];
   const BoundingVolume **child_end = child_begin + child_volumes.size();
-  bool success =
-    _bound->around(child_begin, child_end);
 
+  bool success =
+    bound->around(child_begin, child_end);
 
 #ifndef NDEBUG
   if (!success) {
     graph_cat.error()
       << "Unable to recompute bounding volume for " << *this << ":\n"
-      << "Cannot put " << _bound->get_type() << " around:\n";
+      << "Cannot put " << bound->get_type() << " around:\n";
     for (int i = 0; i < (int)child_volumes.size(); i++) {
       graph_cat.error(false)
         << "  " << *child_volumes[i] << "\n";
     }
   }
 #endif
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/graph/nodeRelation.h

@@ -211,7 +211,7 @@ public:
 
 protected:
   virtual void propagate_stale_bound();
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 PUBLISHED:
   INLINE_GRAPH static TypeHandle get_class_type();

+ 0 - 18
panda/src/pgraph/Sources.pp

@@ -20,17 +20,11 @@
     cullHandler.h \
     cullResult.h \
     qpcullTraverser.h qpcullTraverser.I \
-    cycleData.h cycleData.I \
-    cycleDataReader.h cycleDataReader.I \
-    cycleDataWriter.h cycleDataWriter.I \
     qpgeomNode.h qpgeomNode.I \
     qplensNode.h qplensNode.I \
     nodeChain.h nodeChain.I \
     nodeChainComponent.h nodeChainComponent.I \
     pandaNode.h pandaNode.I \
-    pipeline.h pipeline.I \
-    pipelineCycler.h pipelineCycler.I \
-    pipelineCyclerBase.h pipelineCyclerBase.I \
     renderAttrib.h renderAttrib.I \
     renderState.h renderState.I \
     textureAttrib.h textureAttrib.I \
@@ -53,17 +47,11 @@
     cullHandler.cxx \
     cullResult.cxx \
     qpcullTraverser.cxx \
-    cycleData.cxx \
-    cycleDataReader.cxx \
-    cycleDataWriter.cxx \
     qpgeomNode.cxx \
     qplensNode.cxx \
     nodeChain.cxx \
     nodeChainComponent.cxx \
     pandaNode.cxx \
-    pipeline.cxx \
-    pipelineCycler.cxx \
-    pipelineCyclerBase.cxx \
     renderAttrib.cxx \
     renderState.cxx \
     textureAttrib.cxx \
@@ -91,17 +79,11 @@
     cullHandler.h \
     cullResult.h \
     qpcullTraverser.h qpcullTraverser.I \
-    cycleData.h cycleData.I \
-    cycleDataReader.h cycleDataReader.I \
-    cycleDataWriter.h cycleDataWriter.I \
     qpgeomNode.h qpgeomNode.I \
     qplensNode.h qplensNode.I \
     nodeChain.h nodeChain.I \
     nodeChainComponent.h nodeChainComponent.I \
     pandaNode.h pandaNode.I \
-    pipeline.h pipeline.I \
-    pipelineCycler.h pipelineCycler.I \
-    pipelineCyclerBase.h pipelineCyclerBase.I \
     renderAttrib.h renderAttrib.I \
     renderState.h renderState.I \
     textureAttrib.h textureAttrib.I \

+ 0 - 6
panda/src/pgraph/pgraph_composite2.cxx

@@ -1,14 +1,8 @@
-#include "cycleData.cxx"
-#include "cycleDataReader.cxx"
-#include "cycleDataWriter.cxx"
 #include "qpgeomNode.cxx"
 #include "qplensNode.cxx"
 #include "nodeChain.cxx"
 #include "nodeChainComponent.cxx"
 #include "pandaNode.cxx"
-#include "pipeline.cxx"
-#include "pipelineCycler.cxx"
-#include "pipelineCyclerBase.cxx"
 #include "renderAttrib.cxx"
 #include "renderState.cxx"
 #include "test_pgraph.cxx"

+ 71 - 52
panda/src/putil/Sources.pp

@@ -1,5 +1,5 @@
 #define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
-                   dtoolutil:c dtoolbase:c dtool:m
+                  dtoolutil:c dtoolbase:c dtool:m
 #define LOCAL_LIBS express pandabase
 
 #begin lib_target
@@ -8,59 +8,72 @@
   #define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx   
   
   #define SOURCES \
-     bam.h bamReader.I bamReader.N bamReader.h bamReaderParam.I \
-     bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \
-     bitMask.h buttonEvent.I buttonEvent.h buttonHandle.I \
-     buttonHandle.h buttonRegistry.I buttonRegistry.h \
-     collideMask.h \
-     compareTo.I compareTo.h \
-     config_util.N config_util.h configurable.h \
-     factoryBase.I factoryBase.h \
-     factoryParam.I factoryParam.h factoryParams.I \
-     factoryParams.h \
-     firstOfPairCompare.I firstOfPairCompare.h \
-     firstOfPairLess.I firstOfPairLess.h \
-     globPattern.I globPattern.h \
-     globalPointerRegistry.I globalPointerRegistry.h \
-     indirectCompareNames.I indirectCompareNames.h \
-     indirectCompareTo.I indirectCompareTo.h \
-     indirectLess.I indirectLess.h \
-     ioPtaDatagramFloat.h ioPtaDatagramInt.h \
-     ioPtaDatagramShort.h keyboardButton.h lineStream.I \
-     lineStream.h lineStreamBuf.I lineStreamBuf.h \
-     modifierButtons.I modifierButtons.h mouseButton.h \
-     mouseData.h nameUniquifier.I nameUniquifier.h \
-     ordered_vector.h ordered_vector.I ordered_vector.T \
-     pta_double.h \
-     pta_float.h pta_int.h \
-     string_utils.I string_utils.N string_utils.h \
-     timedCycle.I timedCycle.h typedWritable.I \
-     typedWritable.h typedWritableReferenceCount.I \
-     typedWritableReferenceCount.h updateSeq.I updateSeq.h \
-     vector_double.h vector_float.h vector_typedWritable.h \
-     vector_ushort.h vector_writable.h \
-     writable.I writable.h writableConfigurable.h \
-     writableParam.I writableParam.h 
+    bam.h bamReader.I bamReader.N bamReader.h bamReaderParam.I \
+    bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \
+    bitMask.h buttonEvent.I buttonEvent.h buttonHandle.I \
+    buttonHandle.h buttonRegistry.I buttonRegistry.h \
+    collideMask.h \
+    compareTo.I compareTo.h \
+    config_util.N config_util.h configurable.h \
+    cycleData.h cycleData.I \
+    cycleDataReader.h cycleDataReader.I \
+    cycleDataWriter.h cycleDataWriter.I \
+    factoryBase.I factoryBase.h \
+    factoryParam.I factoryParam.h factoryParams.I \
+    factoryParams.h \
+    firstOfPairCompare.I firstOfPairCompare.h \
+    firstOfPairLess.I firstOfPairLess.h \
+    globPattern.I globPattern.h \
+    globalPointerRegistry.I globalPointerRegistry.h \
+    indirectCompareNames.I indirectCompareNames.h \
+    indirectCompareTo.I indirectCompareTo.h \
+    indirectLess.I indirectLess.h \
+    ioPtaDatagramFloat.h ioPtaDatagramInt.h \
+    ioPtaDatagramShort.h keyboardButton.h lineStream.I \
+    lineStream.h lineStreamBuf.I lineStreamBuf.h \
+    modifierButtons.I modifierButtons.h mouseButton.h \
+    mouseData.h nameUniquifier.I nameUniquifier.h \
+    ordered_vector.h ordered_vector.I ordered_vector.T \
+    pipeline.h pipeline.I \
+    pipelineCycler.h pipelineCycler.I \
+    pipelineCyclerBase.h pipelineCyclerBase.I \
+    pta_double.h \
+    pta_float.h pta_int.h \
+    string_utils.I string_utils.N string_utils.h \
+    timedCycle.I timedCycle.h typedWritable.I \
+    typedWritable.h typedWritableReferenceCount.I \
+    typedWritableReferenceCount.h updateSeq.I updateSeq.h \
+    vector_double.h vector_float.h vector_typedWritable.h \
+    vector_ushort.h vector_writable.h \
+    writable.I writable.h writableConfigurable.h \
+    writableParam.I writableParam.h 
     
  #define INCLUDED_SOURCES \
-     bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \
-     buttonEvent.cxx buttonHandle.cxx buttonRegistry.cxx \
-     config_util.cxx configurable.cxx factoryBase.cxx \
-     factoryParam.cxx factoryParams.cxx globPattern.cxx \
-     globalPointerRegistry.cxx ioPtaDatagramFloat.cxx \
-     ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \
-     keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \
-     modifierButtons.cxx mouseButton.cxx mouseData.cxx \
-     nameUniquifier.cxx \
-     ordered_vector.cxx \
-     pta_double.cxx pta_float.cxx \
-     pta_int.cxx pta_ushort.cxx \
-     string_utils.cxx timedCycle.cxx typedWritable.cxx \
-     typedWritableReferenceCount.cxx updateSeq.cxx \
-     vector_double.cxx vector_float.cxx \
-     vector_typedWritable.cxx \
-     vector_ushort.cxx vector_writable.cxx writable.cxx \
-     writableConfigurable.cxx writableParam.cxx 
+    bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \
+    buttonEvent.cxx buttonHandle.cxx buttonRegistry.cxx \
+    config_util.cxx configurable.cxx \
+    cycleData.cxx \
+    cycleDataReader.cxx \
+    cycleDataWriter.cxx \
+    factoryBase.cxx \
+    factoryParam.cxx factoryParams.cxx globPattern.cxx \
+    globalPointerRegistry.cxx ioPtaDatagramFloat.cxx \
+    ioPtaDatagramInt.cxx ioPtaDatagramShort.cxx \
+    keyboardButton.cxx lineStream.cxx lineStreamBuf.cxx \
+    modifierButtons.cxx mouseButton.cxx mouseData.cxx \
+    nameUniquifier.cxx \
+    ordered_vector.cxx \
+    pipeline.cxx \
+    pipelineCycler.cxx \
+    pipelineCyclerBase.cxx \
+    pta_double.cxx pta_float.cxx \
+    pta_int.cxx pta_ushort.cxx \
+    string_utils.cxx timedCycle.cxx typedWritable.cxx \
+    typedWritableReferenceCount.cxx updateSeq.cxx \
+    vector_double.cxx vector_float.cxx \
+    vector_typedWritable.cxx \
+    vector_ushort.cxx vector_writable.cxx writable.cxx \
+    writableConfigurable.cxx writableParam.cxx 
 
   #define INSTALL_HEADERS \
     bam.h bamReader.I bamReader.h bamReaderParam.I bamReaderParam.h \
@@ -69,6 +82,9 @@
     buttonRegistry.h collideMask.h \
     compareTo.I compareTo.h \
     config_util.h configurable.h factory.I factory.h \
+    cycleData.h cycleData.I \
+    cycleDataReader.h cycleDataReader.I \
+    cycleDataWriter.h cycleDataWriter.I \
     factoryBase.I factoryBase.h factoryParam.I factoryParam.h \
     factoryParams.I factoryParams.h \
     firstOfPairCompare.I firstOfPairCompare.h \
@@ -83,6 +99,9 @@
     modifierButtons.h mouseButton.h mouseData.h nameUniquifier.I \
     nameUniquifier.h \
     ordered_vector.h ordered_vector.I ordered_vector.T \
+    pipeline.h pipeline.I \
+    pipelineCycler.h pipelineCycler.I \
+    pipelineCyclerBase.h pipelineCyclerBase.I \
     pta_double.h \
     pta_float.h pta_int.h pta_ushort.h string_utils.I \
     string_utils.h timedCycle.I timedCycle.h typedWritable.I \

+ 0 - 0
panda/src/pgraph/cycleData.I → panda/src/putil/cycleData.I


+ 0 - 0
panda/src/pgraph/cycleData.cxx → panda/src/putil/cycleData.cxx


+ 0 - 0
panda/src/pgraph/cycleData.h → panda/src/putil/cycleData.h


+ 0 - 0
panda/src/pgraph/cycleDataReader.I → panda/src/putil/cycleDataReader.I


+ 0 - 0
panda/src/pgraph/cycleDataReader.cxx → panda/src/putil/cycleDataReader.cxx


+ 0 - 0
panda/src/pgraph/cycleDataReader.h → panda/src/putil/cycleDataReader.h


+ 0 - 0
panda/src/pgraph/cycleDataWriter.I → panda/src/putil/cycleDataWriter.I


+ 0 - 0
panda/src/pgraph/cycleDataWriter.cxx → panda/src/putil/cycleDataWriter.cxx


+ 0 - 0
panda/src/pgraph/cycleDataWriter.h → panda/src/putil/cycleDataWriter.h


+ 0 - 0
panda/src/pgraph/pipeline.I → panda/src/putil/pipeline.I


+ 0 - 0
panda/src/pgraph/pipeline.cxx → panda/src/putil/pipeline.cxx


+ 0 - 0
panda/src/pgraph/pipeline.h → panda/src/putil/pipeline.h


+ 0 - 0
panda/src/pgraph/pipelineCycler.I → panda/src/putil/pipelineCycler.I


+ 0 - 0
panda/src/pgraph/pipelineCycler.cxx → panda/src/putil/pipelineCycler.cxx


+ 0 - 0
panda/src/pgraph/pipelineCycler.h → panda/src/putil/pipelineCycler.h


+ 0 - 0
panda/src/pgraph/pipelineCyclerBase.I → panda/src/putil/pipelineCyclerBase.I


+ 0 - 0
panda/src/pgraph/pipelineCyclerBase.cxx → panda/src/putil/pipelineCyclerBase.cxx


+ 0 - 0
panda/src/pgraph/pipelineCyclerBase.h → panda/src/putil/pipelineCyclerBase.h


+ 3 - 1
panda/src/putil/putil_composite1.cxx

@@ -1,4 +1,3 @@
-
 #include "bamReader.cxx"
 #include "bamReaderParam.cxx"
 #include "bamWriter.cxx"
@@ -8,6 +7,9 @@
 #include "buttonRegistry.cxx"
 #include "config_util.cxx"
 #include "configurable.cxx"
+#include "cycleData.cxx"
+#include "cycleDataReader.cxx"
+#include "cycleDataWriter.cxx"
 #include "factoryBase.cxx"
 #include "factoryParam.cxx"
 #include "factoryParams.cxx"

+ 3 - 1
panda/src/putil/putil_composite2.cxx

@@ -1,6 +1,8 @@
-
 #include "nameUniquifier.cxx"
 #include "ordered_vector.cxx"
+#include "pipeline.cxx"
+#include "pipelineCycler.cxx"
+#include "pipelineCyclerBase.cxx"
 #include "pta_double.cxx"
 #include "pta_float.cxx"
 #include "pta_int.cxx"

+ 6 - 4
panda/src/sgattrib/renderRelation.cxx

@@ -54,21 +54,23 @@ changed_transition(TypeHandle trans_type) {
 //  Description: Recomputes the dynamic bounding volume for this arc
 //               (and all of its descendants).
 ////////////////////////////////////////////////////////////////////
-void RenderRelation::
+BoundingVolume *RenderRelation::
 recompute_bound() {
   // First, compute the bounding volume around all of our children.
-  NodeRelation::recompute_bound();
-  nassertv(_bound != (BoundingVolume *)NULL);
+  BoundingVolume *bound = NodeRelation::recompute_bound();
+  nassertr(bound != (BoundingVolume *)NULL, bound);
 
   // Now, if we have a transform transition on the arc, apply it to
   // the bounding volume.
   GeometricBoundingVolume *gbv;
-  DCAST_INTO_V(gbv, _bound);
+  DCAST_INTO_R(gbv, bound, bound);
 
   const TransformTransition *tt;
   if (get_transition_into(tt, this)) {
     gbv->xform(tt->get_matrix());
   }
+
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/sgattrib/renderRelation.h

@@ -41,7 +41,7 @@ public:
   virtual void changed_transition(TypeHandle transition_type);
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 public:
   // This is just to be called at initialization time; don't try to

+ 6 - 4
panda/src/sgraph/geomNode.cxx

@@ -414,11 +414,11 @@ add_geoms_from(const GeomNode *other) {
 //       Access: Protected, Virtual
 //  Description: Recomputes the dynamic bounding volume for this node.
 ////////////////////////////////////////////////////////////////////
-void GeomNode::
+BoundingVolume *GeomNode::
 recompute_bound() {
   // First, get ourselves a fresh, empty bounding volume.
-  BoundedObject::recompute_bound();
-  assert(_bound != (BoundingVolume *)NULL);
+  BoundingVolume *bound = BoundedObject::recompute_bound();
+  nassertr(bound != (BoundingVolume *)NULL, bound);
 
   // Now actually compute the bounding volume by putting it around all
   // of our drawable's bounding volumes.
@@ -431,7 +431,9 @@ recompute_bound() {
 
   const BoundingVolume **child_begin = &child_volumes[0];
   const BoundingVolume **child_end = child_begin + child_volumes.size();
-  _bound->around(child_begin, child_end);
+
+  bound->around(child_begin, child_end);
+  return bound;
 }
 
 ////////////////////////////////////////////////////////////////////

+ 1 - 1
panda/src/sgraph/geomNode.h

@@ -73,7 +73,7 @@ PUBLISHED:
   void add_geoms_from(const GeomNode *other);
 
 protected:
-  virtual void recompute_bound();
+  virtual BoundingVolume *recompute_bound();
 
 private:
   typedef PTA(PT(dDrawable)) Geoms;