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

This commit is contained in:
rdb 2015-04-16 20:26:55 +02:00
parent ab1c516ebc
commit 9c313a172d
11 changed files with 483 additions and 24 deletions

View File

@ -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

View File

@ -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);

View File

@ -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
}

View File

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

View File

@ -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();
}

View File

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

View File

@ -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;
}

View File

@ -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();

View File

@ -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();
}
}

View File

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

View File

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