Joint.cpp 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. enum JOINT_TYPE : Byte
  6. {
  7. JOINT_NONE ,
  8. JOINT_FIXED ,
  9. JOINT_HINGE ,
  10. JOINT_SPHERICAL,
  11. JOINT_SLIDER ,
  12. JOINT_DISTANCE ,
  13. };
  14. /******************************************************************************/
  15. #if PHYSX
  16. #define BOUNCE 0.1f
  17. #define DAMPING 0.5f*0
  18. #define SPRING 1.0f*0
  19. /*struct SphericalJoint : PxJoint, PxConstraintConnector
  20. {
  21. static const PxU32 TYPE_ID = PxConcreteType::eFIRST_USER_EXTENSION;
  22. // PxJoint
  23. virtual void setActors(PxRigidActor* actor0, PxRigidActor* actor1)override {}
  24. virtual void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1)const override {}
  25. virtual void setLocalPose(PxJointActorIndex::Enum actor, const PxTransform& localPose)override {}
  26. virtual PxTransform getLocalPose(PxJointActorIndex::Enum actor)const override {}
  27. virtual PxTransform getRelativeTransform()const override {}
  28. virtual PxVec3 getRelativeLinearVelocity()const override {}
  29. virtual PxVec3 getRelativeAngularVelocity()const override {}
  30. virtual void setBreakForce(PxReal force, PxReal torque)override {}
  31. virtual void getBreakForce(PxReal& force, PxReal& torque)const override {}
  32. virtual void setConstraintFlags(PxConstraintFlags flags)override {}
  33. virtual void setConstraintFlag(PxConstraintFlag::Enum flag, bool value)override {}
  34. virtual PxConstraintFlags getConstraintFlags()const override {}
  35. virtual void setInvMassScale0(PxReal invMassScale)override {}
  36. virtual PxReal getInvMassScale0()const override {}
  37. virtual void setInvInertiaScale0(PxReal invInertiaScale) override {}
  38. virtual PxReal getInvInertiaScale0()const override {}
  39. virtual void setInvMassScale1(PxReal invMassScale)override {}
  40. virtual PxReal getInvMassScale1()const override {}
  41. virtual void setInvInertiaScale1(PxReal invInertiaScale)override {}
  42. virtual PxReal getInvInertiaScale1()const override {}
  43. virtual PxConstraint* getConstraint()const override {}
  44. virtual void setName(const char* name)override {}
  45. virtual const char* getName()const override {}
  46. virtual void release()override {}
  47. virtual PxScene* getScene()const override {}
  48. // PxConstraintConnector
  49. virtual void* prepareData()override {}
  50. virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint* c, PxPvdUpdateType::Enum updateType)const override {}
  51. virtual void onConstraintRelease()override {}
  52. virtual void onComShift(PxU32 actor)override {}
  53. virtual void onOriginShift(const PxVec3& shift)override {}
  54. virtual void* getExternalReference(PxU32& typeID)override {}
  55. virtual PxBase* getSerializable()override {}
  56. virtual PxConstraintSolverPrep getPrep()const override {}
  57. virtual const void* getConstantBlock()const override {}
  58. };*/
  59. #else
  60. struct btDistanceConstraint : btPoint2PointConstraint
  61. {
  62. Bool spring;
  63. Flt min_dist, max_dist, spring_spring, spring_damper;
  64. btDistanceConstraint(btRigidBody& rbA, const btVector3& pivotInA, Flt min_dist, Flt max_dist, Bool spring, Flt spring_spring, Flt spring_damper) : btPoint2PointConstraint(rbA, pivotInA)
  65. {
  66. T.min_dist =min_dist ;
  67. T.max_dist =max_dist ;
  68. T.spring =spring ;
  69. T.spring_spring=spring_spring;
  70. T.spring_damper=spring_damper;
  71. }
  72. btDistanceConstraint(btRigidBody& rbA, btRigidBody& rbB, const btVector3& pivotInA, const btVector3& pivotInB, Flt min_dist, Flt max_dist, Bool spring, Flt spring_spring, Flt spring_damper) : btPoint2PointConstraint(rbA, rbB, pivotInA, pivotInB)
  73. {
  74. T.min_dist =min_dist ;
  75. T.max_dist =max_dist ;
  76. T.spring =spring ;
  77. T.spring_spring=spring_spring;
  78. T.spring_damper=spring_damper;
  79. }
  80. virtual void getInfo1(btConstraintInfo1 *info)
  81. {
  82. info->m_numConstraintRows=1;
  83. info->nub=5;
  84. }
  85. virtual void getInfo2(btConstraintInfo2 *info)
  86. {
  87. btVector3 relA = m_rbA.getCenterOfMassTransform().getBasis() * getPivotInA();
  88. btVector3 relB = m_rbB.getCenterOfMassTransform().getBasis() * getPivotInB();
  89. btVector3 posA = m_rbA.getCenterOfMassTransform().getOrigin() + relA;
  90. btVector3 posB = m_rbB.getCenterOfMassTransform().getOrigin() + relB;
  91. btVector3 del = posB - posA;
  92. btScalar currDist = btSqrt(del.dot(del));
  93. btVector3 ortho = (currDist ? del / currDist : btVector3(0, 0, 0));
  94. info->m_J1linearAxis[0] = ortho[0];
  95. info->m_J1linearAxis[1] = ortho[1];
  96. info->m_J1linearAxis[2] = ortho[2];
  97. btVector3 p, q;
  98. p = relA.cross(ortho);
  99. q = relB.cross(ortho);
  100. info->m_J1angularAxis[0] = p[0];
  101. info->m_J1angularAxis[1] = p[1];
  102. info->m_J1angularAxis[2] = p[2];
  103. info->m_J2angularAxis[0] = -q[0];
  104. info->m_J2angularAxis[1] = -q[1];
  105. info->m_J2angularAxis[2] = -q[2];
  106. btScalar rhs = (currDist - 0/*m_distance*/) * info->fps * info->erp * (spring ? spring_spring*0.01f : 1);
  107. info->m_constraintError[0] = rhs;
  108. info->cfm[0] = btScalar(0.f);
  109. info->m_lowerLimit[0] = -SIMD_INFINITY;
  110. info->m_upperLimit[0] = SIMD_INFINITY;
  111. }
  112. };
  113. #endif
  114. /******************************************************************************/
  115. Joint& Joint::del()
  116. {
  117. if(_joint)
  118. {
  119. SafeWriteLock lock(Physics._rws);
  120. if(_joint)
  121. {
  122. #if PHYSX
  123. if(Physx.world)_joint->release(); _joint=null;
  124. #else
  125. if(_joint->needsFeedback())Bullet.breakables.exclude(_joint); // remove from breakable list
  126. if(Bullet.world)Bullet.world->removeConstraint(_joint); // remove from world
  127. Delete(_joint);
  128. #endif
  129. }
  130. }
  131. return T;
  132. }
  133. /******************************************************************************/
  134. static Bool ValidActors(Actor &a0, Actor *a1) // PhysX will still create joint for null actors, and creating for static only will even create a crash
  135. {
  136. return a0.is() && (a1 ? a1->is() : true) // make sure that both exist
  137. #if PHYSX
  138. && (a0.isDynamic() || (a1 && a1->isDynamic())) // for PhysX make sure that at least one is dynamic
  139. #endif
  140. ;
  141. }
  142. /******************************************************************************/
  143. Joint& Joint::create(Actor &a0, Actor *a1)
  144. {
  145. WriteLock lock(Physics._rws);
  146. del();
  147. #if PHYSX
  148. if(Physx.world && ValidActors(a0, a1))
  149. if(PxFixedJoint *fixed=PxFixedJointCreate(*Physx.physics, a0._actor, PxTransform(PxIdentity), a1 ? a1->_actor : null, Physx.matrix(a1 ? a0.matrix().divNormalized(a1->matrix()) : a0.matrix()))) // when specifying world matrix use current a0 world position, when specifying local frame for a1 use current a0 position in a1 space
  150. {
  151. fixed->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED, false);
  152. _joint=fixed;
  153. }
  154. #else
  155. if(a0._actor)
  156. {
  157. btGeneric6DofConstraint *dof=null;
  158. if(a1 && a1->_actor)
  159. {
  160. dof=new btGeneric6DofConstraint(*a0._actor, *a1->_actor, btTransform::getIdentity(), Bullet.matrix(a0.massCenterMatrix()/a1->massCenterMatrix()), false);
  161. }else
  162. {
  163. dof=new btGeneric6DofConstraint(*a0._actor, btTransform::getIdentity(), false);
  164. }
  165. dof->setAngularLowerLimit(btVector3(0, 0, 0));
  166. dof->setAngularUpperLimit(btVector3(0, 0, 0));
  167. dof->setLinearLowerLimit (btVector3(0, 0, 0));
  168. dof->setLinearUpperLimit (btVector3(0, 0, 0));
  169. if(_joint=dof)
  170. {
  171. Flt f=FLT_MAX;
  172. _joint->setUserConstraintId((Int&)f);
  173. _joint->setUserConstraintType(0);
  174. if(Bullet.world)Bullet.world->addConstraint(_joint, true);
  175. }
  176. }
  177. #endif
  178. return T;
  179. }
  180. /******************************************************************************/
  181. static void CreateHinge(Joint &joint, Actor &a0, Actor *a1, C Vec local_anchor[2], C Vec local_axis[2], C Vec local_normal[2], Bool limit_angle, Bool body, Flt angle_min, Flt angle_max, Bool collision)
  182. {
  183. #if PHYSX
  184. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.y=local_normal[0]; m0.z=Cross(m0.x, m0.y);
  185. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.y=local_normal[1]; m1.z=Cross(m1.x, m1.y);
  186. WriteLock lock(Physics._rws);
  187. if(Physx.world && ValidActors(a0, a1))
  188. if(PxRevoluteJoint *hinge=PxRevoluteJointCreate(*Physx.physics, a0._actor, Physx.matrix(m0), a1 ? a1->_actor : null, Physx.matrix(m1)))
  189. {
  190. hinge->setConstraintFlag (PxConstraintFlag ::eCOLLISION_ENABLED, collision );
  191. hinge->setRevoluteJointFlag(PxRevoluteJointFlag::eLIMIT_ENABLED , limit_angle);
  192. PxJointAngularLimitPair limit(-angle_max, -angle_min); if(body){limit.restitution=BOUNCE; limit.stiffness=SPRING; limit.damping=DAMPING;} hinge->setLimit(limit);
  193. joint._joint=hinge;
  194. }
  195. #else
  196. if(a0._actor)
  197. {
  198. Matrix m0; m0.pos=local_anchor[0]; m0.z=local_axis[0]; m0.x=local_normal[0]; m0.y=Cross(m0.z, m0.x); m0*=a0. _actor->offset;
  199. Matrix m1; m1.pos=local_anchor[1]; m1.z=local_axis[1]; m1.x=local_normal[1]; m1.y=Cross(m1.z, m1.x); if(a1 && a1->_actor)m1*=a1->_actor->offset;
  200. btHingeConstraint *hinge=null;
  201. if(a1 && a1->_actor)
  202. {
  203. hinge=new btHingeConstraint(*a0._actor, *a1->_actor, Bullet.matrix(m0), Bullet.matrix(m1));
  204. }else
  205. {
  206. hinge=new btHingeConstraint(*a0._actor, Bullet.matrix(m0)); hinge->getBFrame()=Bullet.matrix(m1);
  207. }
  208. if(joint._joint=hinge)
  209. {
  210. Flt f=FLT_MAX;
  211. hinge->setUserConstraintId((Int&)f);
  212. hinge->setUserConstraintType(0);
  213. if(limit_angle)hinge->setLimit(angle_min, angle_max);
  214. WriteLock lock(Physics._rws);
  215. if(Bullet.world)Bullet.world->addConstraint(hinge, !collision);
  216. }
  217. }
  218. #endif
  219. }
  220. /******************************************************************************/
  221. static void CreateSpherical(Joint &joint, Actor &a0, Actor *a1, C Vec local_anchor[2], C Vec local_axis[2], C Vec local_normal[2], Bool collision, Bool limit_swing, Bool limit_twist, Bool body, Flt swing, Flt twist)
  222. {
  223. #if PHYSX
  224. #if 0 // PxSphericalJoint
  225. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.y=local_normal[0]; m0.z=Cross(m0.x, m0.y);
  226. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.y=local_normal[1]; m1.z=Cross(m1.x, m1.y);
  227. WriteLock lock(Physics._rws);
  228. if(Physx.world && ValidActors(a0, a1))
  229. if(PxSphericalJoint *spherical=PxSphericalJointCreate(*Physx.physics, a0._actor, Physx.matrix(m0), a1 ? a1->_actor : null, Physx.matrix(m1)))
  230. {
  231. spherical->setConstraintFlag (PxConstraintFlag ::eCOLLISION_ENABLED , collision );
  232. spherical->setSphericalJointFlag(PxSphericalJointFlag::eLIMIT_ENABLED , limit_swing);
  233. spherical->setSphericalJointFlag(PxSphericalJointFlag::eTWIST_LIMIT_ENABLED, limit_twist);
  234. Clamp(swing, EPS, PI-EPS);
  235. Clamp(twist, EPS, PI-EPS);
  236. PxJointLimitCone limit(swing, swing); limit.twist=twist; if(body){limit.restitution=BOUNCE; limit.stiffness=SPRING; limit.damping=DAMPING;}
  237. spherical->setLimitCone(limit);
  238. joint._joint=spherical;
  239. }
  240. #else // PxD6Joint
  241. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.y=local_normal[0]; m0.z=Cross(m0.x, m0.y);
  242. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.y=local_normal[1]; m1.z=Cross(m1.x, m1.y);
  243. WriteLock lock(Physics._rws);
  244. if(Physx.world && ValidActors(a0, a1))
  245. if(PxD6Joint *spherical=PxD6JointCreate(*Physx.physics, a0._actor, Physx.matrix(m0), a1 ? a1->_actor : null, Physx.matrix(m1)))
  246. {
  247. spherical->setConstraintFlag(PxConstraintFlag::eCOLLISION_ENABLED , collision );
  248. spherical->setMotion (PxD6Axis::eSWING1, limit_swing ? PxD6Motion::eLIMITED : PxD6Motion::eFREE);
  249. spherical->setMotion (PxD6Axis::eSWING2, limit_swing ? PxD6Motion::eLIMITED : PxD6Motion::eFREE);
  250. spherical->setMotion (PxD6Axis::eTWIST , limit_twist ? PxD6Motion::eLIMITED : PxD6Motion::eFREE);
  251. if(limit_swing)
  252. {
  253. Clamp(swing, EPS, PI-EPS);
  254. PxJointLimitCone limit(swing, swing); if(body){limit.restitution=BOUNCE; limit.stiffness=SPRING; limit.damping=DAMPING;}
  255. spherical->setSwingLimit(limit);
  256. }
  257. if(limit_twist)
  258. {
  259. Clamp(twist, 0, PI);
  260. PxJointAngularLimitPair limit(-twist, twist); if(body){limit.restitution=BOUNCE; limit.stiffness=SPRING; limit.damping=DAMPING;}
  261. spherical->setTwistLimit(limit);
  262. }
  263. joint._joint=spherical;
  264. }
  265. #endif
  266. #else
  267. if(a0._actor)
  268. {
  269. if(!limit_swing && !limit_twist)
  270. {
  271. btPoint2PointConstraint *p2p=null;
  272. if(a1 && a1->_actor)
  273. {
  274. p2p=new btPoint2PointConstraint(*a0._actor, *a1->_actor, Bullet.vec(local_anchor[0]*a0._actor->offset), Bullet.vec(local_anchor[1]*a1->_actor->offset));
  275. }else
  276. {
  277. p2p=new btPoint2PointConstraint(*a0._actor, Bullet.vec(local_anchor[0]*a0._actor->offset)); p2p->setPivotB(Bullet.vec(local_anchor[1]));
  278. }
  279. if(joint._joint=p2p)
  280. {
  281. Flt f=FLT_MAX;
  282. p2p->setUserConstraintId((Int&)f);
  283. p2p->setUserConstraintType(0);
  284. WriteLock lock(Physics._rws);
  285. if(Bullet.world)Bullet.world->addConstraint(p2p, !collision);
  286. }
  287. }else
  288. {
  289. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.z=local_normal[0]; m0.y=Cross(m0.z, m0.x); m0*=a0. _actor->offset;
  290. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.z=local_normal[1]; m1.y=Cross(m1.z, m1.x); if(a1 && a1->_actor)m1*=a1->_actor->offset;
  291. btConeTwistConstraint *cone=null;
  292. if(a1 && a1->_actor)
  293. {
  294. cone=new btConeTwistConstraint(*a0._actor, *a1->_actor, Bullet.matrix(m0), Bullet.matrix(m1));
  295. }else
  296. {
  297. cone=new btConeTwistConstraint(*a0._actor, Bullet.matrix(m0)); cone->getBFrame()=Bullet.matrix(m1);
  298. }
  299. if(joint._joint=cone)
  300. {
  301. Flt f=FLT_MAX;
  302. cone->setUserConstraintId((Int&)f);
  303. cone->setUserConstraintType(0);
  304. cone->setLimit(limit_swing ? swing : FLT_MAX, limit_swing ? swing : FLT_MAX, limit_twist ? twist : FLT_MAX);
  305. WriteLock lock(Physics._rws);
  306. if(Bullet.world)Bullet.world->addConstraint(cone, !collision);
  307. }
  308. }
  309. }
  310. #endif
  311. }
  312. /******************************************************************************/
  313. static void CreateSlider(Joint &joint, Actor &a0, Actor *a1, C Vec local_anchor[2], C Vec local_axis[2], C Vec local_normal[2], Flt min, Flt max, Bool collision)
  314. {
  315. #if PHYSX
  316. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.y=local_normal[0]; m0.z=Cross(m0.x, m0.y);
  317. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.y=local_normal[1]; m1.z=Cross(m1.x, m1.y);
  318. WriteLock lock(Physics._rws);
  319. if(Physx.world && ValidActors(a0, a1))
  320. if(PxPrismaticJoint *slider=PxPrismaticJointCreate(*Physx.physics, a0._actor, Physx.matrix(m0), a1 ? a1->_actor : null, Physx.matrix(m1)))
  321. {
  322. slider->setConstraintFlag (PxConstraintFlag ::eCOLLISION_ENABLED, collision);
  323. slider->setPrismaticJointFlag(PxPrismaticJointFlag::eLIMIT_ENABLED , true );
  324. PxJointLinearLimitPair limit(Physx.physics->getTolerancesScale(), -max, -min); slider->setLimit(limit);
  325. joint._joint=slider;
  326. }
  327. #else
  328. if(a0._actor)
  329. {
  330. Matrix m0; m0.pos=local_anchor[0]; m0.x=local_axis[0]; m0.z=local_normal[0]; m0.y=Cross(m0.z, m0.x); m0*=a0. _actor->offset;
  331. Matrix m1; m1.pos=local_anchor[1]; m1.x=local_axis[1]; m1.z=local_normal[1]; m1.y=Cross(m1.z, m1.x); if(a1 && a1->_actor)m1*=a1->_actor->offset;
  332. btSliderConstraint *slider=null;
  333. if(a1 && a1->_actor)
  334. {
  335. slider=new btSliderConstraint(*a1->_actor, *a0._actor, Bullet.matrix(m1), Bullet.matrix(m0), true); // btSliderConstraint(bodyA, bodyB), because constructor below accepts B, to match order we need to swap here actor order
  336. }else
  337. {
  338. slider=new btSliderConstraint(*a0._actor, Bullet.matrix(m0), true); // btSliderConstraint(bodyB), this accepts B only
  339. slider->setFrames(Bullet.matrix(m1), Bullet.matrix(m0));
  340. }
  341. if(joint._joint=slider)
  342. {
  343. Flt f=FLT_MAX;
  344. slider->setUserConstraintId((Int&)f);
  345. slider->setUserConstraintType(0);
  346. slider->setLowerLinLimit(min);
  347. slider->setUpperLinLimit(max);
  348. WriteLock lock(Physics._rws);
  349. if(Bullet.world)Bullet.world->addConstraint(slider, !collision);
  350. }
  351. }
  352. #endif
  353. }
  354. /******************************************************************************/
  355. static void CreateDistance(Joint &joint, Actor &a0, Actor *a1, C Vec local_anchor[2], Flt min, Flt max, Bool collision, Bool spring, Flt spring_spring, Flt spring_damper)
  356. {
  357. #if PHYSX
  358. WriteLock lock(Physics._rws);
  359. if(Physx.world && ValidActors(a0, a1))
  360. if(PxDistanceJoint *distance=PxDistanceJointCreate(*Physx.physics, a0._actor, Physx.matrix(local_anchor[0]), a1 ? a1->_actor : null, Physx.matrix(local_anchor[1])))
  361. {
  362. distance->setConstraintFlag (PxConstraintFlag::eCOLLISION_ENABLED, collision);
  363. distance->setMinDistance (min);
  364. distance->setMaxDistance (max);
  365. distance->setStiffness (spring_spring);
  366. distance->setDamping (spring_damper);
  367. distance->setDistanceJointFlag(PxDistanceJointFlag::eMIN_DISTANCE_ENABLED, true );
  368. distance->setDistanceJointFlag(PxDistanceJointFlag::eMAX_DISTANCE_ENABLED, true );
  369. distance->setDistanceJointFlag(PxDistanceJointFlag::eSPRING_ENABLED , spring);
  370. joint._joint=distance;
  371. }
  372. #else
  373. if(a0._actor)
  374. {
  375. btDistanceConstraint *dist=null;
  376. if(a1 && a1->_actor)
  377. {
  378. dist=new btDistanceConstraint(*a0._actor, *a1->_actor, Bullet.vec(local_anchor[0]*a0._actor->offset), Bullet.vec(local_anchor[1]*a1->_actor->offset), min, max, spring, spring_spring, spring_damper);
  379. }else
  380. {
  381. dist=new btDistanceConstraint(*a0._actor, Bullet.vec(local_anchor[0]*a0._actor->offset), min, max, spring, spring_spring, spring_damper); dist->setPivotB(Bullet.vec(local_anchor[1]));
  382. }
  383. if(joint._joint=dist)
  384. {
  385. Flt f=FLT_MAX;
  386. dist->setUserConstraintId((Int&)f);
  387. dist->setUserConstraintType(0);
  388. WriteLock lock(Physics._rws);
  389. if(Bullet.world)Bullet.world->addConstraint(dist, !collision);
  390. }
  391. }
  392. #endif
  393. }
  394. /******************************************************************************/
  395. Joint& Joint::createHinge(Actor &a0, Actor *a1, C Vec &anchor, C Vec &axis, Bool collision)
  396. {
  397. del();
  398. Matrix m0 = a0. matrix(),
  399. m1 =(a1 ? a1->matrix() : MatrixIdentity);
  400. Vec normal =PerpN(axis),
  401. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  402. local_axis []={Vec(axis ).divNormalized(m0.orn()), Vec(axis ).divNormalized(m1.orn())},
  403. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  404. CreateHinge(T, a0, a1, local_anchor, local_axis, local_normal, false, false, 0, 0, collision);
  405. return T;
  406. }
  407. Joint& Joint::createHinge(Actor &a0, Actor *a1, C Vec &anchor, C Vec &axis, Flt min_angle, Flt max_angle, Bool collision)
  408. {
  409. del();
  410. Matrix m0 = a0. matrix(),
  411. m1 =(a1 ? a1->matrix() : MatrixIdentity);
  412. Vec normal =PerpN(axis),
  413. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  414. local_axis []={Vec(axis ).divNormalized(m0.orn()), Vec(axis ).divNormalized(m1.orn())},
  415. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  416. CreateHinge(T, a0, a1, local_anchor, local_axis, local_normal, true, false, min_angle, max_angle, collision);
  417. return T;
  418. }
  419. Joint& Joint::createSpherical(Actor &a0, Actor *a1, C Vec &anchor, C Vec &axis, Flt *swing, Flt *twist, Bool collision)
  420. {
  421. del();
  422. Matrix m0 = a0. matrix(),
  423. m1 =(a1 ? a1->matrix() : MatrixIdentity);
  424. Vec normal =PerpN(axis),
  425. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  426. local_axis []={Vec(axis ).divNormalized(m0.orn()), Vec(axis ).divNormalized(m1.orn())},
  427. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  428. CreateSpherical(T, a0, a1, local_anchor, local_axis, local_normal, collision, swing!=null, twist!=null, false, swing ? *swing : 0, twist ? *twist : 0);
  429. return T;
  430. }
  431. Joint& Joint::createSliding(Actor &a0, Actor *a1, C Vec &anchor, C Vec &dir, Flt min, Flt max, Bool collision)
  432. {
  433. del();
  434. Matrix m0 = a0. matrix(),
  435. m1 =(a1 ? a1->matrix() : MatrixIdentity);
  436. Vec normal =PerpN(dir),
  437. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  438. local_axis []={Vec(dir ).divNormalized(m0.orn()), Vec(dir ).divNormalized(m1.orn())},
  439. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  440. CreateSlider(T, a0, a1, local_anchor, local_axis, local_normal, min, max, collision);
  441. return T;
  442. }
  443. Joint& Joint::createDist(Actor &a0, Actor *a1, C Vec &anchor0, C Vec &anchor1, Flt min, Flt max, Spring *spring, Bool collision)
  444. {
  445. del();
  446. Vec local_anchor[]={anchor0, anchor1};
  447. CreateDistance(T, a0, a1, local_anchor, min, max, collision, spring!=null, spring ? spring->spring : 0, spring ? spring->damping : 0);
  448. return T;
  449. }
  450. Joint& Joint::createBodyHinge(Actor &bone, Actor &parent, C Vec &anchor, C Vec &axis, Flt min_angle, Flt max_angle)
  451. {
  452. del();
  453. Matrix m0 =bone .matrix(),
  454. m1 =parent.matrix();
  455. Vec normal =PerpN(axis),
  456. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  457. local_axis []={Vec(axis ).divNormalized(m0.orn()), Vec(axis ).divNormalized(m1.orn())},
  458. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  459. CreateHinge(T, bone, &parent, local_anchor, local_axis, local_normal, true, true, min_angle, max_angle, false);
  460. return T;
  461. }
  462. Joint& Joint::createBodySpherical(Actor &bone, Actor &parent, C Vec &anchor, C Vec &axis, Flt swing, Flt twist)
  463. {
  464. del();
  465. Matrix m0 =bone .matrix(),
  466. m1 =parent.matrix();
  467. Vec normal =PerpN(axis),
  468. local_anchor[]={Vec(anchor).divNormalized(m0 ), Vec(anchor).divNormalized(m1 )},
  469. local_axis []={Vec(axis ).divNormalized(m0.orn()), Vec(axis ).divNormalized(m1.orn())},
  470. local_normal[]={Vec(normal).divNormalized(m0.orn()), Vec(normal).divNormalized(m1.orn())};
  471. CreateSpherical(T, bone, &parent, local_anchor, local_axis, local_normal, false, true, true, true, swing, twist);
  472. return T;
  473. }
  474. /******************************************************************************/
  475. Matrix Joint::localAnchor(Bool index)C
  476. {
  477. #if PHYSX
  478. if(_joint)return Physx.matrix(_joint->getLocalPose(index ? PxJointActorIndex::eACTOR1 : PxJointActorIndex::eACTOR0));
  479. #endif
  480. return MatrixIdentity;
  481. }
  482. void Joint::changed()
  483. {
  484. #if PHYSX
  485. if(_joint)if(PxConstraint *constraint=_joint->getConstraint())constraint->markDirty();
  486. #endif
  487. }
  488. /******************************************************************************/
  489. // BREAKABLE
  490. /******************************************************************************/
  491. Bool Joint::broken()C
  492. {
  493. #if PHYSX
  494. return _joint ? FlagTest((UInt)_joint->getConstraintFlags(), PxConstraintFlag::eBROKEN) : true;
  495. #else
  496. return _joint ? _joint->getUserConstraintType()!=0 : true;
  497. #endif
  498. }
  499. /******************************************************************************/
  500. Joint& Joint::breakable(Flt max_force, Flt max_torque)
  501. {
  502. if(_joint)
  503. {
  504. #if PHYSX
  505. _joint->setBreakForce((max_force <0) ? PX_MAX_REAL : max_force ,
  506. (max_torque<0) ? PX_MAX_REAL : max_torque);
  507. #else
  508. Flt f;
  509. if(max_force >=FLT_MAX)max_force =-1; // need to adjust to -1 because depending on <0 we include/exclude in breakable list
  510. if(max_torque>=FLT_MAX)max_torque=-1; // need to adjust to -1 because depending on <0 we include/exclude in breakable list
  511. if(max_force>=0 || max_torque>=0)
  512. {
  513. Bullet.breakables.include(_joint); // add to breakable list
  514. _joint->enableFeedback(true);
  515. if(max_force>=0 && max_torque>=0)f=Avg(max_force, max_torque);else
  516. if(max_force>=0 )f= max_force ;else
  517. if( max_torque>=0)f= max_torque ;
  518. }else
  519. {
  520. Bullet.breakables.exclude(_joint); // remove from breakable list
  521. _joint->enableFeedback(false);
  522. f=FLT_MAX;
  523. }
  524. _joint->setUserConstraintId((Int&)f);
  525. #endif
  526. }
  527. return T;
  528. }
  529. /******************************************************************************/
  530. // HINGE
  531. /******************************************************************************/
  532. Flt Joint::hingeAngle()C
  533. {
  534. #if PHYSX
  535. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return hinge->getAngle();
  536. #endif
  537. return 0;
  538. }
  539. Flt Joint::hingeVel()C
  540. {
  541. #if PHYSX
  542. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return hinge->getVelocity();
  543. #endif
  544. return 0;
  545. }
  546. Bool Joint::hingeDriveEnabled()C
  547. {
  548. #if PHYSX
  549. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return FlagTest((UInt)hinge->getRevoluteJointFlags(), PxRevoluteJointFlag::eDRIVE_ENABLED);
  550. #endif
  551. return false;
  552. }
  553. Joint& Joint::hingeDriveEnabled(Bool on)
  554. {
  555. #if PHYSX
  556. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())hinge->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_ENABLED, on);
  557. #endif
  558. return T;
  559. }
  560. Bool Joint::hingeDriveFreeSpin()C
  561. {
  562. #if PHYSX
  563. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return FlagTest((UInt)hinge->getRevoluteJointFlags(), PxRevoluteJointFlag::eDRIVE_FREESPIN);
  564. #endif
  565. return false;
  566. }
  567. Joint& Joint::hingeDriveFreeSpin(Bool on)
  568. {
  569. #if PHYSX
  570. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())hinge->setRevoluteJointFlag(PxRevoluteJointFlag::eDRIVE_FREESPIN, on);
  571. #endif
  572. return T;
  573. }
  574. Flt Joint::hingeDriveVel()C
  575. {
  576. #if PHYSX
  577. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return hinge->getDriveVelocity();
  578. #endif
  579. return 0;
  580. }
  581. Joint& Joint::hingeDriveVel(Flt vel)
  582. {
  583. #if PHYSX
  584. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())hinge->setDriveVelocity(vel);
  585. #endif
  586. return T;
  587. }
  588. Flt Joint::hingeDriveForceLimit()C
  589. {
  590. #if PHYSX
  591. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return hinge->getDriveForceLimit();
  592. #endif
  593. return 0;
  594. }
  595. Joint& Joint::hingeDriveForceLimit(Flt limit)
  596. {
  597. #if PHYSX
  598. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())hinge->setDriveForceLimit(limit);
  599. #endif
  600. return T;
  601. }
  602. Flt Joint::hingeDriveGearRatio()C
  603. {
  604. #if PHYSX
  605. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())return hinge->getDriveGearRatio();
  606. #endif
  607. return 0;
  608. }
  609. Joint& Joint::hingeDriveGearRatio(Flt ratio)
  610. {
  611. #if PHYSX
  612. if(_joint)if(PxRevoluteJoint *hinge=_joint->is<PxRevoluteJoint>())hinge->setDriveGearRatio(ratio);
  613. #endif
  614. return T;
  615. }
  616. /******************************************************************************/
  617. // IO
  618. /******************************************************************************/
  619. Bool Joint::save(File &f)C
  620. {
  621. f.cmpUIntV(0); // version
  622. JOINT_TYPE type=JOINT_NONE;
  623. if(_joint && !broken())
  624. {
  625. #if PHYSX
  626. switch(_joint->getConcreteType())
  627. {
  628. case PxJointConcreteType::eFIXED : type=JOINT_FIXED ; break;
  629. case PxJointConcreteType::eREVOLUTE : type=JOINT_HINGE ; break;
  630. case PxJointConcreteType::ePRISMATIC: type=JOINT_SLIDER ; break;
  631. case PxJointConcreteType::eDISTANCE : type=JOINT_DISTANCE ; break;
  632. case PxJointConcreteType::eD6 :
  633. case PxJointConcreteType::eSPHERICAL: type=JOINT_SPHERICAL; break;
  634. }
  635. #else
  636. if(CAST(btDistanceConstraint , _joint))type=JOINT_DISTANCE ;else // this must be checked as first, because 'btDistanceConstraint' extends 'btPoint2PointConstraint' checked below
  637. if(CAST(btGeneric6DofConstraint, _joint))type=JOINT_FIXED ;else
  638. if(CAST(btHingeConstraint , _joint))type=JOINT_HINGE ;else
  639. if(CAST(btPoint2PointConstraint, _joint))type=JOINT_SPHERICAL;else
  640. if(CAST(btConeTwistConstraint , _joint))type=JOINT_SPHERICAL;else
  641. if(CAST(btSliderConstraint , _joint))type=JOINT_SLIDER ;
  642. #endif
  643. }
  644. // save joint type
  645. f.putByte(type);
  646. // save joint data
  647. switch(type)
  648. {
  649. case JOINT_HINGE:
  650. {
  651. Vec anchor[2], axis[2], normal[2];
  652. Bool collision, limit_angle, body;
  653. Flt angle_min, angle_max;
  654. #if PHYSX
  655. PxRevoluteJoint &hinge=*_joint->is<PxRevoluteJoint>();
  656. Matrix m0=Physx.matrix(hinge.getLocalPose(PxJointActorIndex::eACTOR0)),
  657. m1=Physx.matrix(hinge.getLocalPose(PxJointActorIndex::eACTOR1));
  658. PxJointAngularLimitPair limit=hinge.getLimit();
  659. anchor[0]=m0.pos;
  660. anchor[1]=m1.pos;
  661. axis [0]=m0.x;
  662. axis [1]=m1.x;
  663. normal[0]=m0.y;
  664. normal[1]=m1.y;
  665. collision =FlagTest((UInt)hinge.getConstraintFlags (), PxConstraintFlag ::eCOLLISION_ENABLED);
  666. limit_angle=FlagTest((UInt)hinge.getRevoluteJointFlags(), PxRevoluteJointFlag::eLIMIT_ENABLED );
  667. body =(limit.restitution>0 || limit.stiffness>0);
  668. angle_min =-limit.upper;
  669. angle_max =-limit.lower;
  670. #else
  671. btHingeConstraint *hinge=CAST(btHingeConstraint, _joint);
  672. Matrix m=Bullet.matrix(hinge->getAFrame()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))m.divNormalized(rb->offset); anchor[0]=m.pos; axis[0]=m.z; normal[0]=m.y;
  673. m=Bullet.matrix(hinge->getBFrame()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyB()))m.divNormalized(rb->offset); anchor[1]=m.pos; axis[1]=m.z; normal[1]=m.y;
  674. collision=true; btRigidBody &rb=_joint->getRigidBodyA(); REP(rb.getNumConstraintRefs())if(rb.getConstraintRef(i)==_joint){collision=false; break;}
  675. body =false;
  676. angle_min=hinge->getLowerLimit();
  677. angle_max=hinge->getUpperLimit();
  678. limit_angle=(angle_min<=angle_max);
  679. #endif
  680. f<<anchor<<axis<<normal<<collision<<limit_angle<<body;
  681. if(limit_angle)f<<angle_min<<angle_max;
  682. f<<hingeDriveEnabled()<<hingeDriveFreeSpin()<<hingeDriveVel()<<hingeDriveForceLimit()<<hingeDriveGearRatio();
  683. }break;
  684. case JOINT_SPHERICAL:
  685. {
  686. Vec anchor[2], axis[2], normal[2];
  687. Bool collision, limit_swing, limit_twist, body;
  688. Flt swing, twist;
  689. #if PHYSX
  690. #if 0
  691. PxSphericalJoint &spherical=*_joint->is<PxSphericalJoint>();
  692. Matrix m0=Physx.matrix(spherical.getLocalPose(PxJointActorIndex::eACTOR0)),
  693. m1=Physx.matrix(spherical.getLocalPose(PxJointActorIndex::eACTOR1));
  694. PxJointLimitCone limit=spherical.getLimitCone();
  695. anchor[0]=m0.pos;
  696. anchor[1]=m1.pos;
  697. axis [0]=m0.x;
  698. axis [1]=m1.x;
  699. normal[0]=m0.y;
  700. normal[1]=m1.y;
  701. collision =FlagTest((UInt)spherical.getConstraintFlags (), PxConstraintFlag ::eCOLLISION_ENABLED );
  702. limit_swing=FlagTest((UInt)spherical.getSphericalJointFlags(), PxSphericalJointFlag::eLIMIT_ENABLED );
  703. limit_twist=FlagTest((UInt)spherical.getSphericalJointFlags(), PxSphericalJointFlag::eTWIST_LIMIT_ENABLED);
  704. body =(limit.restitution>0 || limit.stiffness>0);
  705. swing =limit.yAngle;
  706. twist =limit.twistAngle;
  707. #else
  708. PxD6Joint &spherical=*_joint->is<PxD6Joint>();
  709. PxJointLimitCone swing_limit=spherical.getSwingLimit();
  710. PxJointAngularLimitPair twist_limit=spherical.getTwistLimit();
  711. Matrix m0=Physx.matrix(spherical.getLocalPose(PxJointActorIndex::eACTOR0)),
  712. m1=Physx.matrix(spherical.getLocalPose(PxJointActorIndex::eACTOR1));
  713. anchor[0]=m0.pos;
  714. anchor[1]=m1.pos;
  715. axis [0]=m0.x;
  716. axis [1]=m1.x;
  717. normal[0]=m0.y;
  718. normal[1]=m1.y;
  719. collision =FlagTest((UInt)spherical.getConstraintFlags(), PxConstraintFlag::eCOLLISION_ENABLED);
  720. limit_swing=(spherical.getMotion(PxD6Axis::eSWING1)!=PxD6Motion::eFREE);
  721. limit_twist=(spherical.getMotion(PxD6Axis::eTWIST )!=PxD6Motion::eFREE);
  722. body =(swing_limit.restitution>0 || swing_limit.stiffness>0);
  723. swing = swing_limit.yAngle;
  724. twist = twist_limit.upper;
  725. #endif
  726. #else
  727. if(btPoint2PointConstraint *p2p=CAST(btPoint2PointConstraint, _joint))
  728. {
  729. anchor[0]=Bullet.vec(p2p->getPivotInA()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))anchor[0].divNormalized(rb->offset); axis[0].set(0, 0, 1); normal[0].set(1, 0, 0);
  730. anchor[1]=Bullet.vec(p2p->getPivotInB()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyB()))anchor[1].divNormalized(rb->offset); axis[1].set(0, 0, 1); normal[1].set(1, 0, 0);
  731. limit_swing=limit_twist=false;
  732. }else
  733. {
  734. btConeTwistConstraint *cone=CAST(btConeTwistConstraint, _joint);
  735. Matrix m=Bullet.matrix(cone->getAFrame()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))m.divNormalized(rb->offset); anchor[0]=m.pos; axis[0]=m.x; normal[0]=m.z;
  736. m=Bullet.matrix(cone->getBFrame()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyB()))m.divNormalized(rb->offset); anchor[1]=m.pos; axis[1]=m.x; normal[1]=m.z;
  737. swing=cone->getSwingSpan1(); limit_swing=(swing!=FLT_MAX);
  738. twist=cone->getTwistSpan (); limit_twist=(twist!=FLT_MAX);
  739. }
  740. collision=true; btRigidBody &rb=_joint->getRigidBodyA(); REP(rb.getNumConstraintRefs())if(rb.getConstraintRef(i)==_joint){collision=false; break;}
  741. body =false;
  742. #endif
  743. f<<anchor<<axis<<normal<<collision<<limit_swing<<limit_twist<<body;
  744. if(limit_swing)f<<swing;
  745. if(limit_twist)f<<twist;
  746. }break;
  747. case JOINT_SLIDER:
  748. {
  749. Vec anchor[2], axis[2], normal[2];
  750. Flt min, max;
  751. Bool collision;
  752. #if PHYSX
  753. PxPrismaticJoint &slider=*_joint->is<PxPrismaticJoint>();
  754. Matrix m0=Physx.matrix(slider.getLocalPose(PxJointActorIndex::eACTOR0)),
  755. m1=Physx.matrix(slider.getLocalPose(PxJointActorIndex::eACTOR1));
  756. PxJointLinearLimitPair limit=slider.getLimit();
  757. anchor[0]=m0.pos;
  758. anchor[1]=m1.pos;
  759. axis [0]=m0.x;
  760. axis [1]=m1.x;
  761. normal[0]=m0.y;
  762. normal[1]=m1.y;
  763. collision=FlagTest((UInt)slider.getConstraintFlags(), PxConstraintFlag::eCOLLISION_ENABLED);
  764. min =-limit.upper;
  765. max =-limit.lower;
  766. #else
  767. btSliderConstraint *slider=CAST(btSliderConstraint, _joint);
  768. Matrix m=Bullet.matrix(slider->getFrameOffsetA()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))m.divNormalized(rb->offset); anchor[1]=m.pos; axis[1]=m.x; normal[1]=m.z;
  769. m=Bullet.matrix(slider->getFrameOffsetB()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyB()))m.divNormalized(rb->offset); anchor[0]=m.pos; axis[0]=m.x; normal[0]=m.z;
  770. collision=true; btRigidBody &rb=_joint->getRigidBodyA(); REP(rb.getNumConstraintRefs())if(rb.getConstraintRef(i)==_joint){collision=false; break;}
  771. min=slider->getLowerLinLimit();
  772. max=slider->getUpperLinLimit();
  773. #endif
  774. f<<anchor<<axis<<normal<<min<<max<<collision;
  775. }break;
  776. case JOINT_DISTANCE:
  777. {
  778. Vec anchor[2];
  779. Flt min, max;
  780. Bool collision, spring;
  781. Flt spring_spring, spring_damper;
  782. #if PHYSX
  783. PxDistanceJoint &distance=*_joint->is<PxDistanceJoint>();
  784. anchor[0] =Physx.vec(distance.getLocalPose(PxJointActorIndex::eACTOR0).p);
  785. anchor[1] =Physx.vec(distance.getLocalPose(PxJointActorIndex::eACTOR1).p);
  786. collision =FlagTest((UInt)distance.getConstraintFlags (), PxConstraintFlag ::eCOLLISION_ENABLED);
  787. spring =FlagTest((UInt)distance.getDistanceJointFlags(), PxDistanceJointFlag::eSPRING_ENABLED );
  788. min =distance.getMinDistance();
  789. max =distance.getMaxDistance();
  790. spring_spring=distance.getStiffness();
  791. spring_damper=distance.getDamping ();
  792. #else
  793. btDistanceConstraint *dist=CAST(btDistanceConstraint, _joint);
  794. anchor[0] =Bullet.vec(dist->getPivotInA()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))anchor[0].divNormalized(rb->offset);
  795. anchor[1] =Bullet.vec(dist->getPivotInB()); if(RigidBody *rb=CAST(RigidBody, &_joint->getRigidBodyA()))anchor[1].divNormalized(rb->offset);
  796. min =dist->min_dist;
  797. max =dist->max_dist;
  798. spring =dist->spring;
  799. spring_spring=dist->spring_spring;
  800. spring_damper=dist->spring_damper;
  801. collision=true; btRigidBody &rb=_joint->getRigidBodyA(); REP(rb.getNumConstraintRefs())if(rb.getConstraintRef(i)==_joint){collision=false; break;}
  802. #endif
  803. f<<anchor<<min<<max<<collision<<spring;
  804. if(spring)f<<spring_spring<<spring_damper;
  805. }break;
  806. }
  807. // save breakable data
  808. if(type)
  809. {
  810. Flt max_force, max_torque;
  811. #if PHYSX
  812. _joint->getBreakForce(max_force, max_torque);
  813. #else
  814. Int force=_joint->getUserConstraintId(); max_force=max_torque=(Flt&)force;
  815. #endif
  816. f<<max_force<<max_torque;
  817. }
  818. return f.ok();
  819. }
  820. /******************************************************************************/
  821. Bool Joint::load(File &f, Actor &a0, Actor *a1)
  822. {
  823. del();
  824. switch(f.decUIntV()) // version
  825. {
  826. case 0:
  827. {
  828. JOINT_TYPE type=JOINT_TYPE(f.getByte());
  829. switch( type)
  830. {
  831. default : goto error; // unknown joint type
  832. case JOINT_NONE : break;
  833. case JOINT_FIXED: create(a0, a1); break;
  834. case JOINT_HINGE:
  835. {
  836. Vec anchor[2], axis[2], normal[2];
  837. Bool collision, limit_angle, body;
  838. Flt angle_min, angle_max;
  839. f>>anchor>>axis>>normal>>collision>>limit_angle>>body;
  840. if(limit_angle)f>>angle_min>>angle_max;
  841. CreateHinge(T, a0, a1, anchor, axis, normal, limit_angle, body, angle_min, angle_max, collision);
  842. hingeDriveEnabled(f.getBool()); hingeDriveFreeSpin(f.getBool()); hingeDriveVel(f.getFlt()); hingeDriveForceLimit(f.getFlt()); hingeDriveGearRatio(f.getFlt());
  843. }break;
  844. case JOINT_SPHERICAL:
  845. {
  846. Vec anchor[2], axis[2], normal[2];
  847. Bool collision, limit_swing, limit_twist, body;
  848. Flt swing, twist;
  849. f>>anchor>>axis>>normal>>collision>>limit_swing>>limit_twist>>body;
  850. if(limit_swing)f>>swing;
  851. if(limit_twist)f>>twist;
  852. CreateSpherical(T, a0, a1, anchor, axis, normal, collision, limit_swing, limit_twist, body, swing, twist);
  853. }break;
  854. case JOINT_SLIDER:
  855. {
  856. Vec anchor[2], axis[2], normal[2];
  857. Flt min, max;
  858. Bool collision;
  859. f>>anchor>>axis>>normal>>min>>max>>collision;
  860. CreateSlider(T, a0, a1, anchor, axis, normal, min, max, collision);
  861. }break;
  862. case JOINT_DISTANCE:
  863. {
  864. Vec anchor[2];
  865. Flt min, max;
  866. Bool collision, spring;
  867. Flt spring_spring, spring_damper;
  868. f>>anchor>>min>>max>>collision>>spring;
  869. if(spring)f>>spring_spring>>spring_damper;
  870. CreateDistance(T, a0, a1, anchor, min, max, collision, spring, spring_spring, spring_damper);
  871. }break;
  872. }
  873. // load breakable data
  874. if(type)
  875. {
  876. Flt max_force, max_torque; f>>max_force>>max_torque; breakable(max_force, max_torque);
  877. }
  878. if(f.ok())return true;
  879. }break;
  880. }
  881. error:
  882. del(); return false;
  883. }
  884. /******************************************************************************/
  885. }
  886. /******************************************************************************/