Actor.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************
  5. Applying Flt damping; (0..1 range) each frame (correct formula) :
  6. actor.vel(actor.vel()*Pow(damping, Time.d()));
  7. OR
  8. actor.addVel(actor.vel()*(Pow(damping, Time.d())-1));
  9. Actor 'addVel at pos' and 'addAccel at pos' are not possible to perform.
  10. It's not the same as 'Actor.addForce*mass() at pos',
  11. Also remember that torque is calculated not based on mass but probably on inertia tensor.
  12. /******************************************************************************/
  13. #if PHYSX
  14. /******************************************************************************
  15. SimulationFilterData( group , ignore_id, PxPairFlag, 0) (also in 'Vehicle')
  16. QueryFilterData(IndexToFlag(group), vehicle_id, 0, 0) (also in 'Vehicle')
  17. /******************************************************************************/
  18. Flt Actor::energy ( )C {return _dynamic ? (inertia().avg()*angVel().length2() + mass()*vel().length2())*0.5f : 0;}
  19. Flt Actor:: damping ( )C {return _dynamic ? _dynamic->getLinearDamping () : 0;}
  20. Flt Actor::adamping ( )C {return _dynamic ? _dynamic->getAngularDamping () : 0;}
  21. Flt Actor::maxAngVel ( )C {return _dynamic ? _dynamic->getMaxAngularVelocity() : 0;}
  22. Flt Actor::mass ( )C {return _dynamic ? _dynamic->getMass () : 0;}
  23. Vec Actor::massCenterL( )C {return _dynamic ? Physx.vec (_dynamic->getCMassLocalPose ().p) : 0 ;}
  24. Vec Actor::massCenterW( )C {return massCenterL()*matrix();}
  25. Vec Actor::inertia ( )C {return _dynamic ? Physx.vec (_dynamic->getMassSpaceInertiaTensor() ) : 0 ;}
  26. Vec Actor::pos ( )C {return _actor ? Physx.vec (_actor ->getGlobalPose ().p) : 0 ;}
  27. Matrix3 Actor::orn ( )C {return _actor ? Physx.orn (_actor ->getGlobalPose ().q) : MatrixIdentity.orn();}
  28. Matrix Actor::matrix ( )C {return _actor ? Physx.matrix(_actor ->getGlobalPose () ) : MatrixIdentity ;}
  29. Vec Actor:: vel ( )C {return _dynamic ? Physx.vec (_dynamic->getLinearVelocity () ) : 0 ;}
  30. Vec Actor:: angVel ( )C {return _dynamic ? Physx.vec (_dynamic->getAngularVelocity () ) : 0 ;}
  31. Vec Actor::pointVelL (C Vec &pos)C {return vel() + Cross(angVel(), (pos-massCenterL())*orn());}
  32. Vec Actor::pointVelW (C Vec &pos)C {return vel() + Cross(angVel(), pos-massCenterW() );}
  33. Actor& Actor:: damping ( Flt damping) {if(_dynamic)_dynamic->setLinearDamping (damping ); return T;}
  34. Actor& Actor::adamping ( Flt damping) {if(_dynamic)_dynamic->setAngularDamping (damping ); return T;}
  35. Actor& Actor::maxAngVel ( Flt vel ) {if(_dynamic)_dynamic->setMaxAngularVelocity (vel ); return T;}
  36. Actor& Actor::mass ( Flt mass ) {if(_dynamic)_dynamic->setMass (Max(EPS, mass )); return T;} // may crash with zero
  37. Actor& Actor::massCenterL(C Vec &center ) {if(_dynamic){PxTransform t=_dynamic->getCMassLocalPose(); t.p=Physx.vec(center); _dynamic->setCMassLocalPose(t);} return T;}
  38. Actor& Actor::massCenterW(C Vec &center ) {return massCenterL(Vec(center).divNormalized(matrix()));}
  39. Actor& Actor::inertia (C Vec &inertia) {if(_dynamic)_dynamic->setMassSpaceInertiaTensor(Physx.vec(Vec(Max(EPS, inertia.x), Max(EPS, inertia.y), Max(EPS, inertia.z)))); return T;} // may crash with zero
  40. Actor& Actor::pos (C Vec &pos ) {if(_actor ){PxTransform t=_actor->getGlobalPose(); t.p=Physx.vec(pos); _actor->setGlobalPose( t);} return T;}
  41. Actor& Actor::orn (C Matrix3 &orn ) {if(_actor ){PxTransform t=_actor->getGlobalPose(); t.q=Physx.orn(orn); _actor->setGlobalPose( t);} return T;}
  42. Actor& Actor::matrix (C Matrix &matrix ) {if(_actor ) _actor->setGlobalPose(Physx.matrix(matrix)); return T;}
  43. Actor& Actor:: vel (C Vec &vel ) {if(_dynamic && !kinematic())_dynamic->setLinearVelocity (Physx.vec(vel)); return T;} // PhysX will report an error if this is called for kinematic
  44. Actor& Actor::angVel (C Vec &vel ) {if(_dynamic && !kinematic())_dynamic->setAngularVelocity(Physx.vec(vel)); return T;} // PhysX will report an error if this is called for kinematic
  45. Actor& Actor::kinematicMoveTo(C Vec &pos ) {if(_dynamic){PxTransform t; if(!_dynamic->getKinematicTarget(t))t=_dynamic->getGlobalPose(); t.p=Physx.vec(pos); _dynamic->setKinematicTarget(t );} return T;}
  46. Actor& Actor::kinematicMoveTo(C Matrix3 &orn ) {if(_dynamic){PxTransform t; if(!_dynamic->getKinematicTarget(t))t=_dynamic->getGlobalPose(); t.q=Physx.orn(orn); _dynamic->setKinematicTarget(t );} return T;}
  47. Actor& Actor::kinematicMoveTo(C Matrix &matrix) {if(_dynamic) _dynamic->setKinematicTarget(Physx.matrix(matrix)); return T;}
  48. // !! in the codes below require actor to be non-kinematic, because when applying forces to a dynamic object that was turned into kinematic, its mass will become infinite, and when disabling kinematic afterwards, it will be like a static actor !!
  49. Actor& Actor::addAngVel (C Vec &ang_vel ) {if(_dynamic && !kinematic()) _dynamic->addTorque ( Physx.vec(ang_vel), PxForceMode::eVELOCITY_CHANGE); return T;}
  50. Actor& Actor::addImpulse(C Vec &impulse ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(impulse), PxForceMode::eIMPULSE ); return T;}
  51. Actor& Actor::addImpulse(C Vec &impulse, C Vec &pos) {if(_dynamic && !kinematic())PxRigidBodyExt::addForceAtPos(*_dynamic, Physx.vec(impulse), Physx.vec(pos), PxForceMode::eIMPULSE ); return T;}
  52. Actor& Actor::addVel (C Vec &vel ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(vel ), PxForceMode::eVELOCITY_CHANGE); return T;}
  53. #if 0 // we can't use 'eFORCE' because we manually manage simulation steps durations and need to make sure we specify correct time duration, also these methods can be called after each step completed AND after all steps completed, so we have to use 'Physics.time' which is set to 'stepTime' and 'updatedTime'
  54. Actor& Actor::addTorque (C Vec &torque ) {if(_dynamic && !kinematic()) _dynamic->addTorque ( Physx.vec(torque ), PxForceMode::eFORCE ); return T;}
  55. Actor& Actor::addForce (C Vec &force ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(force ), PxForceMode::eFORCE ); return T;}
  56. Actor& Actor::addForce (C Vec &force , C Vec &pos) {if(_dynamic && !kinematic())PxRigidBodyExt::addForceAtPos(*_dynamic, Physx.vec(force ), Physx.vec(pos), PxForceMode::eFORCE ); return T;}
  57. Actor& Actor::addAccel (C Vec &accel ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(accel ), PxForceMode::eACCELERATION ); return T;}
  58. #else
  59. Actor& Actor::addTorque (C Vec &torque ) {if(_dynamic && !kinematic()) _dynamic->addTorque ( Physx.vec(torque*Physics.time()), PxForceMode::eIMPULSE ); return T;}
  60. Actor& Actor::addForce (C Vec &force ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(force *Physics.time()), PxForceMode::eIMPULSE ); return T;}
  61. Actor& Actor::addForce (C Vec &force , C Vec &pos) {if(_dynamic && !kinematic())PxRigidBodyExt::addForceAtPos(*_dynamic, Physx.vec(force *Physics.time()), Physx.vec(pos), PxForceMode::eIMPULSE ); return T;}
  62. Actor& Actor::addAccel (C Vec &accel ) {if(_dynamic && !kinematic()) _dynamic->addForce ( Physx.vec(accel *Physics.time()), PxForceMode::eVELOCITY_CHANGE); return T;}
  63. #endif
  64. Actor& Actor::gravity (Bool on) {if( _actor && gravity ()!=on){_actor ->setActorFlag ( PxActorFlag ::eDISABLE_GRAVITY, !on); if( on)sleep(false);} return T;}
  65. Actor& Actor::kinematic(Bool on) {if( _dynamic && kinematic()!=on){_dynamic->setRigidBodyFlag ( PxRigidBodyFlag::eKINEMATIC , on); if(!on)sleep(false);} return T;}
  66. Bool Actor::kinematic( )C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidBodyFlags(), PxRigidBodyFlag::eKINEMATIC ) : false;}
  67. Bool Actor::gravity ( )C {return _actor ? !FlagTest((UInt)_actor ->getActorFlags (), PxActorFlag ::eDISABLE_GRAVITY ) : true ;}
  68. Bool Actor::ccd ( )C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidBodyFlags(), PxRigidBodyFlag::eENABLE_CCD ) : false;}
  69. Bool Actor::ray ()C {if(_actor){PxShape *shape; if(_actor->getShapes(&shape, 1))return FlagTest((UInt)shape->getFlags(), PxShapeFlag::eSCENE_QUERY_SHAPE);} return false;}
  70. Bool Actor::trigger ()C {if(_actor){PxShape *shape; if(_actor->getShapes(&shape, 1))return FlagTest((UInt)shape->getFlags(), PxShapeFlag::eTRIGGER_SHAPE );} return false;}
  71. Bool Actor::collision()C {if(_actor){PxShape *shape; if(_actor->getShapes(&shape, 1))return FlagTest((UInt)shape->getFlags(), PxShapeFlag::eSIMULATION_SHAPE );} return false;}
  72. Byte Actor::group ()C {if(_actor){PxShape *shape; if(_actor->getShapes(&shape, 1))return shape->getSimulationFilterData().word0 ;} return 0;}
  73. Actor& Actor::ccd(Bool on)
  74. {
  75. if(_dynamic)
  76. {
  77. _dynamic->setRigidBodyFlag(PxRigidBodyFlag::eENABLE_CCD, on);
  78. group(group()); // need to re-apply group because of 'eCCD_LINEAR' in 'SimulationFilterData'
  79. }
  80. return T;
  81. }
  82. Actor& Actor::ray(Bool on)
  83. {
  84. if(_actor)for(Int offset=0, shapes=_actor->getNbShapes(); shapes>0; )
  85. {
  86. PxShape *shape[32]; Int s=Min(shapes, Elms(shape));
  87. REP(_actor->getShapes(shape, s, offset))shape[i]->setFlag(PxShapeFlag::eSCENE_QUERY_SHAPE, on);
  88. shapes-=s;
  89. offset+=s;
  90. }
  91. return T;
  92. }
  93. Actor& Actor::trigger(Bool on)
  94. {
  95. if(_actor)for(Int offset=0, shapes=_actor->getNbShapes(); shapes>0; )
  96. {
  97. PxShape *shape[32]; Int s=Min(shapes, Elms(shape));
  98. REP(_actor->getShapes(shape, s, offset))
  99. {
  100. if(on)shape[i]->setFlag(PxShapeFlag::eSIMULATION_SHAPE, false); // if enabling trigger, we need to first disable simulation, because PhysX will ignore setting trigger flag
  101. shape[i]->setFlag(PxShapeFlag::eTRIGGER_SHAPE , on );
  102. }
  103. shapes-=s;
  104. offset+=s;
  105. }
  106. return T;
  107. }
  108. Actor& Actor::collision(Bool on)
  109. {
  110. if(_actor)for(Int offset=0, shapes=_actor->getNbShapes(); shapes>0; )
  111. {
  112. PxShape *shape[32]; Int s=Min(shapes, Elms(shape));
  113. REP(_actor->getShapes(shape, s, offset))
  114. {
  115. if(on)shape[i]->setFlag(PxShapeFlag::eTRIGGER_SHAPE , false); // if enabling collision, we need to first disable trigger, because PhysX will ignore setting collision flag
  116. shape[i]->setFlag(PxShapeFlag::eSIMULATION_SHAPE, on );
  117. }
  118. shapes-=s;
  119. offset+=s;
  120. }
  121. return T;
  122. }
  123. Actor& Actor::group(Byte group)
  124. {
  125. if(_actor && InRange(group, AG_NUM)) // must always apply group even if applying the same one, because '_ignore_id' could be different (and 'qfd' needs to be set)
  126. {
  127. PxFilterData sfd(group, _ignore_id, ccd() ? PxPairFlag::eDETECT_CCD_CONTACT : 0, 0), qfd(IndexToFlag(group), 0, 0, 0);
  128. for(Int offset=0, shapes=_actor->getNbShapes(); shapes>0; )
  129. {
  130. PxShape *shape[32]; Int s=Min(shapes, Elms(shape));
  131. REP(_actor->getShapes(shape, s, offset))
  132. {
  133. shape[i]->setSimulationFilterData(sfd);
  134. shape[i]->setQueryFilterData (qfd);
  135. }
  136. shapes-=s;
  137. offset+=s;
  138. }
  139. }
  140. return T;
  141. }
  142. PhysMtrl* Actor::material()C
  143. {
  144. if(_actor)
  145. {
  146. PxShape *shape; if(_actor->getShapes(&shape, 1))
  147. {
  148. PxMaterial *mtrl;
  149. if(shape->getMaterials(&mtrl, 1))if(mtrl)if(PhysMtrl *pm=(PhysMtrl*)mtrl->userData)if(pm!=&Physics.mtrl_default)return pm; // return default material always as null (we can use 'userData' because PhysMtrl's are stored in non-ref-counted cache and kept forever)
  150. }
  151. }
  152. return null;
  153. }
  154. Bool Actor::freezePosX()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_LINEAR_X) : false;}
  155. Bool Actor::freezePosY()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_LINEAR_Y) : false;}
  156. Bool Actor::freezePosZ()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_LINEAR_Z) : false;}
  157. Bool Actor::freezePos ()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), UInt(PxRigidDynamicLockFlag::eLOCK_LINEAR_X | PxRigidDynamicLockFlag::eLOCK_LINEAR_Y | PxRigidDynamicLockFlag::eLOCK_LINEAR_Z)) : false;}
  158. Bool Actor::freezeRotX()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_ANGULAR_X) : false;}
  159. Bool Actor::freezeRotY()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y) : false;}
  160. Bool Actor::freezeRotZ()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z) : false;}
  161. Bool Actor::freezeRot ()C {return _dynamic ? FlagTest((UInt)_dynamic->getRigidDynamicLockFlags(), UInt(PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z)) : false;}
  162. Actor& Actor::freezePosX(Bool freeze)
  163. {
  164. if(_dynamic)
  165. {
  166. PxRigidDynamicLockFlags flags=_dynamic->getRigidDynamicLockFlags(), new_flags=flags;
  167. FlagSet(new_flags, PxRigidDynamicLockFlag::eLOCK_LINEAR_X, freeze);
  168. if(flags!=new_flags)
  169. {
  170. _dynamic->setRigidDynamicLockFlags(new_flags); if(!freeze)sleep(false); // wake up on un-freeze
  171. }
  172. }
  173. return T;
  174. }
  175. Actor& Actor::freezePosY(Bool freeze)
  176. {
  177. if(_dynamic)
  178. {
  179. PxRigidDynamicLockFlags flags=_dynamic->getRigidDynamicLockFlags(), new_flags=flags;
  180. FlagSet(new_flags, PxRigidDynamicLockFlag::eLOCK_LINEAR_Y, freeze);
  181. if(flags!=new_flags)
  182. {
  183. _dynamic->setRigidDynamicLockFlags(new_flags); if(!freeze)sleep(false); // wake up on un-freeze
  184. }
  185. }
  186. return T;
  187. }
  188. Actor& Actor::freezePosZ(Bool freeze)
  189. {
  190. if(_dynamic)
  191. {
  192. PxRigidDynamicLockFlags flags=_dynamic->getRigidDynamicLockFlags(), new_flags=flags;
  193. FlagSet(new_flags, PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, freeze);
  194. if(flags!=new_flags)
  195. {
  196. _dynamic->setRigidDynamicLockFlags(new_flags); if(!freeze)sleep(false); // wake up on un-freeze
  197. }
  198. }
  199. return T;
  200. }
  201. Actor& Actor::freezePos(Bool freeze)
  202. {
  203. if(_dynamic)
  204. {
  205. PxRigidDynamicLockFlags flags=_dynamic->getRigidDynamicLockFlags(), new_flags=flags;
  206. FlagSet(new_flags, PxRigidDynamicLockFlag::eLOCK_LINEAR_X | PxRigidDynamicLockFlag::eLOCK_LINEAR_Y | PxRigidDynamicLockFlag::eLOCK_LINEAR_Z, freeze);
  207. if(flags!=new_flags)
  208. {
  209. _dynamic->setRigidDynamicLockFlags(new_flags); if(!freeze)sleep(false); // wake up on un-freeze
  210. }
  211. }
  212. return T;
  213. }
  214. Actor& Actor::freezeRotX(Bool freeze) {if(_dynamic)_dynamic->setRigidDynamicLockFlag(PxRigidDynamicLockFlag::eLOCK_ANGULAR_X, freeze); return T;}
  215. Actor& Actor::freezeRotY(Bool freeze) {if(_dynamic)_dynamic->setRigidDynamicLockFlag(PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y, freeze); return T;}
  216. Actor& Actor::freezeRotZ(Bool freeze) {if(_dynamic)_dynamic->setRigidDynamicLockFlag(PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, freeze); return T;}
  217. Actor& Actor::freezeRot (Bool freeze) {if(_dynamic)
  218. {
  219. PxRigidDynamicLockFlags flags=_dynamic->getRigidDynamicLockFlags();
  220. FlagSet(flags, PxRigidDynamicLockFlag::eLOCK_ANGULAR_X | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Y | PxRigidDynamicLockFlag::eLOCK_ANGULAR_Z, freeze);
  221. _dynamic->setRigidDynamicLockFlags(flags);
  222. }return T;}
  223. Ptr Actor::user ()C {return _actor ? _actor->userData : null ;}
  224. Ptr Actor::obj ()C {return _actor ? (Ptr)_actor->getName () : null ;}
  225. Byte Actor::dominance ()C {return _actor ? _actor->getDominanceGroup() : 0 ;}
  226. Bool Actor::sleep ()C {return _dynamic ? _dynamic->isSleeping () : false;}
  227. Flt Actor::sleepEnergy()C {return _dynamic ? _dynamic->getSleepThreshold() : 0 ;}
  228. Actor& Actor::user (Ptr user ) {if(_actor)_actor->userData = user ; return T;}
  229. Actor& Actor::obj (Ptr obj ) {if(_actor)_actor->setName ((char*)obj); return T;}
  230. Actor& Actor::dominance (Byte dominance) {if(_actor)_actor->setDominanceGroup( dominance); return T;}
  231. Actor& Actor::sleep (Bool sleep ) {if(_dynamic && !kinematic()){if(sleep)_dynamic->putToSleep();else _dynamic->wakeUp();} return T;} // PhysX will report an error if this is called for kinematic
  232. Actor& Actor::sleepEnergy(Flt energy ) {if(_dynamic)_dynamic->setSleepThreshold(energy); return T;}
  233. Actor& Actor::ignore (Actor &actor, Bool ignore)
  234. {
  235. if(T._actor && actor._actor && T._actor!=actor._actor)
  236. {
  237. if(ignore) // enable per-actor ignore
  238. {
  239. if(!_ignore_id || !actor._ignore_id) // if at least one doesn't have "ignore ID"
  240. {
  241. WriteLock lock(Physics._rws); // lock needed for 'ignore_id_gen'
  242. if(! _ignore_id){UInt id=Physx.ignore_id_gen.New(); if(id<MAX_ACTOR_IGNORE){ _ignore_id=id; group( group());}else Physx.ignore_id_gen.Return(id);} // if ID is ok then apply it to member and filtering data (through 'group'), apply ONLY AFTER range verification in case filter func is running on secondary thread and could cause crash if it's invalid, if not ok then return it
  243. if(!actor._ignore_id){UInt id=Physx.ignore_id_gen.New(); if(id<MAX_ACTOR_IGNORE){actor._ignore_id=id; actor.group(actor.group());}else Physx.ignore_id_gen.Return(id);}
  244. }
  245. }
  246. if(_ignore_id && actor._ignore_id) // if both have "ignore ID"
  247. {
  248. FlagSet(Physx.ignoreMap( _ignore_id, actor._ignore_id), 1<<(actor._ignore_id&7), ignore);
  249. FlagSet(Physx.ignoreMap(actor._ignore_id, _ignore_id), 1<<( _ignore_id&7), ignore);
  250. }
  251. }
  252. return T;
  253. }
  254. Box Actor::box()C {return _actor ? Physx.box(_actor->getWorldBounds()) : Box(0);}
  255. Shape Actor::shape(Bool local)C
  256. {
  257. Shape shape;
  258. if(_actor)
  259. {
  260. PxShape *s; if(_actor->getShapes(&s, 1))
  261. {
  262. switch(s->getGeometryType())
  263. {
  264. case PxGeometryType::ePLANE : {PxPlaneGeometry plane ; if(s->getPlaneGeometry (plane )){shape.type=SHAPE_PLANE ; shape.plane .set(VecZero, Vec(1, 0, 0));}} break;
  265. case PxGeometryType::eSPHERE : {PxSphereGeometry sphere ; if(s->getSphereGeometry (sphere )){shape.type=SHAPE_BALL ; shape.ball .set(sphere .radius);}} break;
  266. case PxGeometryType::eCAPSULE: {PxCapsuleGeometry capsule; if(s->getCapsuleGeometry(capsule)){shape.type=SHAPE_CAPSULE; shape.capsule.set(capsule.radius, (capsule.halfHeight+capsule.radius)*2, VecZero, Vec(1, 0, 0));}} break;
  267. case PxGeometryType::eBOX : {PxBoxGeometry box ; if(s->getBoxGeometry (box )){shape.type=SHAPE_OBOX ; shape.obox.box.set(Vec(-box.halfExtents.x, -box.halfExtents.y, -box.halfExtents.z), Vec(box.halfExtents.x, box.halfExtents.y, box.halfExtents.z)); shape.obox.matrix.identity();}} break;
  268. }
  269. if(shape.type)shape*=Physx.matrix(local ? s->getLocalPose() : _actor->getGlobalPose()*s->getLocalPose());
  270. }
  271. }
  272. return shape;
  273. }
  274. /******************************************************************************/
  275. #else // BULLET
  276. /******************************************************************************/
  277. RigidBody::~RigidBody()
  278. {
  279. REPA(ignore)if(RigidBody *rb=CAST(RigidBody, ignore[i]))rb->ignore.exclude(this); // remove self from other ignores
  280. }
  281. RigidBody::RigidBody(btRigidBody::btRigidBodyConstructionInfo &info) : btRigidBody(info)
  282. {
  283. material=&Physics.mtrl_default; user=null; obj=null; offset_com.zero(); offset.identity(); setUserPointer(this);
  284. }
  285. Flt Actor::energy()C {return (inertia().avg()*angVel().length2() + mass()*vel().length2())*0.5f;}
  286. Ptr Actor::user( )C {return _actor ? _actor->user : null ;}
  287. Actor& Actor::user(Ptr data) {if( _actor) _actor->user=data; return T;}
  288. Ptr Actor::obj( )C {return _actor ? _actor->obj : null ;}
  289. Actor& Actor::obj(Ptr obj) {if( _actor) _actor->obj=obj; return T;}
  290. Bool Actor::gravity( )C {return _actor ? !FlagTest(_actor->getFlags(), BT_DISABLE_WORLD_GRAVITY) : true;}
  291. Actor& Actor::gravity(Bool on)
  292. {
  293. if(_actor)
  294. {
  295. UInt flags=_actor->getFlags(); if(FlagTest(flags, BT_DISABLE_WORLD_GRAVITY)==on)
  296. {
  297. flags^=BT_DISABLE_WORLD_GRAVITY; _actor->setFlags(flags);
  298. _actor->setGravity(Bullet.vec(on ? Physics.gravity() : VecZero));
  299. if(on)sleep(false);
  300. }
  301. }
  302. return T;
  303. }
  304. Byte Actor::group( )C {return _actor ? _actor->getBroadphaseProxy()->m_collisionFilterGroup : 0;}
  305. Actor& Actor::group(Byte group) {if(_actor && InRange(group, AG_NUM))_actor->getBroadphaseProxy()->m_collisionFilterGroup=group; return T;}
  306. Actor& Actor::ignore(Actor &actor, Bool ignore)
  307. {
  308. if(T._actor && actor._actor && T._actor!=actor._actor)
  309. {
  310. if(ignore){T._actor->ignore.include(actor._actor); actor._actor->ignore.include(T._actor);}
  311. else {T._actor->ignore.exclude(actor._actor); actor._actor->ignore.exclude(T._actor);}
  312. }
  313. return T;
  314. }
  315. Bool Actor::freezePosX()C {return _actor ? _actor->getLinearFactor().x()==0 : false;}
  316. Bool Actor::freezePosY()C {return _actor ? _actor->getLinearFactor().y()==0 : false;}
  317. Bool Actor::freezePosZ()C {return _actor ? _actor->getLinearFactor().z()==0 : false;}
  318. Bool Actor::freezePos ()C {return _actor ? !Bullet.vec(_actor->getLinearFactor()).all() : false;}
  319. Bool Actor::freezeRotX()C {return _actor ? _actor->getAngularFactor().x()==0 : false;}
  320. Bool Actor::freezeRotY()C {return _actor ? _actor->getAngularFactor().y()==0 : false;}
  321. Bool Actor::freezeRotZ()C {return _actor ? _actor->getAngularFactor().z()==0 : false;}
  322. Bool Actor::freezeRot ()C {return _actor ? !Bullet.vec(_actor->getAngularFactor()).all() : false;}
  323. Actor& Actor::freezePosX(Bool on)
  324. {
  325. if(_actor)
  326. {
  327. btVector3 factor=_actor->getLinearFactor(); if(Bool(factor.getX())==on) // if different
  328. {
  329. if(on)
  330. {
  331. _actor->setLinearFactor (btVector3(1, 0, 0)); _actor->applyCentralForce(-_actor->getTotalForce()); // clear X force
  332. btVector3 velocity=_actor->getLinearVelocity( ); velocity.setX(0); _actor->setLinearVelocity( velocity); // clear X velocity
  333. }else sleep(false); // wake up on un-freeze
  334. factor.setX(!on); _actor->setLinearFactor(factor);
  335. }
  336. }
  337. return T;
  338. }
  339. Actor& Actor::freezePosY(Bool on)
  340. {
  341. if(_actor)
  342. {
  343. btVector3 factor=_actor->getLinearFactor(); if(Bool(factor.getY())==on) // if different
  344. {
  345. if(on)
  346. {
  347. _actor->setLinearFactor (btVector3(0, 1, 0)); _actor->applyCentralForce(-_actor->getTotalForce()); // clear Y force
  348. btVector3 velocity=_actor->getLinearVelocity( ); velocity.setY(0); _actor->setLinearVelocity( velocity); // clear Y velocity
  349. }else sleep(false); // wake up on un-freeze
  350. factor.setY(!on); _actor->setLinearFactor(factor);
  351. }
  352. }
  353. return T;
  354. }
  355. Actor& Actor::freezePosZ(Bool on)
  356. {
  357. if(_actor)
  358. {
  359. btVector3 factor=_actor->getLinearFactor(); if(Bool(factor.getZ())==on) // if different
  360. {
  361. if(on)
  362. {
  363. _actor->setLinearFactor (btVector3(0, 0, 1)); _actor->applyCentralForce(-_actor->getTotalForce()); // clear Z force
  364. btVector3 velocity=_actor->getLinearVelocity( ); velocity.setZ(0); _actor->setLinearVelocity( velocity); // clear Z velocity
  365. }else sleep(false); // wake up on un-freeze
  366. factor.setZ(!on); _actor->setLinearFactor(factor);
  367. }
  368. }
  369. return T;
  370. }
  371. Actor& Actor::freezePos(Bool on)
  372. {
  373. if(_actor)
  374. {
  375. btVector3 new_factor=(on ? btVector3(0, 0, 0) : btVector3(1, 1, 1)); if(_actor->getLinearFactor()!=new_factor) // if different
  376. {
  377. if(on)
  378. {
  379. _actor->setLinearFactor (btVector3(1, 1, 1)); _actor->applyCentralForce(-_actor->getTotalForce()); // clear force
  380. _actor->setLinearVelocity(btVector3(0, 0, 0)); // clear velocity
  381. }else sleep(false); // wake up on un-freeze
  382. _actor->setLinearFactor(new_factor);
  383. }
  384. }
  385. return T;
  386. }
  387. Actor& Actor::freezeRotX(Bool on)
  388. {
  389. if(_actor)
  390. {
  391. btVector3 factor=_actor->getAngularFactor();
  392. if(on)
  393. {
  394. _actor->setAngularFactor (btVector3(1, 0, 0)); _actor->applyTorque (-_actor->getTotalTorque()); // clear X torque
  395. btVector3 velocity=_actor->getAngularVelocity( ); velocity.setX(0); _actor->setAngularVelocity( velocity); // clear X velocity
  396. }
  397. factor.setX(!on); _actor->setAngularFactor(factor);
  398. }
  399. return T;
  400. }
  401. Actor& Actor::freezeRotY(Bool on)
  402. {
  403. if(_actor)
  404. {
  405. btVector3 factor=_actor->getAngularFactor();
  406. if(on)
  407. {
  408. _actor->setAngularFactor (btVector3(0, 1, 0)); _actor->applyTorque (-_actor->getTotalTorque()); // clear Y torque
  409. btVector3 velocity=_actor->getAngularVelocity( ); velocity.setY(0); _actor->setAngularVelocity( velocity); // clear Y velocity
  410. }
  411. factor.setY(!on); _actor->setAngularFactor(factor);
  412. }
  413. return T;
  414. }
  415. Actor& Actor::freezeRotZ(Bool on)
  416. {
  417. if(_actor)
  418. {
  419. btVector3 factor=_actor->getAngularFactor();
  420. if(on)
  421. {
  422. _actor->setAngularFactor (btVector3(0, 0, 1)); _actor->applyTorque (-_actor->getTotalTorque()); // clear Z torque
  423. btVector3 velocity=_actor->getAngularVelocity( ); velocity.setZ(0); _actor->setAngularVelocity( velocity); // clear Z velocity
  424. }
  425. factor.setZ(!on); _actor->setAngularFactor(factor);
  426. }
  427. return T;
  428. }
  429. Actor& Actor::freezeRot(Bool on)
  430. {
  431. if(_actor)
  432. {
  433. if(on)
  434. {
  435. _actor->setAngularFactor (btVector3(1, 1, 1)); _actor->applyTorque(-_actor->getTotalTorque()); // clear torque
  436. _actor->setAngularVelocity(btVector3(0, 0, 0)); // clear angular velocity
  437. }
  438. _actor->setAngularFactor(on ? btVector3(0, 0, 0) : btVector3(1, 1, 1));
  439. }
  440. return T;
  441. }
  442. Flt Actor:: mass( )C {if(_actor){Flt mass=_actor->getInvMass(); return mass ? 1/mass : 0;} return 0;}
  443. Actor& Actor:: mass(Flt mass ) {if(_actor)_actor->setMassProps(mass, Bullet.vec(inertia())); return T;}
  444. Flt Actor:: damping( )C {return _actor ? _actor->getLinearDamping () : 0;}
  445. Flt Actor:: adamping( )C {return _actor ? _actor->getAngularDamping() : 0;}
  446. Flt Actor::maxAngVel( )C {return 0;}
  447. Actor& Actor:: damping(Flt damping) {if(_actor)_actor->setDamping( damping , T.adamping()); return T;}
  448. Actor& Actor:: adamping(Flt damping) {if(_actor)_actor->setDamping(T.damping(), damping ); return T;}
  449. Actor& Actor::maxAngVel(Flt damping) {return T;}
  450. Bool Actor:: sleep( )C {return _actor ? !_actor->isActive() : false;}
  451. Actor& Actor:: sleep(Bool on )
  452. {
  453. if(_actor)
  454. {
  455. if(!on)_actor->activate();else
  456. {
  457. _actor->setAngularVelocity(btVector3(0, 0, 0));
  458. _actor->setLinearVelocity (btVector3(0, 0, 0));
  459. // following code taken from "btDiscreteDynamicsWorld::updateActivationState"
  460. if(_actor->isStaticOrKinematicObject())
  461. {
  462. _actor->setActivationState(ISLAND_SLEEPING);
  463. }else
  464. {
  465. if(_actor->getActivationState()==ACTIVE_TAG)_actor->setActivationState(WANTS_DEACTIVATION);
  466. }
  467. }
  468. }
  469. return T;
  470. }
  471. // TODO: check if the scale is OK vs PhysX, or maybe it needs to be dependent on mass?
  472. #define BULLET_SLEEP_ENERGY_LINEAR 0.013f
  473. #define BULLET_SLEEP_ENERGY_ANBULAR 0.02f
  474. Flt Actor::sleepEnergy( )C {return _actor ? Sqr(_actor->getLinearSleepingThreshold())/BULLET_SLEEP_ENERGY_LINEAR : 0;} // to match PhysX scale
  475. Actor& Actor::sleepEnergy(Flt energy) {if(_actor)_actor->setSleepingThresholds(Sqrt(energy*BULLET_SLEEP_ENERGY_LINEAR), Sqrt(energy*BULLET_SLEEP_ENERGY_ANBULAR)); return T;} // to match PhysX scale
  476. Bool Actor::ccd ( )C {return _actor ? _actor->getCcdMotionThreshold()!=0 : false;}
  477. Actor& Actor::ccd (Bool on )
  478. {
  479. if(_actor && on!=ccd())
  480. {
  481. if(on)
  482. {
  483. _actor->setCcdMotionThreshold (0.01f);
  484. _actor->setCcdSweptSphereRadius(0.01f);
  485. }else
  486. {
  487. _actor->setCcdMotionThreshold (0);
  488. _actor->setCcdSweptSphereRadius(0);
  489. }
  490. }
  491. return T;
  492. }
  493. Bool Actor::kinematic( )C {return _actor ? FlagTest(_actor->getCollisionFlags(), btCollisionObject::CF_KINEMATIC_OBJECT) : false;}
  494. Actor& Actor::kinematic(Bool on)
  495. {
  496. if(_actor)
  497. {
  498. UInt flags=_actor->getCollisionFlags(); if(FlagTest(flags, btCollisionObject::CF_KINEMATIC_OBJECT)!=on)
  499. {
  500. FlagToggle(flags, btCollisionObject::CF_KINEMATIC_OBJECT); _actor->setCollisionFlags(flags);
  501. if(on)
  502. { // clear velocities
  503. _actor->setAngularVelocity(btVector3(0, 0, 0));
  504. _actor->setLinearVelocity (btVector3(0, 0, 0));
  505. _actor->setActivationState (DISABLE_DEACTIVATION);
  506. }else _actor->forceActivationState(ACTIVE_TAG);
  507. }
  508. }
  509. return T;
  510. }
  511. Bool Actor::collision( )C {return _actor ? !FlagTest(_actor->getCollisionFlags(), btCollisionObject::CF_NO_CONTACT_RESPONSE) : true;}
  512. Actor& Actor::collision(Bool on)
  513. {
  514. if(_actor)
  515. {
  516. UInt flags=_actor->getCollisionFlags();
  517. FlagSet(flags, btCollisionObject::CF_NO_CONTACT_RESPONSE, !on);
  518. _actor->setCollisionFlags(flags);
  519. }
  520. return T;
  521. }
  522. Bool Actor::ray( )C {return _actor ? _actor->getBroadphaseProxy()->m_collisionFilterMask!=0 : false;}
  523. Actor& Actor::ray(Bool on) {if(_actor)_actor->getBroadphaseProxy()->m_collisionFilterMask=on; return T;}
  524. Bool Actor::trigger()C
  525. {
  526. // TODO: Bullet
  527. return false;
  528. }
  529. Actor& Actor::trigger(Bool on)
  530. {
  531. // TODO: Bullet
  532. return T;
  533. }
  534. Byte Actor::dominance()C
  535. {
  536. // TODO: Bullet
  537. return 0;
  538. }
  539. Actor& Actor::dominance(Byte dominance)
  540. {
  541. // TODO: Bullet
  542. return T;
  543. }
  544. PhysMtrl* Actor::material()C {return (_actor && _actor->material!=&Physics.mtrl_default) ? _actor->material : null;} // return default material always as null
  545. void RigidBody::materialApply()
  546. {
  547. setRestitution(material->bounciness());
  548. setFriction (Avg(material->frictionStatic(), material->frictionDynamic()));
  549. setDamping (material->damping(), material->adamping());
  550. // TODO: Bullet
  551. //setAnisotropicFriction
  552. }
  553. Box Actor::box()C
  554. {
  555. if(_actor)
  556. {
  557. btVector3 min, max; _actor->getAabb(min, max);
  558. return Box(Bullet.vec(min), Bullet.vec(max));
  559. }
  560. return 0;
  561. }
  562. Shape Actor::shape(Bool local)C
  563. {
  564. Shape shape;
  565. if(_actor)if(btCollisionShape *cs=_actor->getCollisionShape())
  566. {
  567. Bool child_matrix_apply=false;
  568. Matrix child_matrix;
  569. if(btCompoundShape *compound=CAST(btCompoundShape, cs))
  570. {
  571. if(!compound->getNumChildShapes())cs=null;else
  572. {
  573. child_matrix_apply=true;
  574. child_matrix =Bullet.matrix(compound->getChildTransform(0));
  575. cs = compound->getChildShape (0) ;
  576. }
  577. }
  578. if(btBoxShape *box =CAST(btBoxShape , cs)){Vec ext=Bullet.vec(box->getHalfExtentsWithMargin()); shape=Box(-ext, ext);}else
  579. if(btSphereShape *ball =CAST(btSphereShape , cs)){shape=Ball(ball->getRadius());}else
  580. if(btCapsuleShape *capsule=CAST(btCapsuleShape , cs)){Flt r=capsule->getRadius(); shape=Capsule(r, (capsule->getHalfHeight()+r)*2);}else
  581. if(btCylinderShape *tube =CAST(btCylinderShape , cs)){shape=Tube(tube->getRadius(), tube->getHalfExtentsWithMargin().y()*2);}else
  582. if(btStaticPlaneShape *plane =CAST(btStaticPlaneShape, cs)){Vec n=Bullet.vec(plane->getPlaneNormal()); shape=Plane(plane->getPlaneConstant()*n, n);}
  583. if(shape.type)
  584. {
  585. if(child_matrix_apply)shape*=child_matrix;
  586. if(!local )shape*=massCenterMatrix();else
  587. {
  588. Matrix temp; _actor->offset.inverse(temp, true); shape*=temp;
  589. }
  590. }
  591. }
  592. return shape;
  593. }
  594. Vec Actor::pos ( )C {return _actor ? _actor->offset.pos *Bullet.matrix(_actor->getWorldTransform() ) : 0;}
  595. Matrix3 Actor::orn ( )C {return _actor ? _actor->offset.orn()*Bullet.matrix(_actor->getWorldTransform().getBasis()) : MatrixIdentity.orn();}
  596. Matrix Actor::matrix( )C {return _actor ? _actor->offset *Bullet.matrix(_actor->getWorldTransform() ) : MatrixIdentity ;}
  597. Actor& Actor::pos (C Vec &pos)
  598. {
  599. if(_actor)
  600. {
  601. // desired_matrix = offset * bullet_matrix
  602. // offset * bullet_matrix = desired_matrix
  603. // bullet_matrix = GetTransform(offset, desired_matrix) = ~offset * desired_matrix
  604. Matrix temp; _actor->offset.inverse(temp, true); temp.mul(orn()).move(pos);
  605. _actor->getWorldTransform().getOrigin()=Bullet.vec(temp.pos);
  606. if(!_actor->isActive() && Bullet.world)Bullet.world->updateSingleAabb(_actor);
  607. sleep(false); // needs to be woken up
  608. REP(_actor->getNumConstraintRefs())if(btTypedConstraint *joint=_actor->getConstraintRef(i)) // wake up all actors linked by joints
  609. {
  610. if(btRigidBody *rb=&joint->getRigidBodyA())if(rb!=_actor)rb->activate();
  611. if(btRigidBody *rb=&joint->getRigidBodyB())if(rb!=_actor)rb->activate();
  612. }
  613. }
  614. return T;
  615. }
  616. Actor& Actor::orn(C Matrix3 &orn)
  617. {
  618. if(_actor)
  619. {
  620. // desired_matrix = offset * bullet_matrix
  621. // offset * bullet_matrix = desired_matrix
  622. // bullet_matrix = GetTransform(offset, desired_matrix) = ~offset * desired_matrix
  623. Matrix temp; _actor->offset.inverse(temp, true); temp.mul(orn).move(pos());
  624. _actor->getWorldTransform()=Bullet.matrix(temp);
  625. if(!_actor->isActive() && Bullet.world)Bullet.world->updateSingleAabb(_actor);
  626. sleep(false); // needs to be woken up
  627. REP(_actor->getNumConstraintRefs())if(btTypedConstraint *joint=_actor->getConstraintRef(i)) // wake up all actors linked by joints
  628. {
  629. if(btRigidBody *rb=&joint->getRigidBodyA())if(rb!=_actor)rb->activate();
  630. if(btRigidBody *rb=&joint->getRigidBodyB())if(rb!=_actor)rb->activate();
  631. }
  632. }
  633. return T;
  634. }
  635. Actor& Actor::matrix(C Matrix &matrix)
  636. {
  637. if(_actor)
  638. {
  639. // desired_matrix = offset * bullet_matrix
  640. // offset * bullet_matrix = desired_matrix
  641. // bullet_matrix = GetTransform(offset, desired_matrix) = ~offset * desired_matrix
  642. Matrix temp; _actor->offset.inverse(temp, true); temp.mul(matrix);
  643. _actor->setWorldTransform(Bullet.matrix(temp));
  644. if(!_actor->isActive() && Bullet.world)Bullet.world->updateSingleAabb(_actor);
  645. sleep(false); // needs to be woken up
  646. REP(_actor->getNumConstraintRefs())if(btTypedConstraint *joint=_actor->getConstraintRef(i)) // wake up all actors linked by joints
  647. {
  648. if(btRigidBody *rb=&joint->getRigidBodyA())if(rb!=_actor)rb->activate();
  649. if(btRigidBody *rb=&joint->getRigidBodyB())if(rb!=_actor)rb->activate();
  650. }
  651. }
  652. return T;
  653. }
  654. Actor& Actor::kinematicMoveTo(C Vec &pos ) {return T.pos (pos );}
  655. Actor& Actor::kinematicMoveTo(C Matrix3 &orn ) {return T.orn (orn );}
  656. Actor& Actor::kinematicMoveTo(C Matrix &matrix) {return T.matrix(matrix);}
  657. Vec Actor::angVel( )C {return _actor ? Bullet.vec(_actor->getAngularVelocity()) : 0;}
  658. Vec Actor:: vel( )C {return _actor ? Bullet.vec(_actor->getLinearVelocity ()) : 0;}
  659. Actor& Actor::angVel(C Vec &ang_vel) {if(_actor){_actor->setAngularVelocity(_actor->getAngularFactor()*Bullet.vec(ang_vel)); if(sleep() && ang_vel.any())sleep(false);} return T;}
  660. Actor& Actor:: vel(C Vec & vel) {if(_actor){_actor->setLinearVelocity (_actor->getLinearFactor ()*Bullet.vec( vel)); if(sleep() && vel.any())sleep(false);} return T;}
  661. Vec Actor::pointVelL (C Vec &pos)C {return _actor ? Bullet.vec(_actor->getVelocityInLocalPoint(Bullet.vec(pos*matrix()-massCenterW()))) : 0;}
  662. Vec Actor::pointVelW (C Vec &pos)C {return _actor ? Bullet.vec(_actor->getVelocityInLocalPoint(Bullet.vec(pos -massCenterW()))) : 0;}
  663. Vec Actor::massCenterW ( )C {return _actor ? Bullet.vec(_actor->getCenterOfMassPosition())+_actor->offset_com : 0;}
  664. Vec Actor::massCenterL ( )C {return massCenterW().divNormalized(matrix());}
  665. Matrix Actor::massCenterMatrix( )C {return _actor ? Bullet.matrix(_actor->getWorldTransform()) : MatrixIdentity;}
  666. Vec Actor::inertia()C
  667. {
  668. if(_actor)
  669. {
  670. Vec inertia=Bullet.vec(_actor->getInvInertiaDiagLocal());
  671. if( inertia.x)inertia.x=1/inertia.x;
  672. if( inertia.y)inertia.y=1/inertia.y;
  673. if( inertia.z)inertia.z=1/inertia.z;
  674. return inertia;
  675. }
  676. return 0;
  677. }
  678. Actor& Actor::inertia(C Vec &inertia) {if(_actor)_actor->setMassProps(mass(), Bullet.vec(inertia)); return T;}
  679. Actor& Actor::massCenterL(C Vec &center) {return T;}
  680. Actor& Actor::massCenterW(C Vec &center) {return T;}
  681. Actor& Actor::addAngVel (C Vec &ang_vel ) {if(_actor){_actor->setAngularVelocity (_actor->getAngularVelocity() + _actor->getAngularFactor()*Bullet.vec(ang_vel)); if(sleep() && ang_vel.any())sleep(false);} return T;}
  682. Actor& Actor::addVel (C Vec &vel ) {if(_actor){_actor-> setLinearVelocity (_actor-> getLinearVelocity() + _actor-> getLinearFactor()*Bullet.vec( vel)); if(sleep() && vel.any())sleep(false);} return T;}
  683. Actor& Actor::addImpulse(C Vec &impulse ) {if(_actor){_actor->applyCentralImpulse(Bullet.vec(impulse ) ); if(sleep() && impulse.any())sleep(false);} return T;}
  684. Actor& Actor::addImpulse(C Vec &impulse, C Vec &pos) {if(_actor){_actor->applyImpulse (Bullet.vec(impulse ), Bullet.vec(pos-massCenterW()) ); if(sleep() && impulse.any())sleep(false);} return T;}
  685. #if 0 // we can't use Force because we manually manage simulation steps durations and need to make sure we specify correct time duration, also these methods can be called after each step completed AND after all steps completed, so we have to use 'Physics.time' which is set to 'stepTime' and 'updatedTime', also on Bullet forces get cleared at the end of simulation, so if we've added a force in the last step, it would be ignored
  686. Actor& Actor::addTorque (C Vec &torque ) {if(_actor){_actor->applyTorque (Bullet.vec(torque ) ); if(sleep() && torque .any())sleep(false);} return T;}
  687. Actor& Actor::addForce (C Vec &force ) {if(_actor){_actor->applyCentralForce (Bullet.vec(force ) ); if(sleep() && force .any())sleep(false);} return T;}
  688. Actor& Actor::addForce (C Vec &force , C Vec &pos) {if(_actor){_actor->applyForce (Bullet.vec(force ), Bullet.vec(pos-massCenterW()) ); if(sleep() && force .any())sleep(false);} return T;}
  689. Actor& Actor::addAccel (C Vec &accel ) {if(_actor){_actor->applyCentralForce (Bullet.vec(accel*mass()) ); if(sleep() && accel .any())sleep(false);} return T;}
  690. #else
  691. Actor& Actor::addTorque (C Vec &torque ) {if(_actor){_actor->applyTorqueImpulse (Bullet.vec(torque *Physics.time()) ); if(sleep() && torque .any())sleep(false);} return T;}
  692. Actor& Actor::addForce (C Vec &force ) {if(_actor){_actor->applyCentralImpulse(Bullet.vec(force *Physics.time()) ); if(sleep() && force .any())sleep(false);} return T;}
  693. Actor& Actor::addForce (C Vec &force , C Vec &pos) {if(_actor){_actor->applyImpulse (Bullet.vec(force *Physics.time()), Bullet.vec(pos-massCenterW()) ); if(sleep() && force .any())sleep(false);} return T;}
  694. #if 0
  695. Actor& Actor::addAccel (C Vec &accel ) {if(_actor){_actor->applyCentralImpulse(Bullet.vec(accel*(mass()*Physics.time())) ); if(sleep() && accel .any())sleep(false);} return T;}
  696. #else
  697. Actor& Actor::addAccel (C Vec &accel ) {return addVel(accel*Physics.time());}
  698. #endif
  699. #endif
  700. /******************************************************************************/
  701. #endif
  702. /******************************************************************************/
  703. Bool Actor::materialForce(PhysMtrl *material)
  704. {
  705. if(_actor)
  706. {
  707. if(!material)material=&Physics.mtrl_default; // always set valid material
  708. #if PHYSX
  709. if(PxMaterial *m=material->_m)
  710. {
  711. for(Int offset=0, shapes=_actor->getNbShapes(); shapes>0; )
  712. {
  713. PxShape *shape[32]; Int s=Min(shapes, Elms(shape));
  714. REP(_actor->getShapes(shape, s, offset))shape[i]->setMaterials(&m, 1);
  715. shapes-=s;
  716. offset+=s;
  717. }
  718. // leave opened brace
  719. #else
  720. {
  721. _actor->material=material;
  722. _actor->materialApply();
  723. // leave opened brace
  724. #endif
  725. damping(material->damping()).adamping(material->adamping());
  726. return true;
  727. }
  728. }
  729. return false;
  730. }
  731. Actor& Actor::material(PhysMtrl *material)
  732. {
  733. if(_actor)
  734. {
  735. if(!material)material=&Physics.mtrl_default; // always set valid material
  736. PhysMtrl *old_mtrl=T.material(); if(!old_mtrl)old_mtrl=&Physics.mtrl_default; // always set valid material
  737. if(material!=old_mtrl && materialForce(material))
  738. {
  739. Flt old_density=old_mtrl->density(), new_density=material->density();
  740. if(!Equal(old_density, new_density) && old_density>EPS && new_density>EPS)
  741. {
  742. Flt mass=T.mass();
  743. if( mass>EPS)T.mass(mass*new_density/old_density);
  744. }
  745. }
  746. }
  747. return T;
  748. }
  749. /******************************************************************************/
  750. Bool Actor::ignored(C Actor &actor)C {return (T._actor && actor._actor) ? Physics.ignored(*T._actor, *actor._actor) : false;}
  751. Bool Actor::ignored(C ActorInfo &actor)C {return (T._actor && actor._actor) ? Physics.ignored(*T._actor, *actor._actor) : false;}
  752. /******************************************************************************/
  753. #pragma pack(push, 1)
  754. struct ActorDesc
  755. {
  756. Byte group, dominance;
  757. U16 flag;
  758. UInt user;
  759. //Flt mass, damping, adamping, sleep; these are ignored
  760. Vec vel, ang_vel;
  761. Matrix matrix;
  762. };
  763. #pragma pack(pop)
  764. Bool Actor::saveState(File &f)C
  765. {
  766. f.cmpUIntV(0); // version
  767. ActorDesc desc;
  768. Unaligned(desc.group , group ());
  769. Unaligned(desc.dominance, dominance());
  770. _Unaligned(desc.user , (UIntPtr)user());
  771. //Unaligned(desc. mass, mass());
  772. //Unaligned(desc. damping, damping());
  773. //Unaligned(desc.adamping, adamping());
  774. //Unaligned(desc.sleep , sleepEnergy());
  775. Unaligned(desc. vel, vel());
  776. Unaligned(desc.ang_vel, angVel());
  777. Unaligned(desc. matrix, matrix());
  778. U16 flag=0;
  779. if(freezePosX())flag|=ACTOR_FREEZE_POS_X;
  780. if(freezePosY())flag|=ACTOR_FREEZE_POS_Y;
  781. if(freezePosZ())flag|=ACTOR_FREEZE_POS_Z;
  782. if(freezeRotX())flag|=ACTOR_FREEZE_ROT_X;
  783. if(freezeRotY())flag|=ACTOR_FREEZE_ROT_Y;
  784. if(freezeRotZ())flag|=ACTOR_FREEZE_ROT_Z;
  785. if(kinematic ())flag|=ACTOR_KINEMATIC;
  786. if(gravity ())flag|=ACTOR_GRAVITY;
  787. if(ray ())flag|=ACTOR_RAY;
  788. if(collision ())flag|=ACTOR_COLLISION;
  789. if(trigger ())flag|=ACTOR_TRIGGER;
  790. if(sleep ())flag|=ACTOR_SLEEP;
  791. if(ccd ())flag|=ACTOR_CCD;
  792. Unaligned(desc.flag, flag);
  793. f.put(desc);
  794. return f.ok();
  795. }
  796. Bool Actor::loadState(File &f) // don't delete on fail, as here we're loading only state !! do not change 'obj' because that's a pointer, and game object classes expect that 'loadState' does not modify this parameter !!
  797. {
  798. switch(f.decUIntV()) // version
  799. {
  800. case 0:
  801. {
  802. ActorDesc desc; if(f.getFast(desc))
  803. {
  804. kinematic(FlagTest(Unaligned(desc.flag), ACTOR_KINEMATIC)); // !! set 'kinematic' as first, because it could disallow setting other members (such as 'vel, angVel, sleep') !!
  805. group ( Unaligned(desc.group ));
  806. dominance( Unaligned(desc.dominance));
  807. user ((Ptr)Unaligned(desc.user ));
  808. //mass(Unaligned(desc. mass)); ignore these and take from 'PhysMtrl' and 'PhysBody'
  809. //damping(Unaligned(desc. damping));
  810. //adamping(Unaligned(desc.adamping));
  811. //sleepEnergy(Unaligned(desc. sleep));
  812. matrix(Unaligned(desc. matrix));
  813. vel(Unaligned(desc. vel));
  814. angVel(Unaligned(desc.ang_vel));
  815. freezePosX(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_POS_X));
  816. freezePosY(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_POS_Y));
  817. freezePosZ(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_POS_Z));
  818. freezeRotX(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_ROT_X));
  819. freezeRotY(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_ROT_Y));
  820. freezeRotZ(FlagTest(Unaligned(desc.flag), ACTOR_FREEZE_ROT_Z));
  821. gravity (FlagTest(Unaligned(desc.flag), ACTOR_GRAVITY ));
  822. ray (FlagTest(Unaligned(desc.flag), ACTOR_RAY ));
  823. collision (FlagTest(Unaligned(desc.flag), ACTOR_COLLISION ));
  824. trigger (FlagTest(Unaligned(desc.flag), ACTOR_TRIGGER ));
  825. ccd (FlagTest(Unaligned(desc.flag), ACTOR_CCD ));
  826. sleep(FlagTest(Unaligned(desc.flag), ACTOR_SLEEP)); // !! set 'sleep' as last, because other methods may change it !!
  827. if(f.ok())return true;
  828. }
  829. }break;
  830. }
  831. return false;
  832. }
  833. /******************************************************************************/
  834. }
  835. /******************************************************************************/