Bläddra i källkod

A start to make Bullet objects writable (to .bam files)

rdb 10 år sedan
förälder
incheckning
38ac0401ce

+ 129 - 4
panda/src/bullet/bulletBodyNode.cxx

@@ -342,7 +342,16 @@ LPoint3 BulletBodyNode::
 get_shape_pos(int idx) const {
 get_shape_pos(int idx) const {
 
 
   nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
   nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
-  return get_shape_mat(idx).get_row3(3);
+
+  btCollisionShape *root = get_object()->getCollisionShape();
+  if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
+    btCompoundShape *compound = (btCompoundShape *)root;
+
+    btTransform trans = compound->getChildTransform(idx);
+    return btVector3_to_LVector3(trans.getOrigin());
+  }
+
+  return LPoint3::zero();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -352,15 +361,24 @@ get_shape_pos(int idx) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 LMatrix4 BulletBodyNode::
 LMatrix4 BulletBodyNode::
 get_shape_mat(int idx) const {
 get_shape_mat(int idx) const {
+  return get_shape_transform(idx)->get_mat();
+}
 
 
-  nassertr(idx >= 0 && idx < (int)_shapes.size(), LMatrix4::ident_mat());
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::get_shape_transform
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+CPT(TransformState) BulletBodyNode::
+get_shape_transform(int idx) const {
+  nassertr(idx >= 0 && idx < (int)_shapes.size(), TransformState::make_identity());
 
 
   btCollisionShape *root = get_object()->getCollisionShape();
   btCollisionShape *root = get_object()->getCollisionShape();
   if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
   if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
     btCompoundShape *compound = (btCompoundShape *)root;
     btCompoundShape *compound = (btCompoundShape *)root;
 
 
     btTransform trans = compound->getChildTransform(idx);
     btTransform trans = compound->getChildTransform(idx);
-    return btTrans_to_LMatrix4(trans);
+    return btTrans_to_TransformState(trans);
 
 
     // The above code assumes that shape's index in _shapes member
     // The above code assumes that shape's index in _shapes member
     // is the same as the shapes index within the compound. If it
     // is the same as the shapes index within the compound. If it
@@ -377,7 +395,7 @@ get_shape_mat(int idx) const {
     */
     */
   }
   }
 
 
-  return LMatrix4::ident_mat();
+  return TransformState::make_identity();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -705,3 +723,110 @@ cout << "origin " << aabbMin.x() << " " << aabbMin.y() << " " << aabbMin.z() <<
   return bounds;
   return bounds;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  PandaNode::write_datagram(manager, dg);
+
+  dg.add_bool(is_static());
+  dg.add_bool(is_kinematic());
+  dg.add_bool(notifies_collisions());
+  dg.add_bool(get_collision_response());
+  dg.add_stdfloat(get_contact_processing_threshold());
+  //dg.add_bool(is_active());
+  dg.add_stdfloat(get_deactivation_time());
+  dg.add_bool(is_deactivation_enabled());
+  //dg.add_bool(is_debug_enabled());
+  dg.add_stdfloat(get_restitution());
+  dg.add_stdfloat(get_friction());
+#if BT_BULLET_VERSION >= 281
+  dg.add_stdfloat(get_rolling_friction());
+#else
+  dg.add_stdfloat(0);
+#endif
+  if (has_anisotropic_friction()) {
+    dg.add_bool(true);
+    get_anisotropic_friction().write_datagram(dg);
+  } else {
+    dg.add_bool(false);
+  }
+  dg.add_stdfloat(get_ccd_swept_sphere_radius());
+  dg.add_stdfloat(get_ccd_motion_threshold());
+
+  for (int i = 0; i < _shapes.size(); ++i) {
+    manager->write_pointer(dg, get_shape(i));
+    manager->write_pointer(dg, get_shape_transform(i));
+  }
+
+  // Write NULL pointer to indicate the end of the list.
+  manager->write_pointer(dg, NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::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 BulletBodyNode::
+complete_pointers(TypedWritable **p_list, BamReader *manager) {
+  int pi = PandaNode::complete_pointers(p_list, manager);
+
+  BulletShape *shape = DCAST(BulletShape, p_list[pi++]);
+
+  while (shape != (BulletShape *)NULL) {
+    const TransformState *trans = DCAST(TransformState, p_list[pi++]);
+    add_shape(shape, trans);
+
+    shape = DCAST(BulletShape, p_list[pi++]);
+  }
+
+  return pi;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::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 BulletBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletBodyNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PandaNode::fillin(scan, manager);
+
+  set_static(scan.get_bool());
+  set_kinematic(scan.get_bool());
+  notify_collisions(scan.get_bool());
+  set_collision_response(scan.get_bool());
+  set_contact_processing_threshold(scan.get_stdfloat());
+  //set_active(scan.get_bool(), true);
+  set_deactivation_time(scan.get_stdfloat());
+  set_deactivation_enabled(scan.get_bool());
+  set_restitution(scan.get_stdfloat());
+  set_friction(scan.get_stdfloat());
+#if BT_BULLET_VERSION >= 281
+  set_rolling_friction(scan.get_stdfloat());
+#else
+  scan.get_stdfloat();
+#endif
+  if (scan.get_bool()) {
+    LVector3 friction;
+    friction.read_datagram(scan);
+    set_anisotropic_friction(friction);
+  }
+  set_ccd_swept_sphere_radius(scan.get_stdfloat());
+  set_ccd_motion_threshold(scan.get_stdfloat());
+
+  // Read shapes.  The list is bounded by a NULL pointer.
+  while (manager->read_pointer(scan)) {
+    // Each shape comes with a TransformState.
+    manager->read_pointer(scan);
+  }
+}

+ 11 - 2
panda/src/bullet/bulletBodyNode.h

@@ -33,9 +33,10 @@ class BulletShape;
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
 class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
+protected:
+  BulletBodyNode(const char *name);
 
 
 PUBLISHED:
 PUBLISHED:
-  BulletBodyNode(const char *name);
   INLINE ~BulletBodyNode();
   INLINE ~BulletBodyNode();
 
 
   // Shapes
   // Shapes
@@ -48,6 +49,7 @@ PUBLISHED:
 
 
   LPoint3 get_shape_pos(int idx) const;
   LPoint3 get_shape_pos(int idx) const;
   LMatrix4 get_shape_mat(int idx) const;
   LMatrix4 get_shape_mat(int idx) const;
+  CPT(TransformState) get_shape_transform(int idx) const;
   BoundingSphere get_shape_bounds() const;
   BoundingSphere get_shape_bounds() const;
 
 
   void add_shapes_from_collision_solids(CollisionNode *cnode);
   void add_shapes_from_collision_solids(CollisionNode *cnode);
@@ -142,7 +144,14 @@ private:
 
 
   static bool is_identity(btTransform &trans);
   static bool is_identity(btTransform &trans);
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+  virtual int complete_pointers(TypedWritable **plist,
+                                BamReader *manager);
+
+protected:
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 64 - 1
panda/src/bullet/bulletBoxShape.cxx

@@ -66,7 +66,7 @@ get_half_extents_with_margin() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletBoxShape::make_from_solid
 //     Function: BulletBoxShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletBoxShape *BulletBoxShape::
 BulletBoxShape *BulletBoxShape::
@@ -82,3 +82,66 @@ make_from_solid(const CollisionBox *solid) {
   return new BulletBoxShape(extents);
   return new BulletBoxShape(extents);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  get_half_extents_with_margin().write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletBoxShape::
+make_from_bam(const FactoryParams &params) {
+  BulletBoxShape *param = new BulletBoxShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBoxShape::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 BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletBoxShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  LVector3 half_extents;
+  half_extents.read_datagram(scan);
+
+  _shape = new btBoxShape(LVecBase3_to_btVector3(half_extents));
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}

+ 11 - 1
panda/src/bullet/bulletBoxShape.h

@@ -29,6 +29,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
 class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletBoxShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletBoxShape(const LVecBase3 &halfExtents);
   BulletBoxShape(const LVecBase3 &halfExtents);
@@ -47,7 +50,14 @@ public:
 private:
 private:
   btBoxShape *_shape;
   btBoxShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 68 - 1
panda/src/bullet/bulletPlaneShape.cxx

@@ -43,7 +43,7 @@ ptr() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletPlaneShape::make_from_solid
 //     Function: BulletPlaneShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletPlaneShape *BulletPlaneShape::
 BulletPlaneShape *BulletPlaneShape::
@@ -55,3 +55,70 @@ make_from_solid(const CollisionPlane *solid) {
   return new BulletPlaneShape(normal, constant);
   return new BulletPlaneShape(normal, constant);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  get_plane_normal().write_datagram(dg);
+  dg.add_stdfloat(get_plane_constant());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletPlaneShape::
+make_from_bam(const FactoryParams &params) {
+  BulletPlaneShape *param = new BulletPlaneShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletPlaneShape::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 BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletPlaneShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  LVector3 normal;
+  normal.read_datagram(scan);
+
+  PN_stdfloat constant = scan.get_stdfloat();
+
+  _shape = new btStaticPlaneShape(LVecBase3_to_btVector3(normal), constant);
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}
+

+ 11 - 1
panda/src/bullet/bulletPlaneShape.h

@@ -29,6 +29,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
 class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletPlaneShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletPlaneShape(const LVector3 &normal, PN_stdfloat constant);
   BulletPlaneShape(const LVector3 &normal, PN_stdfloat constant);
@@ -47,7 +50,14 @@ public:
 private:
 private:
   btStaticPlaneShape *_shape;
   btStaticPlaneShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 99 - 0
panda/src/bullet/bulletRigidBodyNode.cxx

@@ -490,6 +490,28 @@ get_gravity() const {
   return btVector3_to_LVector3(_rigid->getGravity());
   return btVector3_to_LVector3(_rigid->getGravity());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_linear_factor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3 BulletRigidBodyNode::
+get_linear_factor() const {
+
+  return btVector3_to_LVector3(_rigid->getLinearFactor());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::get_angular_factor
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+LVector3 BulletRigidBodyNode::
+get_angular_factor() const {
+
+  return btVector3_to_LVector3(_rigid->getAngularFactor());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletRigidBodyNode::set_linear_factor
 //     Function: BulletRigidBodyNode::set_linear_factor
 //       Access: Published
 //       Access: Published
@@ -650,3 +672,80 @@ pick_dirty_flag() {
   return _motion->pick_dirty_flag();
   return _motion->pick_dirty_flag();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletRigidBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  BulletBodyNode::write_datagram(manager, dg);
+
+  dg.add_stdfloat(get_mass());
+  dg.add_stdfloat(get_linear_damping());
+  dg.add_stdfloat(get_angular_damping());
+  dg.add_stdfloat(get_linear_sleep_threshold());
+  dg.add_stdfloat(get_angular_sleep_threshold());
+  get_gravity().write_datagram(dg);
+  get_linear_factor().write_datagram(dg);
+  get_angular_factor().write_datagram(dg);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of this type is encountered
+//               in the Bam file.  It should create the rigid body
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletRigidBodyNode::
+make_from_bam(const FactoryParams &params) {
+  BulletRigidBodyNode *param = new BulletRigidBodyNode;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletRigidBodyNode::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 BulletRigidBodyNode.
+////////////////////////////////////////////////////////////////////
+void BulletRigidBodyNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  BulletBodyNode::fillin(scan, manager);
+
+  set_mass(scan.get_stdfloat());
+  set_linear_damping(scan.get_stdfloat());
+  set_angular_damping(scan.get_stdfloat());
+  set_linear_sleep_threshold(scan.get_stdfloat());
+  set_angular_sleep_threshold(scan.get_stdfloat());
+
+  LVector3 gravity, linear_factor, angular_factor;
+  gravity.read_datagram(scan);
+  linear_factor.read_datagram(scan);
+  angular_factor.read_datagram(scan);
+
+  set_gravity(gravity);
+  set_linear_factor(linear_factor);
+  set_angular_factor(angular_factor);
+}

+ 11 - 2
panda/src/bullet/bulletRigidBodyNode.h

@@ -80,6 +80,8 @@ PUBLISHED:
   LVector3 get_gravity() const;
   LVector3 get_gravity() const;
 
 
   // Restrict movement
   // Restrict movement
+  LVector3 get_linear_factor() const;
+  LVector3 get_angular_factor() const;
   void set_linear_factor(const LVector3 &factor);
   void set_linear_factor(const LVector3 &factor);
   void set_angular_factor(const LVector3 &factor);
   void set_angular_factor(const LVector3 &factor);
 
 
@@ -100,7 +102,7 @@ protected:
 private:
 private:
   virtual void shape_changed();
   virtual void shape_changed();
 
 
-  // The motion state is used for syncronisation between Bullet
+  // The motion state is used for synchronisation between Bullet
   // and the Panda3D scene graph.
   // and the Panda3D scene graph.
   class MotionState : public btMotionState {
   class MotionState : public btMotionState {
 
 
@@ -127,7 +129,14 @@ private:
   MotionState *_motion;
   MotionState *_motion;
   btRigidBody *_rigid;
   btRigidBody *_rigid;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 5 - 3
panda/src/bullet/bulletShape.h

@@ -26,7 +26,9 @@
 //       Class : BulletShape
 //       Class : BulletShape
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDABULLET BulletShape : public TypedReferenceCount {
+class EXPCL_PANDABULLET BulletShape : public TypedWritableReferenceCount {
+protected:
+  INLINE BulletShape() {};
 
 
 PUBLISHED:
 PUBLISHED:
   INLINE virtual ~BulletShape();
   INLINE virtual ~BulletShape();
@@ -58,9 +60,9 @@ public:
     return _type_handle;
     return _type_handle;
   }
   }
   static void init_type() {
   static void init_type() {
-    TypedReferenceCount::init_type();
+    TypedWritableReferenceCount::init_type();
     register_type(_type_handle, "BulletShape", 
     register_type(_type_handle, "BulletShape", 
-                  TypedReferenceCount::get_class_type());
+                  TypedWritableReferenceCount::get_class_type());
   }
   }
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 61 - 1
panda/src/bullet/bulletSphereShape.cxx

@@ -41,7 +41,7 @@ ptr() const {
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletSphereShape::make_from_solid
 //     Function: BulletSphereShape::make_from_solid
-//       Access: Public
+//       Access: Public, Static
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 BulletSphereShape *BulletSphereShape::
 BulletSphereShape *BulletSphereShape::
@@ -50,3 +50,63 @@ make_from_solid(const CollisionSphere *solid) {
   return new BulletSphereShape(solid->get_radius());
   return new BulletSphereShape(solid->get_radius());
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+  dg.add_stdfloat(get_radius());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::make_from_bam
+//       Access: Protected, Static
+//  Description: This function is called by the BamReader's factory
+//               when a new object of type BulletShape is encountered
+//               in the Bam file.  It should create the BulletShape
+//               and extract its information from the file.
+////////////////////////////////////////////////////////////////////
+TypedWritable *BulletSphereShape::
+make_from_bam(const FactoryParams &params) {
+  BulletSphereShape *param = new BulletSphereShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletSphereShape::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 BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletSphereShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  nassertv(_shape == NULL);
+
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  _shape = new btSphereShape(scan.get_stdfloat());
+  _shape->setUserPointer(this);
+  _shape->setMargin(margin);
+}

+ 11 - 1
panda/src/bullet/bulletSphereShape.h

@@ -28,6 +28,9 @@
 // Description : 
 // Description : 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletSphereShape : public BulletShape {
 class EXPCL_PANDABULLET BulletSphereShape : public BulletShape {
+private:
+  // Only used by make_from_bam
+  INLINE BulletSphereShape() : _shape(NULL) {};
 
 
 PUBLISHED:
 PUBLISHED:
   BulletSphereShape(PN_stdfloat radius);
   BulletSphereShape(PN_stdfloat radius);
@@ -45,7 +48,14 @@ public:
 private:
 private:
   btSphereShape *_shape;
   btSphereShape *_shape;
 
 
-////////////////////////////////////////////////////////////////////
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
 public:
   static TypeHandle get_class_type() {
   static TypeHandle get_class_type() {
     return _type_handle;
     return _type_handle;

+ 6 - 0
panda/src/bullet/config_bullet.cxx

@@ -182,6 +182,12 @@ init_libbullet() {
   BulletVehicle::init_type();
   BulletVehicle::init_type();
   BulletWorld::init_type();
   BulletWorld::init_type();
 
 
+  // Register factory functions for constructing objects from .bam files
+  BulletBoxShape::register_with_read_factory();
+  BulletPlaneShape::register_with_read_factory();
+  BulletRigidBodyNode::register_with_read_factory();
+  BulletSphereShape::register_with_read_factory();
+
   // Custom contact callbacks
   // Custom contact callbacks
   gContactAddedCallback = contact_added_callback;
   gContactAddedCallback = contact_added_callback;
   gContactProcessedCallback = contact_processed_callback;
   gContactProcessedCallback = contact_processed_callback;

+ 2 - 1
panda/src/putil/bam.h

@@ -33,7 +33,7 @@ static const unsigned short _bam_major_ver = 6;
 // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
 // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData.
 
 
 static const unsigned short _bam_first_minor_ver = 14;
 static const unsigned short _bam_first_minor_ver = 14;
-static const unsigned short _bam_minor_ver = 37;
+static const unsigned short _bam_minor_ver = 38;
 // Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
 // Bumped to minor version 14 on 12/19/07 to change default ColorAttrib.
 // Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
 // Bumped to minor version 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
 // Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
 // Bumped to minor version 16 on 5/13/08 to add Texture::_quality_level.
@@ -58,5 +58,6 @@ static const unsigned short _bam_minor_ver = 37;
 // Bumped to minor version 35 on 12/3/14 to change StencilAttrib.
 // Bumped to minor version 35 on 12/3/14 to change StencilAttrib.
 // Bumped to minor version 36 on 12/9/14 to add samplers and lod settings.
 // Bumped to minor version 36 on 12/9/14 to add samplers and lod settings.
 // Bumped to minor version 37 on 1/22/15 to add GeomVertexArrayFormat::_divisor.
 // Bumped to minor version 37 on 1/22/15 to add GeomVertexArrayFormat::_divisor.
+// Bumped to minor version 38 on 4/15/15 to add various Bullet classes.
 
 
 #endif
 #endif

+ 10 - 2
panda/src/putil/bamReader.cxx

@@ -647,12 +647,16 @@ read_handle(DatagramIterator &scan) {
 //               read_pointer() was called.  It is then the calling
 //               read_pointer() was called.  It is then the calling
 //               object's responsibility to store these pointers in the
 //               object's responsibility to store these pointers in the
 //               object properly.
 //               object properly.
+//
+//               We don't know what the final pointer will be yet,
+//               but we do know whether it was NULL, so this method
+//               returns true if the pointer is non-NULL, false if NULL.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void BamReader::
+bool BamReader::
 read_pointer(DatagramIterator &scan) {
 read_pointer(DatagramIterator &scan) {
   Thread::consider_yield();
   Thread::consider_yield();
 
 
-  nassertv(_now_creating != _created_objs.end());
+  nassertr(_now_creating != _created_objs.end(), false);
   int requestor_id = (*_now_creating).first;
   int requestor_id = (*_now_creating).first;
 
 
   // Read the object ID, and associate it with the requesting object.
   // Read the object ID, and associate it with the requesting object.
@@ -680,6 +684,10 @@ read_pointer(DatagramIterator &scan) {
       // object for each non-NULL pointer we read.
       // object for each non-NULL pointer we read.
       _num_extra_objects++;
       _num_extra_objects++;
     }
     }
+
+    return true;
+  } else {
+    return false;
   }
   }
 }
 }
 
 

+ 1 - 1
panda/src/putil/bamReader.h

@@ -163,7 +163,7 @@ PUBLISHED:
 public:
 public:
   // Functions to support classes that read themselves from the Bam.
   // Functions to support classes that read themselves from the Bam.
 
 
-  void read_pointer(DatagramIterator &scan);
+  bool read_pointer(DatagramIterator &scan);
   void read_pointers(DatagramIterator &scan, int count);
   void read_pointers(DatagramIterator &scan, int count);
   void skip_pointer(DatagramIterator &scan);
   void skip_pointer(DatagramIterator &scan);