Redesign of the Bullet <--> scene graph synchronisation.

This commit is contained in:
enn0x 2011-08-12 20:57:59 +00:00
parent 1bd2bac3ef
commit d0c8ccd901
19 changed files with 458 additions and 376 deletions

View File

@ -225,3 +225,29 @@ get_shape(int idx) const {
return _shapes[idx]; return _shapes[idx];
} }
////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::set_debug_enabled
// Access: Published
// Description: Enables or disables the debug visualisation for
// this collision object. By default the debug
// visualisation is enabled.
////////////////////////////////////////////////////////////////////
INLINE void BulletBodyNode::
set_debug_enabled(const bool enabled) {
set_collision_flag(btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT, !enabled);
}
////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::is_debug_enabled
// Access: Published
// Description: Returns TRUE if the debug visualisation is enabled
// for this collision object, and FALSE if the debug
// visualisation is disabled.
////////////////////////////////////////////////////////////////////
INLINE bool BulletBodyNode::
is_debug_enabled() const {
return !get_collision_flag(btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
}

View File

@ -35,9 +35,6 @@ BulletBodyNode(const char *name) : PandaNode(name) {
// Shape // Shape
_shape = new btEmptyShape(); _shape = new btEmptyShape();
// Transform changed callback
_disable_transform_changed = false;
// Default collide mask // Default collide mask
set_into_collide_mask(CollideMask::all_on()); set_into_collide_mask(CollideMask::all_on());
} }
@ -162,22 +159,6 @@ output(ostream &out) const {
if (is_kinematic()) out << " kinematic"; if (is_kinematic()) out << " kinematic";
} }
////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::transform_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletBodyNode::
transform_changed() {
// Apply scale to collision shape
CPT(TransformState) ts = this->get_transform();
if (ts->has_scale()) {
LVecBase3f scale = ts->get_scale();
_shape->setLocalScaling(LVecBase3f_to_btVector3(scale));
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::add_shape // Function: BulletBodyNode::add_shape
// Access: Published // Access: Published
@ -194,7 +175,7 @@ add_shape(BulletShape *shape, CPT(TransformState) ts) {
// Transform // Transform
btTransform trans = btTransform::getIdentity(); btTransform trans = btTransform::getIdentity();
if (ts) { if (ts) {
trans = LMatrix4f_to_btTrans(ts->get_mat()); trans = TransformState_to_btTrans(ts);
} }
// Root shape // Root shape
@ -447,14 +428,14 @@ set_active(bool active, bool force) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::set_disable_deactivation // Function: BulletBodyNode::set_deactivation_enabled
// Access: Published // Access: Published
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletBodyNode:: void BulletBodyNode::
set_disable_deactivation(bool disable, bool force) { set_deactivation_enabled(const bool enabled, const bool force) {
int state = (disable) ? DISABLE_DEACTIVATION : WANTS_DEACTIVATION; int state = (enabled) ? WANTS_DEACTIVATION : DISABLE_DEACTIVATION;
if (force) { if (force) {
get_object()->forceActivationState(state); get_object()->forceActivationState(state);
@ -465,14 +446,14 @@ set_disable_deactivation(bool disable, bool force) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletBodyNode::get_disable_deactivation // Function: BulletBodyNode::is_deactivation_enabled
// Access: Published // Access: Published
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
bool BulletBodyNode:: bool BulletBodyNode::
get_disable_deactivation() const { is_deactivation_enabled() const {
return (get_object()->getActivationState() & DISABLE_DEACTIVATION) != 0; return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -78,8 +78,12 @@ PUBLISHED:
void set_deactivation_time(float dt); void set_deactivation_time(float dt);
float get_deactivation_time() const; float get_deactivation_time() const;
void set_disable_deactivation(bool disable, bool force=false); void set_deactivation_enabled(const bool enabled, const bool force=false);
bool get_disable_deactivation() const; bool is_deactivation_enabled() const;
// Debug Visualistion
INLINE void set_debug_enabled(const bool enabled);
INLINE bool is_debug_enabled() const;
// Friction and Restitution // Friction and Restitution
INLINE float get_restitution() const; INLINE float get_restitution() const;
@ -121,9 +125,6 @@ protected:
typedef PTA(PT(BulletShape)) BulletShapes; typedef PTA(PT(BulletShape)) BulletShapes;
BulletShapes _shapes; BulletShapes _shapes;
bool _disable_transform_changed;
virtual void transform_changed();
private: private:
virtual void shape_changed(); virtual void shape_changed();

View File

@ -24,17 +24,21 @@ TypeHandle BulletCharacterControllerNode::_type_handle;
BulletCharacterControllerNode:: BulletCharacterControllerNode::
BulletCharacterControllerNode(BulletShape *shape, float step_height, const char *name) : PandaNode(name) { BulletCharacterControllerNode(BulletShape *shape, float step_height, const char *name) : PandaNode(name) {
// Setup initial transform // Synchronised transform
_sync = TransformState::make_identity();
_sync_disable = false;
// Initial transform
btTransform trans = btTransform::getIdentity(); btTransform trans = btTransform::getIdentity();
// Get convex shape // Get convex shape (for ghost object)
if (!shape->is_convex()) { if (!shape->is_convex()) {
bullet_cat.error() << "a convex shape is required!" << endl; bullet_cat.error() << "a convex shape is required!" << endl;
} }
btConvexShape *convex = dynamic_cast<btConvexShape *>(shape->ptr()); btConvexShape *convex = dynamic_cast<btConvexShape *>(shape->ptr());
// Setup ghost object // Ghost object
_ghost = new btPairCachingGhostObject(); _ghost = new btPairCachingGhostObject();
_ghost->setUserPointer(this); _ghost->setUserPointer(this);
@ -43,25 +47,21 @@ BulletCharacterControllerNode(BulletShape *shape, float step_height, const char
_ghost->setCollisionShape(convex); _ghost->setCollisionShape(convex);
_ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT); _ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
// Setup up axis // Up axis
_up = get_default_up_axis(); _up = get_default_up_axis();
// Movement // Initialise movement
_linear_velocity_is_local = false; _linear_velocity_is_local = false;
_linear_velocity.set(0.0f, 0.0f, 0.0f); _linear_velocity.set(0.0f, 0.0f, 0.0f);
_angular_velocity = 0.0f; _angular_velocity = 0.0f;
// Setup character controller // Character controller
_character = new btKinematicCharacterController(_ghost, convex, step_height, _up); _character = new btKinematicCharacterController(_ghost, convex, step_height, _up);
_character->setGravity((btScalar)9.81f); _character->setGravity((btScalar)9.81f);
// Retain a pointer to the shape // Retain a pointer to the shape
_shape = shape; _shape = shape;
// The 'transform changed' hook has to be disabled when updating the node's
// transform from inside the post_step method!
_disable_transform_changed = false;
// Default collide mask // Default collide mask
set_into_collide_mask(CollideMask::all_on()); set_into_collide_mask(CollideMask::all_on());
} }
@ -196,14 +196,17 @@ set_angular_velocity(float omega) {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletCharacterControllerNode::pre_step // Function: BulletCharacterControllerNode::sync_p2b
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletCharacterControllerNode:: void BulletCharacterControllerNode::
pre_step(float dt) { sync_p2b(float dt) {
// Angular rotation // Synchronise global transform
transform_changed();
// Angular rotation
btScalar angle = dt * deg_2_rad(_angular_velocity); btScalar angle = dt * deg_2_rad(_angular_velocity);
btMatrix3x3 m = _ghost->getWorldTransform().getBasis(); btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
@ -225,28 +228,32 @@ pre_step(float dt) {
} }
_character->setVelocityForTimeInterval(v, dt); _character->setVelocityForTimeInterval(v, dt);
//_character->setWalkDirection(v * dt);
_angular_velocity = 0.0f; _angular_velocity = 0.0f;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletCharacterControllerNode::post_step // Function: BulletCharacterControllerNode::sync_b2p
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletCharacterControllerNode:: void BulletCharacterControllerNode::
post_step() { sync_b2p() {
btTransform trans = _ghost->getWorldTransform();
CPT(TransformState) ts = btTrans_to_TransformState(trans);
_disable_transform_changed = true;
NodePath np = NodePath::any_path((PandaNode *)this); NodePath np = NodePath::any_path((PandaNode *)this);
np.set_transform(np.get_top(), ts); LVecBase3f scale = np.get_net_transform()->get_scale();
_disable_transform_changed = false; btTransform trans = _ghost->getWorldTransform();
CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
LMatrix4f m_sync = _sync->get_mat();
LMatrix4f m_ts = ts->get_mat();
if (!m_sync.almost_equal(m_ts)) {
_sync = ts;
_sync_disable = true;
np.set_transform(NodePath(), ts);
_sync_disable = false;
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -257,25 +264,36 @@ post_step() {
void BulletCharacterControllerNode:: void BulletCharacterControllerNode::
transform_changed() { transform_changed() {
if (_disable_transform_changed) return; if (_sync_disable) return;
// Get translation and heading
NodePath np = NodePath::any_path((PandaNode *)this); NodePath np = NodePath::any_path((PandaNode *)this);
CPT(TransformState) ts = np.get_transform(np.get_top()); CPT(TransformState) ts = np.get_net_transform();
LPoint3f pos = ts->get_pos(); LMatrix4f m_sync = _sync->get_mat();
float heading = ts->get_hpr().get_x(); LMatrix4f m_ts = ts->get_mat();
// Set translation if (!m_sync.almost_equal(m_ts)) {
_character->warp(LVecBase3f_to_btVector3(pos)); _sync = ts;
// Set Heading // Get translation, heading and scale
btMatrix3x3 m = _ghost->getWorldTransform().getBasis(); LPoint3f pos = ts->get_pos();
btVector3 up = m[_up]; float heading = ts->get_hpr().get_x();
LVecBase3f scale = ts->get_scale();
m = btMatrix3x3(btQuaternion(up, heading)); // Set translation
_character->warp(LVecBase3f_to_btVector3(pos));
_ghost->getWorldTransform().setBasis(m); // Set Heading
btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
btVector3 up = m[_up];
m = btMatrix3x3(btQuaternion(up, heading));
_ghost->getWorldTransform().setBasis(m);
// Set scale
_shape->set_local_scale(scale);
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -408,25 +426,3 @@ set_use_ghost_sweep_test(bool value) {
return _character->setUseGhostSweepTest(value); return _character->setUseGhostSweepTest(value);
} }
/*
////////////////////////////////////////////////////////////////////
// Function: BulletCharacterControllerNode::parents_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletCharacterControllerNode::
parents_changed() {
}
////////////////////////////////////////////////////////////////////
// Function: BulletCharacterControllerNode::children_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletCharacterControllerNode::
children_changed() {
}
*/

View File

@ -69,15 +69,16 @@ public:
INLINE btPairCachingGhostObject *get_ghost() const; INLINE btPairCachingGhostObject *get_ghost() const;
INLINE btKinematicCharacterController *get_character() const; INLINE btKinematicCharacterController *get_character() const;
void pre_step(float dt); void sync_p2b(float dt);
void post_step(); void sync_b2p();
protected: protected:
//virtual void parents_changed();
//virtual void children_changed();
virtual void transform_changed(); virtual void transform_changed();
private: private:
CPT(TransformState) _sync;
bool _sync_disable;
BulletUpAxis _up; BulletUpAxis _up;
btKinematicCharacterController *_character; btKinematicCharacterController *_character;
@ -89,8 +90,6 @@ private:
bool _linear_velocity_is_local; bool _linear_velocity_is_local;
float _angular_velocity; float _angular_velocity;
bool _disable_transform_changed;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
public: public:
static TypeHandle get_class_type() { static TypeHandle get_class_type() {

View File

@ -186,12 +186,12 @@ draw_mask_changed() {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletDebugNode::post_step // Function: BulletDebugNode::sync_b2p
// Access: Private // Access: Private
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletDebugNode:: void BulletDebugNode::
post_step(btDynamicsWorld *world) { sync_b2p(btDynamicsWorld *world) {
if (is_overall_hidden()) return; if (is_overall_hidden()) return;
@ -199,7 +199,7 @@ post_step(btDynamicsWorld *world) {
world->debugDrawWorld(); world->debugDrawWorld();
// Get inverse of this node's net transform // Get inverse of this node's net transform
NodePath np = NodePath::any_path(this); NodePath np = NodePath::any_path((PandaNode *)this);
LMatrix4f m = np.get_net_transform()->get_mat(); LMatrix4f m = np.get_net_transform()->get_mat();
m.invert_in_place(); m.invert_in_place();
@ -348,7 +348,6 @@ drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, cons
void BulletDebugNode::DebugDraw:: void BulletDebugNode::DebugDraw::
drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &n0, const btVector3 &n1, const btVector3 &n2, const btVector3 &color, btScalar alpha) { drawTriangle(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2, const btVector3 &n0, const btVector3 &n1, const btVector3 &n2, const btVector3 &color, btScalar alpha) {
// TODO
bullet_cat.debug() << "drawTriangle(2) - not yet implemented!" << endl; bullet_cat.debug() << "drawTriangle(2) - not yet implemented!" << endl;
} }
@ -374,7 +373,6 @@ drawContactPoint(const btVector3 &point, const btVector3 &normal, btScalar dista
void BulletDebugNode::DebugDraw:: void BulletDebugNode::DebugDraw::
draw3dText(const btVector3 &location, const char *text) { draw3dText(const btVector3 &location, const char *text) {
// TODO
bullet_cat.debug() << "draw3dText - not yet implemented!" << endl; bullet_cat.debug() << "draw3dText - not yet implemented!" << endl;
} }

View File

@ -49,7 +49,7 @@ public:
virtual bool safe_to_flatten_below() const; virtual bool safe_to_flatten_below() const;
private: private:
void post_step(btDynamicsWorld *world); void sync_b2p(btDynamicsWorld *world);
struct Line { struct Line {
LVecBase3f _p0; LVecBase3f _p0;

View File

@ -25,19 +25,20 @@ TypeHandle BulletGhostNode::_type_handle;
BulletGhostNode:: BulletGhostNode::
BulletGhostNode(const char *name) : BulletBodyNode(name) { BulletGhostNode(const char *name) : BulletBodyNode(name) {
// Setup initial transform // Synchronised transform
_sync = TransformState::make_identity();
_sync_disable = false;
// Initial transform
btTransform trans = btTransform::getIdentity(); btTransform trans = btTransform::getIdentity();
// Setup ghost object // Ghost object
_ghost = new btPairCachingGhostObject(); _ghost = new btPairCachingGhostObject();
_ghost->setUserPointer(this); _ghost->setUserPointer(this);
_ghost->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE); _ghost->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
_ghost->setWorldTransform(trans); _ghost->setWorldTransform(trans);
_ghost->setInterpolationWorldTransform(trans); _ghost->setInterpolationWorldTransform(trans);
_ghost->setCollisionShape(_shape); _ghost->setCollisionShape(_shape);
// Autosync is off by default
_sync_transform = false;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -51,35 +52,6 @@ get_object() const {
return _ghost; return _ghost;
} }
////////////////////////////////////////////////////////////////////
// Function: BulletGhostNode::parents_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletGhostNode::
parents_changed() {
// Enable autosync if one of the parents is suited for this
Parents parents = get_parents();
for (int i=0; i < parents.get_num_parents(); ++i) {
PandaNode *parent = parents.get_parent(i);
TypeHandle type = parent->get_type();
if (BulletRigidBodyNode::get_class_type() == type ||
BulletSoftBodyNode::get_class_type() == type ||
BulletGhostNode::get_class_type() == type ||
BulletCharacterControllerNode::get_class_type() == type) {
_sync_transform = true;
return;
}
}
// None of the parents is suited for autosync
_sync_transform = false;
transform_changed();
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletGhostNode::transform_changed // Function: BulletGhostNode::transform_changed
// Access: Protected // Access: Protected
@ -88,26 +60,64 @@ parents_changed() {
void BulletGhostNode:: void BulletGhostNode::
transform_changed() { transform_changed() {
if (_disable_transform_changed) return; if (_sync_disable) return;
btTransform trans = btTransform::getIdentity(); NodePath np = NodePath::any_path((PandaNode *)this);
get_node_transform(trans, this); CPT(TransformState) ts = np.get_net_transform();
_ghost->setWorldTransform(trans);
_ghost->setInterpolationWorldTransform(trans);
BulletBodyNode::transform_changed(); LMatrix4f m_sync = _sync->get_mat();
LMatrix4f m_ts = ts->get_mat();
if (!m_sync.almost_equal(m_ts)) {
_sync = ts;
btTransform trans = TransformState_to_btTrans(ts);
_ghost->setWorldTransform(trans);
_ghost->setInterpolationWorldTransform(trans);
if (ts->has_scale()) {
LVecBase3f scale = ts->get_scale();
for (int i=0; i<get_num_shapes(); i++) {
PT(BulletShape) shape = _shapes[i];
shape->set_local_scale(scale);
}
}
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletGhostNode::pre_step // Function: BulletGhostNode::sync_p2b
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletGhostNode:: void BulletGhostNode::
pre_step() { sync_p2b() {
if (_sync_transform) { transform_changed();
transform_changed(); }
////////////////////////////////////////////////////////////////////
// Function: BulletGhostNode::sync_b2p
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void BulletGhostNode::
sync_b2p() {
NodePath np = NodePath::any_path((PandaNode *)this);
LVecBase3f scale = np.get_net_transform()->get_scale();
btTransform trans = _ghost->getWorldTransform();
CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
LMatrix4f m_sync = _sync->get_mat();
LMatrix4f m_ts = ts->get_mat();
if (!m_sync.almost_equal(m_ts)) {
_sync = ts;
_sync_disable = true;
np.set_transform(NodePath(), ts);
_sync_disable = false;
} }
} }

View File

@ -44,16 +44,17 @@ PUBLISHED:
public: public:
virtual btCollisionObject *get_object() const; virtual btCollisionObject *get_object() const;
void pre_step(); void sync_p2b();
void sync_b2p();
protected: protected:
virtual void parents_changed();
virtual void transform_changed(); virtual void transform_changed();
private: private:
btPairCachingGhostObject *_ghost; CPT(TransformState) _sync;
bool _sync_disable;
bool _sync_transform; btPairCachingGhostObject *_ghost;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
public: public:

View File

@ -21,8 +21,8 @@
INLINE BulletRigidBodyNode:: INLINE BulletRigidBodyNode::
~BulletRigidBodyNode() { ~BulletRigidBodyNode() {
delete _body; delete _rigid->getMotionState();
delete _motion; delete _rigid;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -33,7 +33,7 @@ INLINE BulletRigidBodyNode::
INLINE void BulletRigidBodyNode:: INLINE void BulletRigidBodyNode::
set_linear_damping(float value) { set_linear_damping(float value) {
_body->setDamping(value, _body->getAngularDamping()); _rigid->setDamping(value, _rigid->getAngularDamping());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -44,7 +44,7 @@ set_linear_damping(float value) {
INLINE void BulletRigidBodyNode:: INLINE void BulletRigidBodyNode::
set_angular_damping(float value) { set_angular_damping(float value) {
_body->setDamping(_body->getLinearDamping(), value); _rigid->setDamping(_rigid->getLinearDamping(), value);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -55,7 +55,7 @@ set_angular_damping(float value) {
INLINE float BulletRigidBodyNode:: INLINE float BulletRigidBodyNode::
get_linear_damping() const { get_linear_damping() const {
return _body->getLinearDamping(); return _rigid->getLinearDamping();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -66,6 +66,6 @@ get_linear_damping() const {
INLINE float BulletRigidBodyNode:: INLINE float BulletRigidBodyNode::
get_angular_damping() const { get_angular_damping() const {
return _body->getAngularDamping(); return _rigid->getAngularDamping();
} }

View File

@ -25,16 +25,19 @@ TypeHandle BulletRigidBodyNode::_type_handle;
BulletRigidBodyNode:: BulletRigidBodyNode::
BulletRigidBodyNode(const char *name) : BulletBodyNode(name) { BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {
// Setup motion state // Synchronised transform
_motion = new MotionState(this); _sync = TransformState::make_identity();
_sync_disable = false;
// Setup mass properties // Mass properties
btScalar mass(0.0); btScalar mass(0.0);
btVector3 inertia(0, 0, 0); btVector3 inertia(0, 0, 0);
btRigidBody::btRigidBodyConstructionInfo ci(mass, _motion, _shape, inertia); // Motion state and construction info
btDefaultMotionState *motion = new btDefaultMotionState();
btRigidBody::btRigidBodyConstructionInfo ci(mass, motion, _shape, inertia);
// Enable additional damping // Additional damping
if (bullet_additional_damping) { if (bullet_additional_damping) {
ci.m_additionalDamping = true; ci.m_additionalDamping = true;
ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor; ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
@ -43,9 +46,9 @@ BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {
ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold; ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
} }
// Setup rigid body // Rigid body
_body = new btRigidBody(ci); _rigid = new btRigidBody(ci);
_body->setUserPointer(this); _rigid->setUserPointer(this);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -69,7 +72,7 @@ output(ostream &out) const {
btCollisionObject *BulletRigidBodyNode:: btCollisionObject *BulletRigidBodyNode::
get_object() const { get_object() const {
return _body; return _rigid;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -97,10 +100,10 @@ set_mass(float mass) {
btVector3 inertia(0.0f, 0.0f, 0.0f); btVector3 inertia(0.0f, 0.0f, 0.0f);
if (mass > 0.0f) { if (mass > 0.0f) {
_body->getCollisionShape()->calculateLocalInertia(mass, inertia); _rigid->getCollisionShape()->calculateLocalInertia(mass, inertia);
} }
_body->setMassProps(mass, inertia); _rigid->setMassProps(mass, inertia);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -111,7 +114,7 @@ set_mass(float mass) {
float BulletRigidBodyNode:: float BulletRigidBodyNode::
get_mass() const { get_mass() const {
btScalar invMass = _body->getInvMass(); btScalar invMass = _rigid->getInvMass();
if (invMass == 0.0f) { if (invMass == 0.0f) {
return 0.0f; return 0.0f;
@ -132,7 +135,7 @@ apply_force(const LVector3f &force, const LPoint3f &pos) {
nassertv_always(!force.is_nan()); nassertv_always(!force.is_nan());
nassertv_always(!pos.is_nan()); nassertv_always(!pos.is_nan());
_body->applyForce(LVecBase3f_to_btVector3(force), _rigid->applyForce(LVecBase3f_to_btVector3(force),
LVecBase3f_to_btVector3(pos)); LVecBase3f_to_btVector3(pos));
} }
@ -146,7 +149,7 @@ apply_central_force(const LVector3f &force) {
nassertv_always(!force.is_nan()); nassertv_always(!force.is_nan());
_body->applyCentralForce(LVecBase3f_to_btVector3(force)); _rigid->applyCentralForce(LVecBase3f_to_btVector3(force));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -159,7 +162,7 @@ apply_torque(const LVector3f &torque) {
nassertv_always(!torque.is_nan()); nassertv_always(!torque.is_nan());
_body->applyTorque(LVecBase3f_to_btVector3(torque)); _rigid->applyTorque(LVecBase3f_to_btVector3(torque));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -172,7 +175,7 @@ apply_torque_impulse(const LVector3f &torque) {
nassertv_always(!torque.is_nan()); nassertv_always(!torque.is_nan());
_body->applyTorqueImpulse(LVecBase3f_to_btVector3(torque)); _rigid->applyTorqueImpulse(LVecBase3f_to_btVector3(torque));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -186,7 +189,7 @@ apply_impulse(const LVector3f &impulse, const LPoint3f &pos) {
nassertv_always(!impulse.is_nan()); nassertv_always(!impulse.is_nan());
nassertv_always(!pos.is_nan()); nassertv_always(!pos.is_nan());
_body->applyImpulse(LVecBase3f_to_btVector3(impulse), _rigid->applyImpulse(LVecBase3f_to_btVector3(impulse),
LVecBase3f_to_btVector3(pos)); LVecBase3f_to_btVector3(pos));
} }
@ -200,18 +203,7 @@ apply_central_impulse(const LVector3f &impulse) {
nassertv_always(!impulse.is_nan()); nassertv_always(!impulse.is_nan());
_body->applyCentralImpulse(LVecBase3f_to_btVector3(impulse)); _rigid->applyCentralImpulse(LVecBase3f_to_btVector3(impulse));
}
////////////////////////////////////////////////////////////////////
// Function: BulletRigidBodyNode::parents_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
parents_changed() {
transform_changed();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -222,56 +214,65 @@ parents_changed() {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
transform_changed() { transform_changed() {
if (_disable_transform_changed) return; if (_sync_disable) return;
btTransform trans = btTransform::getIdentity(); NodePath np = NodePath::any_path((PandaNode *)this);
get_node_transform(trans, this); CPT(TransformState) ts = np.get_net_transform();
_body->setWorldTransform(trans);
_body->setInterpolationWorldTransform(trans);
BulletBodyNode::transform_changed(); LMatrix4f m_sync = _sync->get_mat();
} LMatrix4f m_ts = ts->get_mat();
//////////////////////////////////////////////////////////////////// if (!m_sync.almost_equal(m_ts)) {
// Function: BulletRigidBodyNode::MotionState::getWorldTransform _sync = ts;
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::MotionState::
getWorldTransform(btTransform &trans) const {
get_node_transform(trans, _node); btTransform trans = TransformState_to_btTrans(ts);
} _rigid->setWorldTransform(trans);
_rigid->setInterpolationWorldTransform(trans);
//////////////////////////////////////////////////////////////////// if (ts->has_scale()) {
// Function: BulletRigidBodyNode::MotionState::setWorldTransform LVecBase3f scale = ts->get_scale();
// Access: Public for (int i=0; i<get_num_shapes(); i++) {
// Description: PT(BulletShape) shape = _shapes[i];
//////////////////////////////////////////////////////////////////// shape->set_local_scale(scale);
void BulletRigidBodyNode::MotionState:: }
setWorldTransform(const btTransform &trans) { }
if (trans.getOrigin().getX() != trans.getOrigin().getX()) {
bullet_cat.error() << "setWorldTransform: trans is NAN!" << endl;
return;
} }
}
LVecBase3f scale = _node->get_transform()->get_scale(); ////////////////////////////////////////////////////////////////////
// Function: BulletRigidBodyNode::sync_p2b
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_p2b() {
transform_changed();
}
////////////////////////////////////////////////////////////////////
// Function: BulletRigidBodyNode::sync_b2p
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void BulletRigidBodyNode::
sync_b2p() {
NodePath np = NodePath::any_path((PandaNode *)this);
LVecBase3f scale = np.get_net_transform()->get_scale();
btTransform trans = _rigid->getWorldTransform();
CPT(TransformState) ts = btTrans_to_TransformState(trans, scale); CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
// Disable transform_changed callback LMatrix4f m_sync = _sync->get_mat();
_node->_disable_transform_changed = true; LMatrix4f m_ts = ts->get_mat();
if (_node->get_num_parents() == 0) { if (!m_sync.almost_equal(m_ts)) {
_node->set_transform(ts); _sync = ts;
_sync_disable = true;
np.set_transform(NodePath(), ts);
_sync_disable = false;
} }
else {
NodePath np = NodePath::any_path(_node);
np.set_transform(np.get_top(), ts);
}
// Re-enable transform_changed callback again
_node->_disable_transform_changed = false;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -284,11 +285,10 @@ set_center_of_mass_pos(const LPoint3f &pos) {
nassertv_always(!pos.is_nan()); nassertv_always(!pos.is_nan());
btTransform xform = btTransform::getIdentity(); btTransform trans = btTransform::getIdentity();
xform.setIdentity(); trans.setOrigin(LVecBase3f_to_btVector3(pos));
xform.setOrigin(LVecBase3f_to_btVector3(pos));
_body->setCenterOfMassTransform(xform); _rigid->setCenterOfMassTransform(trans);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -299,7 +299,7 @@ set_center_of_mass_pos(const LPoint3f &pos) {
LPoint3f BulletRigidBodyNode:: LPoint3f BulletRigidBodyNode::
get_center_of_mass_pos() const { get_center_of_mass_pos() const {
return btVector3_to_LPoint3f(_body->getCenterOfMassPosition()); return btVector3_to_LPoint3f(_rigid->getCenterOfMassPosition());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -310,7 +310,7 @@ get_center_of_mass_pos() const {
LVector3f BulletRigidBodyNode:: LVector3f BulletRigidBodyNode::
get_linear_velocity() const { get_linear_velocity() const {
return btVector3_to_LVector3f(_body->getLinearVelocity()); return btVector3_to_LVector3f(_rigid->getLinearVelocity());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -321,7 +321,7 @@ get_linear_velocity() const {
LVector3f BulletRigidBodyNode:: LVector3f BulletRigidBodyNode::
get_angular_velocity() const { get_angular_velocity() const {
return btVector3_to_LVector3f(_body->getAngularVelocity()); return btVector3_to_LVector3f(_rigid->getAngularVelocity());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -334,7 +334,7 @@ set_linear_velocity(const LVector3f &velocity) {
nassertv_always(!velocity.is_nan()); nassertv_always(!velocity.is_nan());
_body->setLinearVelocity(LVecBase3f_to_btVector3(velocity)); _rigid->setLinearVelocity(LVecBase3f_to_btVector3(velocity));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -347,7 +347,7 @@ set_angular_velocity(const LVector3f &velocity) {
nassertv_always(!velocity.is_nan()); nassertv_always(!velocity.is_nan());
_body->setAngularVelocity(LVecBase3f_to_btVector3(velocity)); _rigid->setAngularVelocity(LVecBase3f_to_btVector3(velocity));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -358,7 +358,7 @@ set_angular_velocity(const LVector3f &velocity) {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
clear_forces() { clear_forces() {
_body->clearForces(); _rigid->clearForces();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -369,7 +369,7 @@ clear_forces() {
float BulletRigidBodyNode:: float BulletRigidBodyNode::
get_linear_sleep_threshold() const { get_linear_sleep_threshold() const {
return _body->getLinearSleepingThreshold(); return _rigid->getLinearSleepingThreshold();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -380,7 +380,7 @@ get_linear_sleep_threshold() const {
float BulletRigidBodyNode:: float BulletRigidBodyNode::
get_angular_sleep_threshold() const { get_angular_sleep_threshold() const {
return _body->getAngularSleepingThreshold(); return _rigid->getAngularSleepingThreshold();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -391,7 +391,7 @@ get_angular_sleep_threshold() const {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
set_linear_sleep_threshold(float threshold) { set_linear_sleep_threshold(float threshold) {
_body->setSleepingThresholds(_body->getLinearSleepingThreshold(), threshold); _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -402,7 +402,7 @@ set_linear_sleep_threshold(float threshold) {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
set_angular_sleep_threshold(float threshold) { set_angular_sleep_threshold(float threshold) {
_body->setSleepingThresholds(threshold, _body->getAngularSleepingThreshold()); _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -415,7 +415,7 @@ set_gravity(const LVector3f &gravity) {
nassertv_always(!gravity.is_nan()); nassertv_always(!gravity.is_nan());
_body->setGravity(LVecBase3f_to_btVector3(gravity)); _rigid->setGravity(LVecBase3f_to_btVector3(gravity));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -426,7 +426,7 @@ set_gravity(const LVector3f &gravity) {
LVector3f BulletRigidBodyNode:: LVector3f BulletRigidBodyNode::
get_gravity() const { get_gravity() const {
return btVector3_to_LVector3f(_body->getGravity()); return btVector3_to_LVector3f(_rigid->getGravity());
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -437,7 +437,7 @@ get_gravity() const {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
set_linear_factor(const LVector3f &factor) { set_linear_factor(const LVector3f &factor) {
_body->setLinearFactor(LVecBase3f_to_btVector3(factor)); _rigid->setLinearFactor(LVecBase3f_to_btVector3(factor));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -448,6 +448,6 @@ set_linear_factor(const LVector3f &factor) {
void BulletRigidBodyNode:: void BulletRigidBodyNode::
set_angular_factor(const LVector3f &factor) { set_angular_factor(const LVector3f &factor) {
_body->setAngularFactor(LVecBase3f_to_btVector3(factor)); _rigid->setAngularFactor(LVecBase3f_to_btVector3(factor));
} }

View File

@ -82,28 +82,19 @@ public:
virtual void output(ostream &out) const; virtual void output(ostream &out) const;
void sync_p2b();
void sync_b2p();
protected: protected:
virtual void parents_changed();
virtual void transform_changed(); virtual void transform_changed();
private: private:
virtual void shape_changed(); virtual void shape_changed();
class MotionState : public btMotionState { CPT(TransformState) _sync;
bool _sync_disable;
public: btRigidBody *_rigid;
MotionState(BulletRigidBodyNode *node) : _node(node) {};
~MotionState() {};
virtual void getWorldTransform(btTransform &trans) const;
virtual void setWorldTransform(const btTransform &trans);
private:
BulletRigidBodyNode *_node;
};
btRigidBody *_body;
MotionState *_motion;
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
public: public:

View File

@ -21,7 +21,7 @@
INLINE BulletSoftBodyNode:: INLINE BulletSoftBodyNode::
~BulletSoftBodyNode() { ~BulletSoftBodyNode() {
delete _body; delete _soft;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -32,12 +32,16 @@ TypeHandle BulletSoftBodyNode::_type_handle;
BulletSoftBodyNode:: BulletSoftBodyNode::
BulletSoftBodyNode(btSoftBody *body, const char *name) : BulletBodyNode(name) { BulletSoftBodyNode(btSoftBody *body, const char *name) : BulletBodyNode(name) {
// Setup body // Synchronised transform
_body = body; _sync = TransformState::make_identity();
_body->setUserPointer(this); _sync_disable = false;
// Softbody
_soft = body;
_soft->setUserPointer(this);
// Shape // Shape
btCollisionShape *shape_ptr = _body->getCollisionShape(); btCollisionShape *shape_ptr = _soft->getCollisionShape();
nassertv(shape_ptr != NULL); nassertv(shape_ptr != NULL);
nassertv(shape_ptr->getShapeType() == SOFTBODY_SHAPE_PROXYTYPE); nassertv(shape_ptr->getShapeType() == SOFTBODY_SHAPE_PROXYTYPE);
@ -58,7 +62,7 @@ BulletSoftBodyNode(btSoftBody *body, const char *name) : BulletBodyNode(name) {
btCollisionObject *BulletSoftBodyNode:: btCollisionObject *BulletSoftBodyNode::
get_object() const { get_object() const {
return _body; return _soft;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -69,7 +73,7 @@ get_object() const {
BulletSoftBodyConfig BulletSoftBodyNode:: BulletSoftBodyConfig BulletSoftBodyNode::
get_cfg() { get_cfg() {
return BulletSoftBodyConfig(_body->m_cfg); return BulletSoftBodyConfig(_soft->m_cfg);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -80,7 +84,7 @@ get_cfg() {
BulletSoftBodyWorldInfo BulletSoftBodyNode:: BulletSoftBodyWorldInfo BulletSoftBodyNode::
get_world_info() { get_world_info() {
return BulletSoftBodyWorldInfo(*(_body->m_worldInfo)); return BulletSoftBodyWorldInfo(*(_soft->m_worldInfo));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -91,7 +95,7 @@ get_world_info() {
int BulletSoftBodyNode:: int BulletSoftBodyNode::
get_num_materials() const { get_num_materials() const {
return _body->m_materials.size(); return _soft->m_materials.size();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -104,7 +108,21 @@ get_material(int idx) const {
nassertr(idx >= 0 && idx < get_num_materials(), BulletSoftBodyMaterial::empty()); nassertr(idx >= 0 && idx < get_num_materials(), BulletSoftBodyMaterial::empty());
btSoftBody::Material *material = _body->m_materials[idx]; btSoftBody::Material *material = _soft->m_materials[idx];
return BulletSoftBodyMaterial(*material);
}
////////////////////////////////////////////////////////////////////
// Function: BulletSoftBodyNode::append_material
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
BulletSoftBodyMaterial BulletSoftBodyNode::
append_material() {
btSoftBody::Material *material = _soft->appendMaterial();
nassertr(material, BulletSoftBodyMaterial::empty());
return BulletSoftBodyMaterial(*material); return BulletSoftBodyMaterial(*material);
} }
@ -116,7 +134,7 @@ get_material(int idx) const {
int BulletSoftBodyNode:: int BulletSoftBodyNode::
get_num_nodes() const { get_num_nodes() const {
return _body->m_nodes.size(); return _soft->m_nodes.size();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -128,21 +146,7 @@ BulletSoftBodyNodeElement BulletSoftBodyNode::
get_node(int idx) const { get_node(int idx) const {
nassertr(idx >=0 && idx < get_num_nodes(), BulletSoftBodyNodeElement::empty()); nassertr(idx >=0 && idx < get_num_nodes(), BulletSoftBodyNodeElement::empty());
return BulletSoftBodyNodeElement(_body->m_nodes[idx]); return BulletSoftBodyNodeElement(_soft->m_nodes[idx]);
}
////////////////////////////////////////////////////////////////////
// Function: BulletSoftBodyNode::append_material
// Access: Published
// Description:
////////////////////////////////////////////////////////////////////
BulletSoftBodyMaterial BulletSoftBodyNode::
append_material() {
btSoftBody::Material *material = _body->appendMaterial();
nassertr(material, BulletSoftBodyMaterial::empty());
return BulletSoftBodyMaterial(*material);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -154,10 +158,10 @@ void BulletSoftBodyNode::
generate_bending_constraints(int distance, BulletSoftBodyMaterial *material) { generate_bending_constraints(int distance, BulletSoftBodyMaterial *material) {
if (material) { if (material) {
_body->generateBendingConstraints(distance, &(material->get_material())); _soft->generateBendingConstraints(distance, &(material->get_material()));
} }
else { else {
_body->generateBendingConstraints(distance); _soft->generateBendingConstraints(distance);
} }
} }
@ -169,18 +173,7 @@ generate_bending_constraints(int distance, BulletSoftBodyMaterial *material) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
randomize_constraints() { randomize_constraints() {
_body->randomizeConstraints(); _soft->randomizeConstraints();
}
////////////////////////////////////////////////////////////////////
// Function: BulletSoftBodyNode::parents_changed
// Access: Protected
// Description:
////////////////////////////////////////////////////////////////////
void BulletSoftBodyNode::
parents_changed() {
transform_changed();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -191,24 +184,52 @@ parents_changed() {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
transform_changed() { transform_changed() {
if (_disable_transform_changed) return; if (_sync_disable) return;
btTransform trans = btTransform::getIdentity(); NodePath np = NodePath::any_path((PandaNode *)this);
get_node_transform(trans, this); CPT(TransformState) ts = np.get_net_transform();
trans *= _body->m_initialWorldTransform.inverse();
_body->transform(trans);
BulletBodyNode::transform_changed(); LMatrix4f m_sync = _sync->get_mat();
LMatrix4f m_ts = ts->get_mat();
if (!m_sync.almost_equal(m_ts)) {
_sync = ts;
btTransform trans = TransformState_to_btTrans(ts);
trans *= _soft->m_initialWorldTransform.inverse();
_soft->transform(trans);
if (ts->has_scale()) {
LVecBase3f scale = ts->get_scale();
for (int i=0; i<get_num_shapes(); i++) {
PT(BulletShape) shape = _shapes[i];
shape->set_local_scale(scale);
}
}
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletSoftBodyNode::post_step // Function: BulletSoftBodyNode::sync_p2b
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletSoftBodyNode:: void BulletSoftBodyNode::
post_step() { sync_p2b() {
transform_changed();
}
////////////////////////////////////////////////////////////////////
// Function: BulletSoftBodyNode::sync_b2p
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void BulletSoftBodyNode::
sync_b2p() {
// Render softbody
if (_geom) { if (_geom) {
btTransform trans = btTransform::getIdentity(); btTransform trans = btTransform::getIdentity();
get_node_transform(trans, this); get_node_transform(trans, this);
@ -221,7 +242,7 @@ post_step() {
GeomVertexReader flips(vdata, BulletHelper::get_sb_flip()); GeomVertexReader flips(vdata, BulletHelper::get_sb_flip());
while (!vertices.is_at_end()) { while (!vertices.is_at_end()) {
btSoftBody::Node node = _body->m_nodes[indices.get_data1i()]; btSoftBody::Node node = _soft->m_nodes[indices.get_data1i()];
btVector3 v = trans.invXform(node.m_x); btVector3 v = trans.invXform(node.m_x);
btVector3 n = node.m_n; btVector3 n = node.m_n;
@ -233,7 +254,7 @@ post_step() {
} }
if (_curve) { if (_curve) {
btSoftBody::tNodeArray &nodes(_body->m_nodes); btSoftBody::tNodeArray &nodes(_soft->m_nodes);
for (int i=0; i < nodes.size(); i++) { for (int i=0; i < nodes.size(); i++) {
btVector3 pos = nodes[i].m_x; btVector3 pos = nodes[i].m_x;
@ -242,7 +263,7 @@ post_step() {
} }
if (_surface) { if (_surface) {
btSoftBody::tNodeArray &nodes(_body->m_nodes); btSoftBody::tNodeArray &nodes(_soft->m_nodes);
int num_u = _surface->get_num_u_vertices(); int num_u = _surface->get_num_u_vertices();
int num_v = _surface->get_num_v_vertices(); int num_v = _surface->get_num_v_vertices();
@ -260,11 +281,18 @@ post_step() {
// set_bounds does not store the pointer - it makes a copy using // set_bounds does not store the pointer - it makes a copy using
// volume->make_copy(). // volume->make_copy().
BoundingBox bb = this->get_aabb(); BoundingBox bb = this->get_aabb();
CPT(TransformState) xform = TransformState::make_pos(bb.get_approx_center()); LVecBase3f pos = bb.get_approx_center();
_disable_transform_changed = true; NodePath np = NodePath::any_path((PandaNode *)this);
this->set_transform(xform); LVecBase3f scale = np.get_net_transform()->get_scale();
_disable_transform_changed = false;
CPT(TransformState) ts = TransformState::make_pos(pos);
ts = ts->set_scale(scale);
_sync = ts;
_sync_disable = true;
np.set_transform(NodePath(), ts);
_sync_disable = false;
Thread *current_thread = Thread::get_current_thread(); Thread *current_thread = Thread::get_current_thread();
this->r_mark_geom_bounds_stale(current_thread); this->r_mark_geom_bounds_stale(current_thread);
@ -289,7 +317,7 @@ get_closest_node_index(LVecBase3f point, bool local) {
get_node_transform(trans, this); get_node_transform(trans, this);
} }
btSoftBody::tNodeArray &nodes(_body->m_nodes); btSoftBody::tNodeArray &nodes(_soft->m_nodes);
int node_idx = 0; int node_idx = 0;
for (int i=0; i<nodes.size(); ++i) { for (int i=0; i<nodes.size(); ++i) {
@ -317,6 +345,8 @@ link_geom(Geom *geom) {
nassertv(geom->get_vertex_data()->has_column(InternalName::get_vertex())); nassertv(geom->get_vertex_data()->has_column(InternalName::get_vertex()));
nassertv(geom->get_vertex_data()->has_column(InternalName::get_normal())); nassertv(geom->get_vertex_data()->has_column(InternalName::get_normal()));
sync_p2b();
_geom = geom; _geom = geom;
PT(GeomVertexData) vdata = _geom->modify_vertex_data(); PT(GeomVertexData) vdata = _geom->modify_vertex_data();
@ -362,7 +392,7 @@ unlink_geom() {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
link_curve(NurbsCurveEvaluator *curve) { link_curve(NurbsCurveEvaluator *curve) {
nassertv(curve->get_num_vertices() == _body->m_nodes.size()); nassertv(curve->get_num_vertices() == _soft->m_nodes.size());
_curve = curve; _curve = curve;
} }
@ -386,7 +416,7 @@ unlink_curve() {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
link_surface(NurbsSurfaceEvaluator *surface) { link_surface(NurbsSurfaceEvaluator *surface) {
nassertv(surface->get_num_u_vertices() * surface->get_num_v_vertices() == _body->m_nodes.size()); nassertv(surface->get_num_u_vertices() * surface->get_num_v_vertices() == _soft->m_nodes.size());
_surface = surface; _surface = surface;
} }
@ -413,7 +443,7 @@ get_aabb() const {
btVector3 pMin; btVector3 pMin;
btVector3 pMax; btVector3 pMax;
_body->getAabb(pMin, pMax); _soft->getAabb(pMin, pMax);
return BoundingBox( return BoundingBox(
btVector3_to_LPoint3f(pMin), btVector3_to_LPoint3f(pMin),
@ -429,7 +459,7 @@ get_aabb() const {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_volume_mass(float mass) { set_volume_mass(float mass) {
_body->setVolumeMass(mass); _soft->setVolumeMass(mass);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -440,7 +470,7 @@ set_volume_mass(float mass) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_total_mass(float mass, bool fromfaces) { set_total_mass(float mass, bool fromfaces) {
_body->setTotalMass(mass, fromfaces); _soft->setTotalMass(mass, fromfaces);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -451,7 +481,7 @@ set_total_mass(float mass, bool fromfaces) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_volume_density(float density) { set_volume_density(float density) {
_body->setVolumeDensity(density); _soft->setVolumeDensity(density);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -462,7 +492,7 @@ set_volume_density(float density) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_total_density(float density) { set_total_density(float density) {
_body->setTotalDensity(density); _soft->setTotalDensity(density);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -473,7 +503,7 @@ set_total_density(float density) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_mass(int node, float mass) { set_mass(int node, float mass) {
_body->setMass(node, mass); _soft->setMass(node, mass);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -484,7 +514,7 @@ set_mass(int node, float mass) {
float BulletSoftBodyNode:: float BulletSoftBodyNode::
get_mass(int node) const { get_mass(int node) const {
return _body->getMass(node); return _soft->getMass(node);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -495,7 +525,7 @@ get_mass(int node) const {
float BulletSoftBodyNode:: float BulletSoftBodyNode::
get_total_mass() const { get_total_mass() const {
return _body->getTotalMass(); return _soft->getTotalMass();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -506,7 +536,7 @@ get_total_mass() const {
float BulletSoftBodyNode:: float BulletSoftBodyNode::
get_volume() const { get_volume() const {
return _body->getVolume(); return _soft->getVolume();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -518,7 +548,7 @@ void BulletSoftBodyNode::
add_force(const LVector3f &force) { add_force(const LVector3f &force) {
nassertv(!force.is_nan()); nassertv(!force.is_nan());
_body->addForce(LVecBase3f_to_btVector3(force)); _soft->addForce(LVecBase3f_to_btVector3(force));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -530,7 +560,7 @@ void BulletSoftBodyNode::
add_force(const LVector3f &force, int node) { add_force(const LVector3f &force, int node) {
nassertv(!force.is_nan()); nassertv(!force.is_nan());
_body->addForce(LVecBase3f_to_btVector3(force), node); _soft->addForce(LVecBase3f_to_btVector3(force), node);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -542,7 +572,7 @@ void BulletSoftBodyNode::
set_velocity(const LVector3f &velocity) { set_velocity(const LVector3f &velocity) {
nassertv(!velocity.is_nan()); nassertv(!velocity.is_nan());
_body->setVelocity(LVecBase3f_to_btVector3(velocity)); _soft->setVelocity(LVecBase3f_to_btVector3(velocity));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -554,7 +584,7 @@ void BulletSoftBodyNode::
add_velocity(const LVector3f &velocity) { add_velocity(const LVector3f &velocity) {
nassertv(!velocity.is_nan()); nassertv(!velocity.is_nan());
_body->addVelocity(LVecBase3f_to_btVector3(velocity)); _soft->addVelocity(LVecBase3f_to_btVector3(velocity));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -566,7 +596,7 @@ void BulletSoftBodyNode::
add_velocity(const LVector3f &velocity, int node) { add_velocity(const LVector3f &velocity, int node) {
nassertv(!velocity.is_nan()); nassertv(!velocity.is_nan());
_body->addVelocity(LVecBase3f_to_btVector3(velocity), node); _soft->addVelocity(LVecBase3f_to_btVector3(velocity), node);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -577,7 +607,7 @@ add_velocity(const LVector3f &velocity, int node) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
generate_clusters(int k, int maxiterations) { generate_clusters(int k, int maxiterations) {
_body->generateClusters(k, maxiterations); _soft->generateClusters(k, maxiterations);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -588,7 +618,7 @@ generate_clusters(int k, int maxiterations) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
release_clusters() { release_clusters() {
_body->releaseClusters(); _soft->releaseClusters();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -599,7 +629,7 @@ release_clusters() {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
release_cluster(int index) { release_cluster(int index) {
_body->releaseCluster(index); _soft->releaseCluster(index);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -610,7 +640,7 @@ release_cluster(int index) {
int BulletSoftBodyNode:: int BulletSoftBodyNode::
get_num_clusters() const { get_num_clusters() const {
return _body->clusterCount(); return _soft->clusterCount();
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -621,7 +651,7 @@ get_num_clusters() const {
LVecBase3f BulletSoftBodyNode:: LVecBase3f BulletSoftBodyNode::
cluster_com(int cluster) const { cluster_com(int cluster) const {
return btVector3_to_LVecBase3f(_body->clusterCom(cluster)); return btVector3_to_LVecBase3f(_soft->clusterCom(cluster));
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -632,7 +662,7 @@ cluster_com(int cluster) const {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
set_pose(bool bvolume, bool bframe) { set_pose(bool bvolume, bool bframe) {
_body->setPose(bvolume, bframe); _soft->setPose(bvolume, bframe);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -643,11 +673,13 @@ set_pose(bool bvolume, bool bframe) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
append_anchor(int node, BulletRigidBodyNode *body, bool disable) { append_anchor(int node, BulletRigidBodyNode *body, bool disable) {
nassertv(node < _body->m_nodes.size()) nassertv(node < _soft->m_nodes.size())
nassertv(body); nassertv(body);
body->sync_p2b();
btRigidBody *ptr =(btRigidBody *)body->get_object(); btRigidBody *ptr =(btRigidBody *)body->get_object();
_body->appendAnchor(node, ptr, disable); _soft->appendAnchor(node, ptr, disable);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -658,12 +690,14 @@ append_anchor(int node, BulletRigidBodyNode *body, bool disable) {
void BulletSoftBodyNode:: void BulletSoftBodyNode::
append_anchor(int node, BulletRigidBodyNode *body, const LVector3f &pivot, bool disable) { append_anchor(int node, BulletRigidBodyNode *body, const LVector3f &pivot, bool disable) {
nassertv(node < _body->m_nodes.size()) nassertv(node < _soft->m_nodes.size())
nassertv(body); nassertv(body);
nassertv(!pivot.is_nan()); nassertv(!pivot.is_nan());
body->sync_p2b();
btRigidBody *ptr =(btRigidBody *)body->get_object(); btRigidBody *ptr =(btRigidBody *)body->get_object();
_body->appendAnchor(node, ptr, LVecBase3f_to_btVector3(pivot), disable); _soft->appendAnchor(node, ptr, LVecBase3f_to_btVector3(pivot), disable);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -188,14 +188,17 @@ PUBLISHED:
public: public:
virtual btCollisionObject *get_object() const; virtual btCollisionObject *get_object() const;
void post_step(); void sync_p2b();
void sync_b2p();
protected: protected:
virtual void parents_changed();
virtual void transform_changed(); virtual void transform_changed();
private: private:
btSoftBody *_body; btSoftBody *_soft;
CPT(TransformState) _sync;
bool _sync_disable;
PT(Geom) _geom; PT(Geom) _geom;
PT(NurbsCurveEvaluator) _curve; PT(NurbsCurveEvaluator) _curve;

View File

@ -218,12 +218,12 @@ get_wheel(int idx) const {
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletVehicle::post_step // Function: BulletVehicle::sync_b2p
// Access: Public // Access: Public
// Description: // Description:
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void BulletVehicle:: void BulletVehicle::
post_step() { sync_b2p() {
for (int i=0; i < get_num_wheels(); i++) { for (int i=0; i < get_num_wheels(); i++) {
btWheelInfo info = _vehicle->getWheelInfo(i); btWheelInfo info = _vehicle->getWheelInfo(i);

View File

@ -91,7 +91,7 @@ PUBLISHED:
public: public:
INLINE btRaycastVehicle *get_vehicle() const; INLINE btRaycastVehicle *get_vehicle() const;
void post_step(); void sync_b2p();
private: private:
btRaycastVehicle *_vehicle; btRaycastVehicle *_vehicle;

View File

@ -24,7 +24,8 @@ TypeHandle BulletWorld::_type_handle;
PStatCollector BulletWorld::_pstat_physics("App:Bullet:DoPhysics"); PStatCollector BulletWorld::_pstat_physics("App:Bullet:DoPhysics");
PStatCollector BulletWorld::_pstat_simulation("App:Bullet:DoPhysics:Simulation"); PStatCollector BulletWorld::_pstat_simulation("App:Bullet:DoPhysics:Simulation");
PStatCollector BulletWorld::_pstat_debug("App:Bullet:DoPhysics:Debug"); PStatCollector BulletWorld::_pstat_debug("App:Bullet:DoPhysics:Debug");
PStatCollector BulletWorld::_pstat_sb("App:Bullet:DoPhysics:SoftBodies"); PStatCollector BulletWorld::_pstat_p2b("App:Bullet:DoPhysics:SyncP2B");
PStatCollector BulletWorld::_pstat_b2p("App:Bullet:DoPhysics:SyncB2P");
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletWorld::Constructor // Function: BulletWorld::Constructor
@ -140,49 +141,86 @@ do_physics(float dt, int substeps, float stepsize) {
_pstat_physics.start(); _pstat_physics.start();
// Preprocess characters // Synchronize Panda to Bullet
for (int i=0; i < get_num_characters(); i++) { _pstat_p2b.start();
get_character(i)->pre_step(dt); sync_p2b(dt);
} _pstat_p2b.stop();
// Preprocess ghosts (autosync)
for (int i=0; i < get_num_ghosts(); i++) {
get_ghost(i)->pre_step();
}
// Simulation // Simulation
_pstat_simulation.start(); _pstat_simulation.start();
_world->stepSimulation(dt, substeps, stepsize); _world->stepSimulation(dt, substeps, stepsize);
_pstat_simulation.stop(); _pstat_simulation.stop();
// Postprocess characters // Synchronize Bullet to Panda
for (int i=0; i < get_num_characters(); i++) { _pstat_b2p.start();
get_character(i)->post_step(); sync_b2p();
} _info.m_sparsesdf.GarbageCollect(bullet_gc_lifetime);
_pstat_b2p.stop();
// Postprocess vehicles
for (int i=0; i < get_num_vehicles(); i++) {
get_vehicle(i)->post_step();
}
// Render debug // Render debug
_pstat_debug.start();
if (_debug) { if (_debug) {
_debug->post_step(_world); _pstat_debug.start();
_debug->sync_b2p(_world);
_pstat_debug.stop();
} }
_pstat_debug.stop();
// Render soft bodies
_pstat_sb.start();
for (int i=0; i < get_num_soft_bodies(); i++) {
get_soft_body(i)->post_step();
}
_info.m_sparsesdf.GarbageCollect(bullet_gc_lifetime);
_pstat_sb.stop();
_pstat_physics.stop(); _pstat_physics.stop();
} }
////////////////////////////////////////////////////////////////////
// Function: BulletWorld::sync_p2b
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void BulletWorld::
sync_p2b(float dt) {
for (int i=0; i < get_num_rigid_bodies(); i++) {
get_rigid_body(i)->sync_p2b();
}
for (int i=0; i < get_num_soft_bodies(); i++) {
get_soft_body(i)->sync_p2b();
}
for (int i=0; i < get_num_ghosts(); i++) {
get_ghost(i)->sync_p2b();
}
for (int i=0; i < get_num_characters(); i++) {
get_character(i)->sync_p2b(dt);
}
}
////////////////////////////////////////////////////////////////////
// Function: BulletWorld::sync_b2p
// Access: Private
// Description:
////////////////////////////////////////////////////////////////////
void BulletWorld::
sync_b2p() {
for (int i=0; i < get_num_vehicles(); i++) {
get_vehicle(i)->sync_b2p();
}
for (int i=0; i < get_num_rigid_bodies(); i++) {
get_rigid_body(i)->sync_b2p();
}
for (int i=0; i < get_num_soft_bodies(); i++) {
get_soft_body(i)->sync_b2p();
}
for (int i=0; i < get_num_ghosts(); i++) {
get_ghost(i)->sync_b2p();
}
for (int i=0; i < get_num_characters(); i++) {
get_character(i)->sync_b2p();
}
}
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
// Function: BulletWorld::set_debug_node // Function: BulletWorld::set_debug_node
// Access: Published // Access: Published
@ -325,7 +363,7 @@ attach_ghost(BulletGhostNode *node) {
// TODO group/filter settings... // TODO group/filter settings...
/* /*
enum CollisionFilterGroups { enum CollisionFilterGroups {
DefaultFilter = 1, DefaultFilter = 1,
StaticFilter = 2, StaticFilter = 2,
KinematicFilter = 4, KinematicFilter = 4,

View File

@ -151,6 +151,9 @@ public:
INLINE btDispatcher *get_dispatcher() const; INLINE btDispatcher *get_dispatcher() const;
private: private:
void sync_p2b(float dt);
void sync_b2p();
typedef PTA(PT(BulletRigidBodyNode)) BulletRigidBodies; typedef PTA(PT(BulletRigidBodyNode)) BulletRigidBodies;
typedef PTA(PT(BulletSoftBodyNode)) BulletSoftBodies; typedef PTA(PT(BulletSoftBodyNode)) BulletSoftBodies;
typedef PTA(PT(BulletGhostNode)) BulletGhosts; typedef PTA(PT(BulletGhostNode)) BulletGhosts;
@ -161,7 +164,8 @@ private:
static PStatCollector _pstat_physics; static PStatCollector _pstat_physics;
static PStatCollector _pstat_simulation; static PStatCollector _pstat_simulation;
static PStatCollector _pstat_debug; static PStatCollector _pstat_debug;
static PStatCollector _pstat_sb; static PStatCollector _pstat_p2b;
static PStatCollector _pstat_b2p;
struct btFilterCallback : public btOverlapFilterCallback { struct btFilterCallback : public btOverlapFilterCallback {
virtual bool needBroadphaseCollision( virtual bool needBroadphaseCollision(