فهرست منبع

Make writable: bullet convex hull, triangle mesh, debug node

rdb 10 سال پیش
والد
کامیت
9c313a172d

+ 29 - 10
panda/src/bullet/bulletBodyNode.cxx

@@ -167,13 +167,16 @@ output(ostream &out) const {
 //  Description:
 ////////////////////////////////////////////////////////////////////
 void BulletBodyNode::
-add_shape(BulletShape *shape, const TransformState *ts) {
+add_shape(BulletShape *bullet_shape, const TransformState *ts) {
 
   nassertv(get_object());
   nassertv(ts);
 
-  nassertv(!(shape->ptr()->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE 
-    && ((btConvexHullShape *)shape->ptr())->getNumVertices() == 0));
+  btCollisionShape *shape = bullet_shape->ptr();
+  nassertv(shape != NULL);
+
+  nassertv(!(shape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE &&
+            ((btConvexHullShape *)shape)->getNumVertices() == 0));
 
   // Transform
   btTransform trans = TransformState_to_btTrans(ts);
@@ -195,13 +198,13 @@ add_shape(BulletShape *shape, const TransformState *ts) {
       // After adding the shape we will have one shape, but with transform.
       // We need to wrap the shape within a compound shape, in oder to
       // be able to set the local transform.
-      next = shape->ptr();
+      next = shape;
     }
     else {
       // After adding the shape we will have a total of one shape, without 
       // local transform. We can set the shape directly.
       next = new btCompoundShape();
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
     }
 
     get_object()->setCollisionShape(next);
@@ -216,7 +219,7 @@ add_shape(BulletShape *shape, const TransformState *ts) {
       // to the compound shape.
       next = previous;
 
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
     }
     else {
       // We have one shape which is NOT a compound shape, and want to add
@@ -225,7 +228,7 @@ add_shape(BulletShape *shape, const TransformState *ts) {
 
       btTransform previous_trans = btTransform::getIdentity();
       ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
-      ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+      ((btCompoundShape *)next)->addChildShape(trans, shape);
 
       get_object()->setCollisionShape(next);
       _shape = next;
@@ -238,10 +241,10 @@ add_shape(BulletShape *shape, const TransformState *ts) {
     nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
 
     next = previous;
-    ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
+    ((btCompoundShape *)next)->addChildShape(trans, shape);
   }
 
-  _shapes.push_back(shape);
+  _shapes.push_back(bullet_shape);
 
   // Restore the local scaling again
   np.set_scale(scale);
@@ -778,7 +781,7 @@ int BulletBodyNode::
 complete_pointers(TypedWritable **p_list, BamReader *manager) {
   int pi = PandaNode::complete_pointers(p_list, manager);
 
-  BulletShape *shape = DCAST(BulletShape, p_list[pi++]);
+  PT(BulletShape) shape = DCAST(BulletShape, p_list[pi++]);
 
   while (shape != (BulletShape *)NULL) {
     const TransformState *trans = DCAST(TransformState, p_list[pi++]);
@@ -790,6 +793,22 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
   return pi;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletBodyNode::require_fully_complete
+//       Access: Public, Virtual
+//  Description: Some objects require all of their nested pointers to
+//               have been completed before the objects themselves can
+//               be completed.  If this is the case, override this
+//               method to return true, and be careful with circular
+//               references (which would make the object unreadable
+//               from a bam file).
+////////////////////////////////////////////////////////////////////
+bool BulletBodyNode::
+require_fully_complete() const {
+  // We require the shape pointers to be complete before we add them.
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletBodyNode::fillin
 //       Access: Protected

+ 1 - 0
panda/src/bullet/bulletBodyNode.h

@@ -148,6 +148,7 @@ public:
   virtual void write_datagram(BamWriter *manager, Datagram &dg);
   virtual int complete_pointers(TypedWritable **plist,
                                 BamReader *manager);
+  virtual bool require_fully_complete() const;
 
 protected:
   void fillin(DatagramIterator &scan, BamReader *manager);

+ 100 - 4
panda/src/bullet/bulletConvexHullShape.cxx

@@ -66,10 +66,17 @@ add_array(const PTA_LVecBase3 &points) {
   _shape->setUserPointer(this);
 
   PTA_LVecBase3::const_iterator it;
-  for (it=points.begin(); it!=points.end(); it++) {
-    LVecBase3 v = *it;
-    _shape->addPoint(LVecBase3_to_btVector3(v));
+
+#if BT_BULLET_VERSION >= 282
+  for (it = points.begin(); it != points.end(); ++it) {
+    _shape->addPoint(LVecBase3_to_btVector3(*it), false);
   }
+  _shape->recalcLocalAabb();
+#else
+  for (it = points.begin(); it != points.end(); ++it) {
+    _shape->addPoint(LVecBase3_to_btVector3(*it));
+  }
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -100,8 +107,97 @@ add_geom(const Geom *geom, const TransformState *ts) {
   _shape->setUserPointer(this);
 
   pvector<LPoint3>::const_iterator it;
-  for (it=points.begin(); it!=points.end(); it++) {
+
+#if BT_BULLET_VERSION >= 282
+  for (it = points.begin(); it != points.end(); ++it) {
+    LVecBase3 v = *it;
+    _shape->addPoint(LVecBase3_to_btVector3(*it), false);
+  }
+  _shape->recalcLocalAabb();
+#else
+  for (it = points.begin(); it != points.end(); ++it) {
+    LVecBase3 v = *it;
     _shape->addPoint(LVecBase3_to_btVector3(*it));
   }
+#endif
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletShape.
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletConvexHullShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+
+  unsigned int num_points = _shape->getNumPoints();
+  dg.add_uint32(num_points);
+
+  const btVector3 *points = _shape->getUnscaledPoints();
+
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point = btVector3_to_LVecBase3(points[i]);
+    point.write_datagram(dg);
+  }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::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 *BulletConvexHullShape::
+make_from_bam(const FactoryParams &params) {
+  BulletConvexHullShape *param = new BulletConvexHullShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletConvexHullShape::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 BulletConvexHullShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PN_stdfloat margin = scan.get_stdfloat();
+  unsigned int num_points = scan.get_uint32();
+
+#if BT_BULLET_VERSION >= 282
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point;
+    point.read_datagram(scan);
+    _shape->addPoint(LVecBase3_to_btVector3(point), false);
+  }
+  _shape->recalcLocalAabb();
+#else
+  for (unsigned int i = 0; i < num_points; ++i) {
+    LVecBase3 point;
+    point.read_datagram(scan);
+    _shape->addPoint(LVecBase3_to_btVector3(point));
+  }
+#endif
+}

+ 8 - 2
panda/src/bullet/bulletConvexHullShape.h

@@ -29,7 +29,6 @@
 // Description : 
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletConvexHullShape : public BulletShape {
-
 PUBLISHED:
   BulletConvexHullShape();
   INLINE BulletConvexHullShape(const BulletConvexHullShape &copy);
@@ -47,7 +46,14 @@ public:
 private:
   btConvexHullShape *_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:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 67 - 0
panda/src/bullet/bulletDebugNode.cxx

@@ -463,3 +463,70 @@ drawSphere(btScalar radius, const btTransform &transform, const btVector3 &color
   drawArc(center, zoffs, xoffs, radius, radius, 0, SIMD_2_PI, color, false, 10.0);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletDebugNode.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  // Don't upcall to GeomNode since we're not interested in storing
+  // the actual debug Geoms in the .bam file.
+  PandaNode::write_datagram(manager, dg);
+
+  dg.add_bool(_wireframe);
+  dg.add_bool(_constraints);
+  dg.add_bool(_bounds);
+  dg.add_bool(_drawer._normals);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::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 *BulletDebugNode::
+make_from_bam(const FactoryParams &params) {
+  BulletDebugNode *param = new BulletDebugNode;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletDebugNode::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 BulletDebugNode.
+////////////////////////////////////////////////////////////////////
+void BulletDebugNode::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  // Don't upcall to GeomNode since we're not interested in storing
+  // the actual debug Geoms in the .bam file.
+  PandaNode::fillin(scan, manager);
+
+  _wireframe = scan.get_bool();
+  _constraints = scan.get_bool();
+  _bounds = scan.get_bool();
+  _drawer._normals = scan.get_bool();
+}

+ 8 - 1
panda/src/bullet/bulletDebugNode.h

@@ -101,7 +101,14 @@ private:
 
   friend class BulletWorld;
 
-////////////////////////////////////////////////////////////////////
+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:
   static TypeHandle get_class_type() {
     return _type_handle;

+ 122 - 0
panda/src/bullet/bulletTriangleMesh.cxx

@@ -213,3 +213,125 @@ write(ostream &out, int indent_level) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletTriangleMesh.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_welding_distance());
+
+  // In case we ever want to represent more than 1 indexed mesh.
+  dg.add_int32(1);
+
+  btIndexedMesh &mesh = _mesh->getIndexedMeshArray()[0];
+  dg.add_int32(mesh.m_numVertices);
+  dg.add_int32(mesh.m_numTriangles);
+
+  // In case we want to use this to distinguish 16-bit vs 32-bit indices.
+  dg.add_bool(true);
+
+  // Add the vertices.
+  const unsigned char *vptr = mesh.m_vertexBase;
+  nassertv(vptr != NULL || mesh.m_numVertices == 0);
+
+  for (int i = 0; i < mesh.m_numVertices; ++i) {
+    const btVector3 &vertex = *((btVector3 *)vptr);
+    dg.add_stdfloat(vertex.getX());
+    dg.add_stdfloat(vertex.getY());
+    dg.add_stdfloat(vertex.getZ());
+    vptr += mesh.m_vertexStride;
+  }
+
+  // Now add the triangle indices.
+  const unsigned char *iptr = mesh.m_triangleIndexBase;
+  nassertv(iptr != NULL || mesh.m_numTriangles == 0);
+
+  if (_mesh->getUse32bitIndices()) {
+    for (int i = 0; i < mesh.m_numTriangles; ++i) {
+      int *triangle = (int *)iptr;
+      dg.add_int32(triangle[0]);
+      dg.add_int32(triangle[1]);
+      dg.add_int32(triangle[2]);
+      iptr += mesh.m_triangleIndexStride;
+    }
+  } else {
+    for (int i = 0; i < mesh.m_numTriangles; ++i) {
+      short int *triangle = (short int *)iptr;
+      dg.add_int32(triangle[0]);
+      dg.add_int32(triangle[1]);
+      dg.add_int32(triangle[2]);
+      iptr += mesh.m_triangleIndexStride;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::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 *BulletTriangleMesh::
+make_from_bam(const FactoryParams &params) {
+  BulletTriangleMesh *param = new BulletTriangleMesh;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMesh::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 BulletTriangleMesh.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMesh::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  set_welding_distance(scan.get_stdfloat());
+
+  nassertv(scan.get_int32() == 1);
+  int num_vertices = scan.get_int32();
+  int num_triangles = scan.get_int32();
+  nassertv(scan.get_bool() == true);
+
+  // Read and add the vertices.
+  _mesh->preallocateVertices(num_vertices);
+  for (int i = 0; i < num_vertices; ++i) {
+    PN_stdfloat x = scan.get_stdfloat();
+    PN_stdfloat y = scan.get_stdfloat();
+    PN_stdfloat z = scan.get_stdfloat();
+    _mesh->findOrAddVertex(btVector3(x, y, z), false);
+  }
+
+  // Now read and add the indices.
+  int num_indices = num_triangles * 3;
+  _mesh->preallocateIndices(num_indices);
+  for (int i = 0; i < num_indices; ++i) {
+    _mesh->addIndex(scan.get_int32());
+  }
+
+  // Since we manually added the vertices individually, we have to
+  // update the triangle count appropriately.
+  _mesh->getIndexedMeshArray()[0].m_numTriangles = num_triangles;
+}

+ 12 - 5
panda/src/bullet/bulletTriangleMesh.h

@@ -20,7 +20,7 @@
 #include "bullet_includes.h"
 #include "bullet_utils.h"
 
-#include "typedReferenceCount.h"
+#include "typedWritableReferenceCount.h"
 #include "nodePath.h"
 #include "luse.h"
 #include "geom.h"
@@ -31,7 +31,7 @@
 //       Class : BulletTriangleMesh
 // Description : 
 ////////////////////////////////////////////////////////////////////
-class EXPCL_PANDABULLET BulletTriangleMesh : public TypedReferenceCount {
+class EXPCL_PANDABULLET BulletTriangleMesh : public TypedWritableReferenceCount {
 
 PUBLISHED:
   BulletTriangleMesh();
@@ -63,15 +63,22 @@ public:
 private:
   btTriangleMesh *_mesh;
 
-////////////////////////////////////////////////////////////////////
+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:
   static TypeHandle get_class_type() {
     return _type_handle;
   }
   static void init_type() {
-    TypedReferenceCount::init_type();
+    TypedWritableReferenceCount::init_type();
     register_type(_type_handle, "BulletTriangleMesh", 
-                  TypedReferenceCount::get_class_type());
+                  TypedWritableReferenceCount::get_class_type());
   }
   virtual TypeHandle get_type() const {
     return get_class_type();

+ 116 - 1
panda/src/bullet/bulletTriangleMeshShape.cxx

@@ -21,6 +21,21 @@
 
 TypeHandle BulletTriangleMeshShape::_type_handle;
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::Constructor
+//       Access: Private
+//  Description: Only used by make_from_bam.
+////////////////////////////////////////////////////////////////////
+BulletTriangleMeshShape::
+BulletTriangleMeshShape() :
+  _mesh(NULL),
+  _gimpact_shape(NULL),
+  _bvh_shape(NULL),
+  _dynamic(false),
+  _compress(false),
+  _bvh(false) {
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: BulletTriangleMeshShape::Constructor
 //       Access: Published
@@ -28,7 +43,10 @@ TypeHandle BulletTriangleMeshShape::_type_handle;
 //               if 'dynamic' is set to FALSE.
 ////////////////////////////////////////////////////////////////////
 BulletTriangleMeshShape::
-BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress, bool bvh) {
+BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress, bool bvh) :
+  _dynamic(dynamic),
+  _compress(compress),
+  _bvh(bvh) {
 
   // Assert that mesh is not NULL
   if (!mesh) {
@@ -101,3 +119,100 @@ refit_tree(const LPoint3 &aabb_min, const LPoint3 &aabb_max) {
                         LVecBase3_to_btVector3(aabb_max));
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::register_with_read_factory
+//       Access: Public, Static
+//  Description: Tells the BamReader how to create objects of type
+//               BulletTriangleMeshShape.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+register_with_read_factory() {
+  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::write_datagram
+//       Access: Public, Virtual
+//  Description: Writes the contents of this object to the datagram
+//               for shipping out to a Bam file.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+write_datagram(BamWriter *manager, Datagram &dg) {
+  dg.add_stdfloat(get_margin());
+
+  manager->write_pointer(dg, _mesh);
+
+  dg.add_bool(_dynamic);
+  if (!_dynamic) {
+    dg.add_bool(_compress);
+    dg.add_bool(_bvh);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::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 BulletTriangleMeshShape::
+complete_pointers(TypedWritable **p_list, BamReader *manager) {
+  int pi = BulletShape::complete_pointers(p_list, manager);
+
+  _mesh = DCAST(BulletTriangleMesh, p_list[pi++]);
+
+  btTriangleMesh *mesh_ptr = _mesh->ptr();
+  nassertr(mesh_ptr != NULL, pi);
+
+  if (_dynamic) {
+    _gimpact_shape = new btGImpactMeshShape(mesh_ptr);
+    _gimpact_shape->updateBound();
+    _gimpact_shape->setUserPointer(this);
+  } else {
+    _bvh_shape = new btBvhTriangleMeshShape(mesh_ptr, _compress, _bvh);
+    _bvh_shape->setUserPointer(this);
+  }
+
+  return pi;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::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 *BulletTriangleMeshShape::
+make_from_bam(const FactoryParams &params) {
+  BulletTriangleMeshShape *param = new BulletTriangleMeshShape;
+  DatagramIterator scan;
+  BamReader *manager;
+
+  parse_params(params, scan, manager);
+  param->fillin(scan, manager);
+
+  return param;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: BulletTriangleMeshShape::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 BulletTriangleMeshShape.
+////////////////////////////////////////////////////////////////////
+void BulletTriangleMeshShape::
+fillin(DatagramIterator &scan, BamReader *manager) {
+  PN_stdfloat margin = scan.get_stdfloat();
+
+  manager->read_pointer(scan);
+
+  _dynamic = scan.get_bool();
+  if (!_dynamic) {
+    _compress = scan.get_bool();
+    _bvh = scan.get_bool();
+  }
+}

+ 16 - 1
panda/src/bullet/bulletTriangleMeshShape.h

@@ -29,6 +29,8 @@ class BulletTriangleMesh;
 // Description : 
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDABULLET BulletTriangleMeshShape : public BulletShape {
+private:
+  INLINE BulletTriangleMeshShape();
 
 PUBLISHED:
   BulletTriangleMeshShape(BulletTriangleMesh *mesh, bool dynamic, bool compress=true, bool bvh=true);
@@ -50,7 +52,20 @@ private:
 
   PT(BulletTriangleMesh) _mesh;
 
-////////////////////////////////////////////////////////////////////
+  bool _dynamic : 1;
+  bool _compress : 1;
+  bool _bvh : 1;
+
+public:
+  static void register_with_read_factory();
+  virtual void write_datagram(BamWriter *manager, Datagram &dg);
+  virtual int complete_pointers(TypedWritable **plist,
+                              BamReader *manager);
+
+protected:
+  static TypedWritable *make_from_bam(const FactoryParams &params);
+  void fillin(DatagramIterator &scan, BamReader *manager);
+
 public:
   static TypeHandle get_class_type() {
     return _type_handle;

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

@@ -184,9 +184,13 @@ init_libbullet() {
 
   // Register factory functions for constructing objects from .bam files
   BulletBoxShape::register_with_read_factory();
+  BulletConvexHullShape::register_with_read_factory();
+  BulletDebugNode::register_with_read_factory();
   BulletPlaneShape::register_with_read_factory();
   BulletRigidBodyNode::register_with_read_factory();
   BulletSphereShape::register_with_read_factory();
+  BulletTriangleMesh::register_with_read_factory();
+  BulletTriangleMeshShape::register_with_read_factory();
 
   // Custom contact callbacks
   gContactAddedCallback = contact_added_callback;