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

This commit is contained in:
rdb 2015-04-15 22:00:30 +02:00
parent 76e135b835
commit 38ac0401ce
15 changed files with 500 additions and 21 deletions

View File

@ -342,7 +342,16 @@ LPoint3 BulletBodyNode::
get_shape_pos(int idx) const {
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::
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();
if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
btCompoundShape *compound = (btCompoundShape *)root;
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
// 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;
}
////////////////////////////////////////////////////////////////////
// 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);
}
}

View File

@ -33,9 +33,10 @@ class BulletShape;
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDABULLET BulletBodyNode : public PandaNode {
protected:
BulletBodyNode(const char *name);
PUBLISHED:
BulletBodyNode(const char *name);
INLINE ~BulletBodyNode();
// Shapes
@ -48,6 +49,7 @@ PUBLISHED:
LPoint3 get_shape_pos(int idx) const;
LMatrix4 get_shape_mat(int idx) const;
CPT(TransformState) get_shape_transform(int idx) const;
BoundingSphere get_shape_bounds() const;
void add_shapes_from_collision_solids(CollisionNode *cnode);
@ -142,7 +144,14 @@ private:
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:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -66,7 +66,7 @@ get_half_extents_with_margin() const {
////////////////////////////////////////////////////////////////////
// Function: BulletBoxShape::make_from_solid
// Access: Public
// Access: Public, Static
// Description:
////////////////////////////////////////////////////////////////////
BulletBoxShape *BulletBoxShape::
@ -82,3 +82,66 @@ make_from_solid(const CollisionBox *solid) {
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);
}

View File

@ -29,6 +29,9 @@
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDABULLET BulletBoxShape : public BulletShape {
private:
// Only used by make_from_bam
INLINE BulletBoxShape() : _shape(NULL) {};
PUBLISHED:
BulletBoxShape(const LVecBase3 &halfExtents);
@ -47,7 +50,14 @@ public:
private:
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:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -43,7 +43,7 @@ ptr() const {
////////////////////////////////////////////////////////////////////
// Function: BulletPlaneShape::make_from_solid
// Access: Public
// Access: Public, Static
// Description:
////////////////////////////////////////////////////////////////////
BulletPlaneShape *BulletPlaneShape::
@ -55,3 +55,70 @@ make_from_solid(const CollisionPlane *solid) {
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);
}

View File

@ -29,6 +29,9 @@
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDABULLET BulletPlaneShape : public BulletShape {
private:
// Only used by make_from_bam
INLINE BulletPlaneShape() : _shape(NULL) {};
PUBLISHED:
BulletPlaneShape(const LVector3 &normal, PN_stdfloat constant);
@ -47,7 +50,14 @@ public:
private:
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:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -490,6 +490,28 @@ get_gravity() const {
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
// Access: Published
@ -650,3 +672,80 @@ 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);
}

View File

@ -80,6 +80,8 @@ PUBLISHED:
LVector3 get_gravity() const;
// Restrict movement
LVector3 get_linear_factor() const;
LVector3 get_angular_factor() const;
void set_linear_factor(const LVector3 &factor);
void set_angular_factor(const LVector3 &factor);
@ -100,7 +102,7 @@ protected:
private:
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.
class MotionState : public btMotionState {
@ -127,7 +129,14 @@ private:
MotionState *_motion;
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:
static TypeHandle get_class_type() {
return _type_handle;

View File

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

View File

@ -41,7 +41,7 @@ ptr() const {
////////////////////////////////////////////////////////////////////
// Function: BulletSphereShape::make_from_solid
// Access: Public
// Access: Public, Static
// Description:
////////////////////////////////////////////////////////////////////
BulletSphereShape *BulletSphereShape::
@ -50,3 +50,63 @@ make_from_solid(const CollisionSphere *solid) {
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);
}

View File

@ -28,6 +28,9 @@
// Description :
////////////////////////////////////////////////////////////////////
class EXPCL_PANDABULLET BulletSphereShape : public BulletShape {
private:
// Only used by make_from_bam
INLINE BulletSphereShape() : _shape(NULL) {};
PUBLISHED:
BulletSphereShape(PN_stdfloat radius);
@ -45,7 +48,14 @@ public:
private:
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:
static TypeHandle get_class_type() {
return _type_handle;

View File

@ -182,6 +182,12 @@ init_libbullet() {
BulletVehicle::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
gContactAddedCallback = contact_added_callback;
gContactProcessedCallback = contact_processed_callback;

View File

@ -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.
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 15 on 4/9/08 to add TextureAttrib::_implicit_sort.
// 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 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 38 on 4/15/15 to add various Bullet classes.
#endif

View File

@ -647,12 +647,16 @@ read_handle(DatagramIterator &scan) {
// read_pointer() was called. It is then the calling
// object's responsibility to store these pointers in the
// 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) {
Thread::consider_yield();
nassertv(_now_creating != _created_objs.end());
nassertr(_now_creating != _created_objs.end(), false);
int requestor_id = (*_now_creating).first;
// 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.
_num_extra_objects++;
}
return true;
} else {
return false;
}
}

View File

@ -163,7 +163,7 @@ PUBLISHED:
public:
// 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 skip_pointer(DatagramIterator &scan);