Hello, our friends
I’m afraid if this forum is an appropriate place to post a bug report, but
I’d like to report a runtime error about BulletSoftBodyNode.appendAngularJoint()
in the following version of Panda3D.
Version: Development SDK Panda3D-2013.06.21-40.exe for Windows.
Language: Python
That error happened in BulletWorld.do_physics() after calling
BulletSoftBodyNode.appendAngularJoint() as follows.
softBody.appendAngularJoint(rigidBody, axis=Vec3(0, 1, 0), erp=0.5)
The cause of the runtime error seems as follows. BulletSoftBodyNode::append_angular_joint() in
the C++ source code is declared so that the argument ‘control’ should be NULL in default.
void append_angular_joint(BulletBodyNode *body, const LVector3 &axis,
PN_stdfloat erp=1.0,
PN_stdfloat cfm=1.0,
PN_stdfloat split=1.0,
BulletSoftBodyControl *control=NULL);
The argument ‘control’ is then stored by a btSoftBody instance. Because btSoftBody::AJoint
does no NULL check when using btSoftBody::AJoint::m_icontrol to solve constraints,
that NULL in ‘control’ causes an access violation.
One way to avoid that runtime error is to specify a BulletSoftBodyControl instance
for the argument ‘control’ explicitly, and keep the instance from getting released
while repeatedly executing doPhysics().
self.dummyCtrl = BulletSoftBodyControl()
softBody.appendAngularJoint(rigidBody, axis=Vec3(0, 1, 0), erp=0.5, cfm=1.0, split=0,
control=self.dummyCtrl)
It would be nice if BulletSoftBodyNode::append_angular_joint() is changed either
- to do NULL check:
void BulletSoftBodyNode::
append_angular_joint(BulletBodyNode *body, const LVector3 &axis, PN_stdfloat erp, PN_stdfloat
cfm, PN_stdfloat split, BulletSoftBodyControl *control) {
// ... omitted ...
btSoftBody::AJoint::Specs as;
// --> The constructor initializes as.control = btSoftBody::AJoint::IControl::Default()
// ... omitted ...
if(control != NULL){
as.icontrol = control;
}
// ... omitted ...
}
- Or, to have an appropriate default instance instead of NULL for the ‘control’ argument:
// In bulletSoftBodyNode.cxx
void append_angular_joint(BulletBodyNode *body, const LVector3 &axis,
PN_stdfloat erp=1.0,
PN_stdfloat cfm=1.0,
PN_stdfloat split=1.0,
BulletSoftBodyControl *control=static_cast<BulletSoftBodyControl*>(BulletSoftBodyControl::Default()));
// --> Default() is a static member function inherited from the base class btSoftBody::AJoint::IControl.
- Or, to do the same as above by appropriately overriding that static Default()
member function in BulletSoftBodyControl:
void append_angular_joint(BulletBodyNode *body, const LVector3 &axis,
PN_stdfloat erp=1.0,
PN_stdfloat cfm=1.0,
PN_stdfloat split=1.0,
BulletSoftBodyControl *control=BulletSoftBodyControl::Default());
// --> overridden Default().
I think that the option 3 above would be better than the others for its extensibility.
Regards,