Browse Source

Merge branch 'master' of https://github.com/panda3d/panda3d

David Rose 10 years ago
parent
commit
1d1ee63b8e

+ 6 - 1
direct/src/directscripts/extract_docs.py

@@ -203,6 +203,11 @@ def processType(handle, type):
             if docstring:
                 print >>handle, docstring
             print >>handle, interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ","
+
+    elif interrogate_type_is_typedef(type):
+        wrapped_type = translated_type_name(interrogate_type_wrapped_type(type))
+        print >>handle, "typedef %s %s;" % (wrapped_type, typename)
+        return
     else:
         if interrogate_type_is_struct(type):
             classtype = "struct"
@@ -211,7 +216,7 @@ def processType(handle, type):
         elif interrogate_type_is_union(type):
             classtype = "union"
         else:
-            print "I don't know what type %s is" % typename
+            print "I don't know what type %s is" % interrogate_type_true_name(type)
             return
         
         if len(derivations) > 0:

File diff suppressed because it is too large
+ 237 - 236
dtool/metalibs/dtoolconfig/pydtool.cxx


+ 1 - 1
dtool/src/interrogate/interfaceMakerPythonNative.cxx

@@ -2636,7 +2636,7 @@ write_module_class(ostream &out, Object *obj) {
     write_function_slot(out, 2, slots, "bf_getsegcount");
     write_function_slot(out, 2, slots, "bf_getcharbuffer");
     out << "#endif\n";
-    out << "#if PY_MAJOR_VERSION >= 0x02060000\n";
+    out << "#if PY_VERSION_HEX >= 0x02060000\n";
     write_function_slot(out, 2, slots, "bf_getbuffer");
     write_function_slot(out, 2, slots, "bf_releasebuffer");
     out << "#endif\n";

+ 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;

+ 26 - 0
panda/src/display/graphicsStateGuardian.I

@@ -397,6 +397,22 @@ get_max_cube_map_dimension() const {
   return _max_cube_map_dimension;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_max_buffer_texture_size
+//       Access: Published
+//  Description: Returns the largest possible buffer texture size,
+//               or -1 if there is no particular limit.  Returns 0
+//               if cube map textures are not supported.
+//
+//               The value returned may not be meaningful until after
+//               the graphics context has been fully created (e.g. the
+//               window has been opened).
+////////////////////////////////////////////////////////////////////
+INLINE int GraphicsStateGuardian::
+get_max_buffer_texture_size() const {
+  return _max_buffer_texture_size;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_supports_texture_combine
 //       Access: Published
@@ -469,6 +485,16 @@ get_supports_cube_map() const {
   return _supports_cube_map;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_supports_buffer_texture
+//       Access: Published
+//  Description: Returns true if this GSG can render buffer textures.
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::
+get_supports_buffer_texture() const {
+  return _supports_buffer_texture;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_supports_tex_non_pow2
 //       Access: Published

+ 2 - 0
panda/src/display/graphicsStateGuardian.cxx

@@ -185,6 +185,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _max_3d_texture_dimension = 0;
   _max_2d_texture_array_layers = 0;
   _max_cube_map_dimension = 0;
+  _max_buffer_texture_size = 0;
 
   // Assume we don't support these fairly advanced texture combiner
   // modes.
@@ -195,6 +196,7 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
   _supports_3d_texture = false;
   _supports_2d_texture_array = false;
   _supports_cube_map = false;
+  _supports_buffer_texture = false;
   _supports_tex_non_pow2 = false;
   _supports_texture_srgb = false;
   _supports_compressed_texture = false;

+ 4 - 0
panda/src/display/graphicsStateGuardian.h

@@ -121,6 +121,7 @@ PUBLISHED:
   INLINE int get_max_3d_texture_dimension() const;
   INLINE int get_max_2d_texture_array_layers() const; //z axis
   INLINE int get_max_cube_map_dimension() const;
+  INLINE int get_max_buffer_texture_size() const;
 
   INLINE bool get_supports_texture_combine() const;
   INLINE bool get_supports_texture_saved_result() const;
@@ -129,6 +130,7 @@ PUBLISHED:
   INLINE bool get_supports_3d_texture() const;
   INLINE bool get_supports_2d_texture_array() const;
   INLINE bool get_supports_cube_map() const;
+  INLINE bool get_supports_buffer_texture() const;
   INLINE bool get_supports_tex_non_pow2() const;
   INLINE bool get_supports_texture_srgb() const;
 
@@ -476,6 +478,7 @@ protected:
   int _max_3d_texture_dimension;
   int _max_2d_texture_array_layers; //on the z axis
   int _max_cube_map_dimension;
+  int _max_buffer_texture_size;
 
   bool _supports_texture_combine;
   bool _supports_texture_saved_result;
@@ -484,6 +487,7 @@ protected:
   bool _supports_3d_texture;
   bool _supports_2d_texture_array;
   bool _supports_cube_map;
+  bool _supports_buffer_texture;
   bool _supports_tex_non_pow2;
   bool _supports_texture_srgb;
 

+ 132 - 23
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -854,6 +854,17 @@ reset() {
   }
 #endif
 
+#ifndef OPENGLES
+  if (is_at_least_gl_version(3, 0)) {
+    _glTexBuffer = (PFNGLTEXBUFFERPROC)get_extension_func("glTexBuffer");
+    _supports_buffer_texture = true;
+
+  } else if (has_extension("GL_ARB_texture_buffer_object")) {
+    _glTexBuffer = (PFNGLTEXBUFFERPROC)get_extension_func("glTexBufferARB");
+    _supports_buffer_texture = true;
+  }
+#endif
+
   _supports_texture_srgb = false;
   if (is_at_least_gl_version(2, 1) || has_extension("GL_EXT_texture_sRGB")) {
     _supports_texture_srgb = true;
@@ -1941,6 +1952,7 @@ reset() {
   GLint max_3d_texture_size = 0;
   GLint max_2d_texture_array_layers = 0;
   GLint max_cube_map_size = 0;
+  GLint max_buffer_texture_size = 0;
 
   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
   _max_texture_dimension = max_texture_size;
@@ -1966,6 +1978,15 @@ reset() {
     _max_cube_map_dimension = 0;
   }
 
+#ifndef OPENGLES
+  if (_supports_buffer_texture) {
+    glGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &max_buffer_texture_size);
+    _max_buffer_texture_size = max_buffer_texture_size;
+  } else {
+    _max_buffer_texture_size = 0;
+  }
+#endif  // !OPENGLES
+
   GLint max_elements_vertices = 0, max_elements_indices = 0;
 #ifndef OPENGLES
   glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &max_elements_vertices);
@@ -4510,6 +4531,15 @@ prepare_texture(Texture *tex, int view) {
         << "Cube map textures are not supported by this OpenGL driver.\n";
       return NULL;
     }
+    break;
+
+  case Texture::TT_buffer_texture:
+    if (!_supports_buffer_texture) {
+      GLCAT.warning()
+        << "Buffer textures are not supported by this OpenGL driver.\n";
+      return NULL;
+    }
+    break;
 
   default:
     break;
@@ -7362,27 +7392,35 @@ get_texture_target(Texture::TextureType texture_type) const {
     return GL_TEXTURE_2D;
 
   case Texture::TT_3d_texture:
-    if (_supports_3d_texture) {
 #ifndef OPENGLES_1
+    if (_supports_3d_texture) {
       return GL_TEXTURE_3D;
-#endif
-    } else {
-      return GL_NONE;
     }
+#endif
+    return GL_NONE;
+
   case Texture::TT_2d_texture_array:
-    if (_supports_2d_texture_array) {
 #ifndef OPENGLES
+    if (_supports_2d_texture_array) {
       return GL_TEXTURE_2D_ARRAY_EXT;
-#endif
-    } else {
-      return GL_NONE;
     }
+#endif
+    return GL_NONE;
+
   case Texture::TT_cube_map:
     if (_supports_cube_map) {
       return GL_TEXTURE_CUBE_MAP;
     } else {
       return GL_NONE;
     }
+
+  case Texture::TT_buffer_texture:
+#ifndef OPENGLES
+    if (_supports_buffer_texture) {
+      return GL_TEXTURE_BUFFER;
+    }
+#endif
+    return GL_NONE;
   }
 
   GLCAT.error() << "Invalid Texture::TextureType value!\n";
@@ -10252,6 +10290,12 @@ specify_texture(CLP(TextureContext) *gtc, const SamplerState &sampler) {
     // Unsupported target (e.g. 3-d texturing on GL 1.1).
     return false;
   }
+#ifndef OPENGLES
+  if (target == GL_TEXTURE_BUFFER) {
+    // Buffer textures may not receive texture parameters.
+    return false;
+  }
+#endif  // OPENGLES
 
   // Record the active sampler settings.
   gtc->_active_sampler = sampler;
@@ -10505,7 +10549,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
 
   // If we'll use immutable texture storage, we have to pick a sized
   // image format.
-  bool force_sized = (gl_immutable_texture_storage && _supports_tex_storage);
+  bool force_sized = (gl_immutable_texture_storage && _supports_tex_storage) ||
+                     (tex->get_texture_type() == Texture::TT_buffer_texture);
 
   GLint internal_format = get_internal_image_format(tex, force_sized);
   GLint external_format = get_external_image_format(tex);
@@ -10553,6 +10598,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
     max_dimension_z = _max_2d_texture_array_layers;
     break;
 
+  case Texture::TT_buffer_texture:
+    max_dimension_x = _max_buffer_texture_size;
+    max_dimension_y = 1;
+    max_dimension_z = 1;
+    break;
+
   default:
     max_dimension_x = _max_texture_dimension;
     max_dimension_y = _max_texture_dimension;
@@ -10631,6 +10682,13 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
 
   GLenum target = get_texture_target(tex->get_texture_type());
   uses_mipmaps = (uses_mipmaps && !gl_ignore_mipmaps) || gl_force_mipmaps;
+#ifndef OPENGLES
+  if (target == GL_TEXTURE_BUFFER) {
+    // Buffer textures may not have mipmaps.
+    uses_mipmaps = false;
+  }
+#endif  // OPENGLES
+
   bool needs_reload = false;
   if (!gtc->_has_storage ||
       gtc->_uses_mipmaps != uses_mipmaps ||
@@ -10640,6 +10698,12 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
       gtc->_depth != depth) {
     // We need to reload a new GL Texture object.
     needs_reload = true;
+
+    if (_use_object_labels) {
+      // This seems like a good time to assign a label for the debug messages.
+      const string &name = tex->get_name();
+      _glObjectLabel(GL_TEXTURE, gtc->_index, name.size(), name.data());
+    }
   }
 
   if (needs_reload && gtc->_immutable) {
@@ -10648,13 +10712,26 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
     glBindTexture(target, gtc->_index);
   }
 
-  if (needs_reload) {
-    if (_use_object_labels) {
-      // This seems like a good time to assign a label for the debug messages.
-      const string &name = tex->get_name();
-      _glObjectLabel(GL_TEXTURE, gtc->_index, name.size(), name.data());
-    }
+#ifndef OPENGLES
+  if (target == GL_TEXTURE_BUFFER) {
+    // Buffer textures don't support mipmappping.
+    gtc->_generate_mipmaps = false;
 
+    if (gtc->_buffer == 0) {
+      // The buffer object wasn't created yet.
+      _glGenBuffers(1, &gtc->_buffer);
+      _glBindBuffer(GL_TEXTURE_BUFFER, gtc->_buffer);
+      _glTexBuffer(GL_TEXTURE_BUFFER, internal_format, gtc->_buffer);
+      needs_reload = true;
+    } else {
+      _glBindBuffer(GL_TEXTURE_BUFFER, gtc->_buffer);
+      if (gtc->_internal_format != internal_format) {
+        _glTexBuffer(GL_TEXTURE_BUFFER, internal_format, gtc->_buffer);
+      }
+    }
+  } else
+#endif  // !OPENGLES
+  if (needs_reload) {
     // Figure out whether mipmaps will be generated by the GPU or by
     // Panda (or not at all), and how many mipmap levels should be created.
     gtc->_generate_mipmaps = false;
@@ -10736,6 +10813,8 @@ upload_texture(CLP(TextureContext) *gtc, bool force, bool uses_mipmaps) {
       }
 
       switch (tex->get_texture_type()) {
+      case Texture::TT_buffer_texture:
+        // Won't get here, but squelch compiler warning
       case Texture::TT_1d_texture:
         _glTexStorage1D(target, num_levels, internal_format, width);
         break;
@@ -11095,6 +11174,17 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
         break;
 #endif  // OPENGLES
 
+#ifndef OPENGLES
+      case GL_TEXTURE_BUFFER:
+        if (_supports_buffer_texture) {
+          _glBufferSubData(GL_TEXTURE_BUFFER, 0, width, image_ptr);
+        } else {
+          report_my_gl_errors();
+          return false;
+        }
+        break;
+#endif  // OPENGLES
+
       default:
         if (image_compression == Texture::CM_off) {
           if (n==0) {
@@ -11248,6 +11338,7 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
         }
         break;
 #endif
+
 #ifndef OPENGLES
       case GL_TEXTURE_2D_ARRAY_EXT:
         if (_supports_2d_texture_array) {
@@ -11265,7 +11356,19 @@ upload_texture_image(CLP(TextureContext) *gtc, bool needs_reload,
           return false;
         }
         break;
-#endif
+#endif  // OPENGLES
+
+#ifndef OPENGLES
+      case GL_TEXTURE_BUFFER:
+        if (_supports_buffer_texture) {
+          _glBufferData(GL_TEXTURE_BUFFER, width, image_ptr,
+                        get_usage(tex->get_usage_hint()));
+        } else {
+          report_my_gl_errors();
+          return false;
+        }
+        break;
+#endif  // OPENGLES
 
       default:
         if (image_compression == Texture::CM_off) {
@@ -11396,6 +11499,12 @@ get_texture_memory_size(Texture *tex) {
     // We need a particular page to get the level parameter from.
     page_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
     scale = 6;
+
+  } else if (target == GL_TEXTURE_BUFFER) {
+    // In the case of buffer textures, we provided the size to begin with,
+    // so no point in querying anything.  Plus, glGetTexParameter is not even
+    // supported for buffer textures.
+    return tex->get_expected_ram_image_size();
   }
 
   GLint minfilter;
@@ -11431,20 +11540,20 @@ get_texture_memory_size(Texture *tex) {
     luminance_size, intensity_size;
   GLint depth_size = 0;
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_RED_SIZE, &red_size);
+                           GL_TEXTURE_RED_SIZE, &red_size);
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_GREEN_SIZE, &green_size);
+                           GL_TEXTURE_GREEN_SIZE, &green_size);
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_BLUE_SIZE, &blue_size);
+                           GL_TEXTURE_BLUE_SIZE, &blue_size);
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_ALPHA_SIZE, &alpha_size);
+                           GL_TEXTURE_ALPHA_SIZE, &alpha_size);
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_LUMINANCE_SIZE, &luminance_size);
+                           GL_TEXTURE_LUMINANCE_SIZE, &luminance_size);
   glGetTexLevelParameteriv(page_target, 0,
-                              GL_TEXTURE_INTENSITY_SIZE, &intensity_size);
+                           GL_TEXTURE_INTENSITY_SIZE, &intensity_size);
   if (_supports_depth_texture) {
     glGetTexLevelParameteriv(page_target, 0,
-                                GL_TEXTURE_DEPTH_SIZE, &depth_size);
+                             GL_TEXTURE_DEPTH_SIZE, &depth_size);
   }
 
   GLint width = 1, height = 1, depth = 1;

+ 4 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -693,6 +693,10 @@ public:
   PFNGLTEXSTORAGE2DPROC _glTexStorage2D;
   PFNGLTEXSTORAGE3DPROC _glTexStorage3D;
 
+#ifndef OPENGLES
+  PFNGLTEXBUFFERPROC _glTexBuffer;
+#endif
+
   bool _supports_clear_texture;
 #ifndef OPENGLES
   PFNGLCLEARTEXIMAGEPROC _glClearTexImage;

+ 25 - 1
panda/src/glstuff/glShaderContext_src.cxx

@@ -602,16 +602,19 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             case GL_INT_SAMPLER_3D:
             case GL_INT_SAMPLER_2D_ARRAY:
             case GL_INT_SAMPLER_CUBE:
+            case GL_INT_SAMPLER_BUFFER:
             case GL_UNSIGNED_INT_SAMPLER_1D:
             case GL_UNSIGNED_INT_SAMPLER_2D:
             case GL_UNSIGNED_INT_SAMPLER_3D:
             case GL_UNSIGNED_INT_SAMPLER_CUBE:
             case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+            case GL_UNSIGNED_INT_SAMPLER_BUFFER:
             case GL_SAMPLER_1D_SHADOW:
             case GL_SAMPLER_1D:
             case GL_SAMPLER_CUBE_SHADOW:
             case GL_SAMPLER_2D_ARRAY:
             case GL_SAMPLER_2D_ARRAY_SHADOW:
+            case GL_SAMPLER_BUFFER:
 #endif  // !OPENGLES
             case GL_SAMPLER_2D:
             case GL_SAMPLER_2D_SHADOW:
@@ -620,7 +623,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
               Shader::ShaderTexSpec bind;
               bind._id = arg_id;
               bind._name = InternalName::make(param_name);
-              bind._desired_type = Texture::TT_2d_texture_array;
+              bind._desired_type = Texture::TT_2d_texture;
               bind._stage = texunitno++;
               if (get_sampler_texture_type(bind._desired_type, param_type)) {
                 _glgsg->_glUniform1i(p, s->_tex_spec.size());
@@ -761,16 +764,19 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             case GL_IMAGE_3D_EXT:
             case GL_IMAGE_CUBE_EXT:
             case GL_IMAGE_2D_ARRAY_EXT:
+            case GL_IMAGE_BUFFER_EXT:
             case GL_INT_IMAGE_1D_EXT:
             case GL_INT_IMAGE_2D_EXT:
             case GL_INT_IMAGE_3D_EXT:
             case GL_INT_IMAGE_CUBE_EXT:
             case GL_INT_IMAGE_2D_ARRAY_EXT:
+            case GL_INT_IMAGE_BUFFER_EXT:
             case GL_UNSIGNED_INT_IMAGE_1D_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_EXT:
             case GL_UNSIGNED_INT_IMAGE_3D_EXT:
             case GL_UNSIGNED_INT_IMAGE_CUBE_EXT:
             case GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT:
+            case GL_UNSIGNED_INT_IMAGE_BUFFER_EXT:
               // This won't really change at runtime, so we might as well
               // bind once and then forget about it.
               _glgsg->_glUniform1i(p, imgunitno++);
@@ -1076,6 +1082,18 @@ get_sampler_texture_type(int &out, GLenum param_type) {
         << "GLSL shader uses 2D texture array, which is unsupported by the driver.\n";
       return false;
     }
+
+  case GL_INT_SAMPLER_BUFFER:
+  case GL_UNSIGNED_INT_SAMPLER_BUFFER:
+  case GL_SAMPLER_BUFFER:
+    out = Texture::TT_buffer_texture;
+    if (_glgsg->_supports_buffer_texture) {
+      return true;
+    } else {
+      GLCAT.error()
+        << "GLSL shader uses buffer texture, which is unsupported by the driver.\n";
+      return false;
+    }
 #endif
 
   default:
@@ -1509,6 +1527,12 @@ disable_shader_texture_bindings() {
     case Texture::TT_cube_map:
       glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
       break;
+
+    case Texture::TT_buffer_texture:
+#ifndef OPENGLES
+      glBindTexture(GL_TEXTURE_BUFFER, 0);
+#endif
+      break;
     }
   }
 

+ 1 - 0
panda/src/glstuff/glTextureContext_src.I

@@ -26,6 +26,7 @@ CLP(TextureContext)(CLP(GraphicsStateGuardian) *glgsg,
   _glgsg = glgsg;
 
   glGenTextures(1, &_index);
+  _buffer = 0;
 
   _handle = 0;
   _has_storage = false;

+ 10 - 0
panda/src/glstuff/glTextureContext_src.cxx

@@ -34,6 +34,11 @@ CLP(TextureContext)::
 
   glDeleteTextures(1, &_index);
   _index = 0;
+
+  if (_buffer != 0) {
+    _glgsg->_glDeleteBuffers(1, &_buffer);
+    _buffer = 0;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -88,6 +93,11 @@ reset_data() {
   // Free the texture resources.
   glDeleteTextures(1, &_index);
 
+  if (_buffer != 0) {
+    _glgsg->_glDeleteBuffers(1, &_buffer);
+    _buffer = 0;
+  }
+
   // We still need a valid index number, though, in case we want to
   // re-load the texture later.
   glGenTextures(1, &_index);

+ 3 - 0
panda/src/glstuff/glTextureContext_src.h

@@ -48,6 +48,9 @@ public:
   // This is the GL "name" of the texture object.
   GLuint _index;
 
+  // This is only used for buffer textures.
+  GLuint _buffer;
+
   // This is the bindless "handle" to the texture object.
   GLuint64 _handle;
   bool _handle_resident;

+ 32 - 0
panda/src/gobj/texture.I

@@ -215,6 +215,26 @@ setup_cube_map(int size, ComponentType component_type, Format format) {
   setup_texture(TT_cube_map, size, size, 6, component_type, format);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::setup_buffer_texture
+//       Access: Published
+//  Description: Sets the texture as an empty buffer texture with
+//               the specified size and properties.  Follow up
+//               with set_ram_image() or modify_ram_image() to fill
+//               the image data, or use set_clear_color to let the
+//               texture be cleared to a solid color.
+//
+//               Note that a buffer texture's format needs to match
+//               the component type.
+////////////////////////////////////////////////////////////////////
+INLINE void Texture::
+setup_buffer_texture(int size, ComponentType component_type, Format format,
+                     GeomEnums::UsageHint usage) {
+  setup_texture(TT_buffer_texture, size, 1, 1, component_type, format);
+  CDWriter cdata(_cycler);
+  cdata->_usage_hint = usage;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::clear_image
 //       Access: Published
@@ -886,6 +906,18 @@ get_component_type() const {
   return cdata->_component_type;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: Texture::get_usage_hint
+//       Access: Published
+//  Description: Returns the usage hint specified for buffer textures,
+//               or UH_unspecified for all other texture types.
+////////////////////////////////////////////////////////////////////
+INLINE GeomEnums::UsageHint Texture::
+get_usage_hint() const {
+  CDReader cdata(_cycler);
+  return cdata->_usage_hint;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: Texture::set_wrap_u
 //       Access: Published

+ 29 - 2
panda/src/gobj/texture.cxx

@@ -1524,6 +1524,10 @@ write(ostream &out, int indent_level) const {
   case TT_cube_map:
     out << "cube map, " << cdata->_x_size << " x " << cdata->_y_size;
     break;
+
+  case TT_buffer_texture:
+    out << "buffer, " << cdata->_x_size;
+    break;
   }
 
   if (cdata->_num_views > 1) {
@@ -1924,6 +1928,8 @@ format_texture_type(TextureType tt) {
     return "2d_texture_array";
   case TT_cube_map:
     return "cube_map";
+  case TT_buffer_texture:
+    return "buffer_texture";
   }
   return "**invalid**";
 }
@@ -1946,6 +1952,8 @@ string_texture_type(const string &str) {
     return TT_2d_texture_array;
   } else if (cmp_nocase(str, "cube_map") == 0) {
     return TT_cube_map;
+  } else if (cmp_nocase(str, "buffer_texture") == 0) {
+    return TT_buffer_texture;
   }
 
   gobj_cat->error()
@@ -2673,6 +2681,7 @@ do_read(CData *cdata, const Filename &fullpath, const Filename &alpha_fullpath,
     switch (cdata->_texture_type) {
     case TT_1d_texture:
     case TT_2d_texture:
+    case TT_buffer_texture:
       z_size = 1;
       break;
 
@@ -4854,7 +4863,8 @@ do_reconsider_image_properties(CData *cdata, int x_size, int y_size, int num_com
     }
 
 #ifndef NDEBUG
-    if (cdata->_texture_type == TT_1d_texture) {
+    if (cdata->_texture_type == TT_1d_texture ||
+        cdata->_texture_type == TT_buffer_texture) {
       nassertr(y_size == 1, false);
     } else if (cdata->_texture_type == TT_cube_map) {
       nassertr(x_size == y_size, false);
@@ -5051,6 +5061,10 @@ do_setup_texture(CData *cdata, Texture::TextureType texture_type,
     cdata->_default_sampler.set_wrap_v(SamplerState::WM_clamp);
     cdata->_default_sampler.set_wrap_w(SamplerState::WM_clamp);
     break;
+
+  case TT_buffer_texture:
+    nassertv(y_size == 1 && z_size == 1);
+    break;
   }
 
   if (texture_type != TT_2d_texture) {
@@ -5199,7 +5213,8 @@ do_set_x_size(CData *cdata, int x_size) {
 void Texture::
 do_set_y_size(CData *cdata, int y_size) {
   if (cdata->_y_size != y_size) {
-    nassertv(cdata->_texture_type != Texture::TT_1d_texture || y_size == 1);
+    nassertv((cdata->_texture_type != Texture::TT_buffer_texture &&
+              cdata->_texture_type != Texture::TT_1d_texture) || y_size == 1);
     cdata->_y_size = y_size;
     cdata->inc_image_modified();
     do_clear_ram_image(cdata);
@@ -7897,6 +7912,10 @@ do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
   me.add_uint8(cdata->_format);
   me.add_uint8(cdata->_num_components);
 
+  if (cdata->_texture_type == TT_buffer_texture) {
+    me.add_uint8(cdata->_usage_hint);
+  }
+
   me.add_uint8(cdata->_auto_texture_scale);
   me.add_uint32(cdata->_orig_file_x_size);
   me.add_uint32(cdata->_orig_file_y_size);
@@ -8063,6 +8082,7 @@ make_this_from_bam(const FactoryParams &params) {
       options.set_auto_texture_scale(auto_texture_scale);
 
       switch (texture_type) {
+      case TT_buffer_texture:
       case TT_1d_texture:
       case TT_2d_texture:
         if (alpha_filename.empty()) {
@@ -8124,6 +8144,10 @@ do_fillin_body(CData *cdata, DatagramIterator &scan, BamReader *manager) {
   cdata->_format = (Format)scan.get_uint8();
   cdata->_num_components = scan.get_uint8();
 
+  if (cdata->_texture_type == TT_buffer_texture) {
+    cdata->_usage_hint = (GeomEnums::UsageHint)scan.get_uint8();
+  }
+
   cdata->inc_properties_modified();
 
   cdata->_auto_texture_scale = ATS_unspecified;
@@ -8304,6 +8328,9 @@ CData() {
   // check in do_set_format depending on an uninitialized value.
   _format = F_rgba;
 
+  // Only used for buffer textures.
+  _usage_hint = GeomEnums::UH_unspecified;
+
   _pad_x_size = 0;
   _pad_y_size = 0;
   _pad_z_size = 0;

+ 6 - 0
panda/src/gobj/texture.h

@@ -42,6 +42,7 @@
 #include "samplerState.h"
 #include "pnmImage.h"
 #include "colorSpace.h"
+#include "geomEnums.h"
 
 class PNMImage;
 class PfmFile;
@@ -82,6 +83,7 @@ PUBLISHED:
     TT_3d_texture,
     TT_2d_texture_array,
     TT_cube_map,
+    TT_buffer_texture,
   };
 
   enum ComponentType {
@@ -240,6 +242,8 @@ PUBLISHED:
   INLINE void setup_2d_texture_array(int z_size = 1);
   INLINE void setup_2d_texture_array(int x_size, int y_size, int z_size,
                                      ComponentType component_type, Format format);
+  INLINE void setup_buffer_texture(int size, ComponentType component_type,
+                                   Format format, GeomEnums::UsageHint usage);
   void generate_normalization_cube_map(int size);
   void generate_alpha_scale_map();
 
@@ -304,6 +308,7 @@ PUBLISHED:
   INLINE TextureType get_texture_type() const;
   INLINE Format get_format() const;
   INLINE ComponentType get_component_type() const;
+  INLINE GeomEnums::UsageHint get_usage_hint() const;
 
   INLINE void set_wrap_u(WrapMode wrap);
   INLINE void set_wrap_v(WrapMode wrap);
@@ -829,6 +834,7 @@ protected:
     TextureType _texture_type;
     Format _format;
     ComponentType _component_type;
+    GeomEnums::UsageHint _usage_hint;
 
     bool _loaded_from_image;
     bool _loaded_from_txo;

Some files were not shown because too many files changed in this diff