Ragdoll.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************
  5. TODO: Ragdoll actor shape creation should be verified across many models,
  6. if no universal code is found, Ragdoll Editor should be added.
  7. /******************************************************************************/
  8. static Shape ShapeBone(C Vec &from, C Vec &to, Flt width)
  9. {
  10. Shape shape;
  11. if(width>=0.5f)
  12. {
  13. shape.type=SHAPE_BALL; Ball &ball=shape.ball;
  14. ball.pos=Avg(from, to);
  15. ball.r =width*(to-from).length();
  16. }else
  17. {
  18. shape.type=SHAPE_CAPSULE; Capsule &capsule=shape.capsule;
  19. capsule.pos=Avg(from, to);
  20. capsule.up = to-from;
  21. capsule.h =capsule.up.normalize();
  22. capsule.r =Max(0.01f, width*capsule.h);
  23. Flt eps=capsule.r*0.5f;
  24. capsule.pos-=eps*capsule.up;
  25. capsule.h +=eps*2;
  26. }
  27. return shape;
  28. }
  29. inline static Shape ShapeBone(C SkelBone &bone) {return ShapeBone(bone.pos, bone.to(), bone.width);} // return shape from bone
  30. /******************************************************************************/
  31. void Ragdoll::zero()
  32. {
  33. _scale=0;
  34. _skel =null;
  35. }
  36. Ragdoll::Ragdoll() {zero();}
  37. Ragdoll& Ragdoll::del()
  38. {
  39. _joints.del();
  40. _bones .del();
  41. _resets.del();
  42. _aggr .del(); // delete aggregate after actors, so they won't be re-inserted into scene when aggregate is deleted
  43. zero(); return T;
  44. }
  45. Bool Ragdoll::createTry(C AnimatedSkeleton &anim_skel, Flt density, Bool kinematic)
  46. {
  47. del();
  48. if(T._skel=anim_skel.skeleton())
  49. {
  50. T._scale=anim_skel.scale();
  51. Memt<Shape> shapes;
  52. C Skeleton &skel=*anim_skel.skeleton();
  53. Int body=-1;
  54. FREPA(skel.bones) // order is important, main bones should be added at start, in case the skeleton doesn't have "body" bone, and as main bone (zero) should be set some different
  55. {
  56. C SkelBone &sbon=skel.bones[i];
  57. if(sbon.flag&BONE_RAGDOLL)
  58. {
  59. Vec from =sbon.pos,
  60. to =sbon.to();
  61. Flt width=sbon.width;
  62. if(sbon.type==BONE_FOOT)
  63. {
  64. C SkelBone *b=skel.findBone(BONE_TOE, sbon.type_index);
  65. if(b){from=Avg(sbon.pos, sbon.to()); to=b->to(); width=Avg(width, b->width)*0.5f; Vec down=sbon.dir*(width*Dist(from, to)*0.5f); from-=down; to-=down;}else width*=0.8f;
  66. }else
  67. if(sbon.type==BONE_HAND)
  68. {
  69. C SkelBone *b=skel.findBone(BONE_FINGER, (sbon.type_index>=0) ? 2 : -3); // find middle finger (2 for right, -3 for left hand)
  70. if(b){to=b->to(); width*=0.6f;}
  71. }else
  72. if(sbon.type==BONE_SPINE && sbon.type_sub==0)
  73. {
  74. body=_bones.elms();
  75. _resets.add(i); // add main bone for resetting
  76. }
  77. Shape &s =shapes.New(); s=ShapeBone(from, to, width);
  78. Bone &rb=_bones.New(); Set(rb.name, sbon.name);
  79. rb.skel_bone =i;
  80. rb.rbon_parent=0xFF;
  81. if(!rb.actor.createTry(s*T._scale, density, &VecZero, kinematic))return false;
  82. }else
  83. {
  84. _resets.add(i);
  85. }
  86. }
  87. // force 'body' bone to have index=0
  88. if(body>0)
  89. {
  90. Swap(_bones[0], _bones[body]);
  91. Swap(shapes[0], shapes[body]);
  92. }
  93. // set parents, damping and solver iterations
  94. REPA(T)
  95. {
  96. // find first parent which has an actor
  97. Bone &rb=bone(i);
  98. C SkelBone &sb=skel.bones[rb.skel_bone];
  99. if(i) // skip the main bone
  100. {
  101. Byte skel_bone_parent =sb.parent;
  102. if( skel_bone_parent!=0xFF) // if has a parent
  103. {
  104. Int rbone =findBoneIndexFromSkelBone(skel_bone_parent); // find ragdoll bone assigned to skeleton parent bone
  105. if( rbone>=0)rb.rbon_parent=rbone; // if exists, then set as ragdoll parent
  106. }
  107. }
  108. if(sb.type==BONE_HEAD)rb.actor.adamping(7);
  109. else rb.actor.adamping(4);
  110. rb.actor. damping(0.5f).sleepEnergy(0.1f);
  111. }
  112. if(!kinematic)
  113. {
  114. // joints
  115. REPA(_bones)
  116. if(i) // skip the main bone
  117. {
  118. Bone &rb= bone (i);
  119. C SkelBone &sb=skel.bones[rb.skel_bone];
  120. Byte rbon_parent=((rb.rbon_parent==0xFF) ? 0 : rb.rbon_parent); // if doesn't have a parent then use the main bone
  121. //if(rbon_parent!=0xFF)
  122. {
  123. Bone &rp= _bones[ rbon_parent];
  124. C SkelBone &sp=skel.bones[rp.skel_bone ];
  125. if(sb.type==BONE_HEAD)
  126. {
  127. if(sp.type==BONE_NECK)_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad(30), DegToRad(35));
  128. else _joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad(50), DegToRad(40));
  129. }else
  130. if(sb.type==BONE_NECK )_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad( 20), DegToRad( 5));else
  131. if(sb.type==BONE_SHOULDER )_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad( 5), DegToRad( 5));else
  132. if(sb.type==BONE_UPPER_ARM )_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad( 80), DegToRad(30));else
  133. if(sb.type==BONE_UPPER_LEG )_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad(155), DegToRad(25));else
  134. if(sb.type==BONE_SPINE )_joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad( 40), DegToRad(30));else
  135. if(sb.type==BONE_FOOT )_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(1, 0,0), -DegToRad(45), DegToRad( 45));else
  136. if(sb.type==BONE_HAND && sb.type_index< 0)_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(0, 1,0), -DegToRad(80), DegToRad( 80));else
  137. if(sb.type==BONE_HAND && sb.type_index>=0)_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(0,-1,0), -DegToRad(80), DegToRad( 80));else
  138. if(sb.type==BONE_LOWER_ARM && sb.type_index< 0)_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(0, 1,0), 0 , DegToRad(140));else
  139. if(sb.type==BONE_LOWER_ARM && sb.type_index>=0)_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(0,-1,0), 0 , DegToRad(140));else
  140. if(sb.type==BONE_LOWER_LEG )_joints.New().createBodyHinge (rb.actor, rp.actor, sb.pos*_scale, Vec(1, 0,0), 0 , DegToRad(150));else
  141. _joints.New().createBodySpherical(rb.actor, rp.actor, sb.pos*_scale, sb.dir, DegToRad(40), DegToRad(30));
  142. }
  143. }
  144. // ignore
  145. REPA(T)
  146. REPD(j, i)
  147. if(Cuts(shapes[i], shapes[j]))
  148. bone(i).actor.ignore(bone(j).actor);
  149. }
  150. _aggr.create(bones()); REPA(T)_aggr.add(bone(i).actor);
  151. return true;
  152. }
  153. return false;
  154. }
  155. /******************************************************************************/
  156. Ragdoll& Ragdoll::create(C AnimatedSkeleton &anim_skel, Flt density, Bool kinematic)
  157. {
  158. if(!createTry(anim_skel, density, kinematic))Exit("Can't create Ragdoll");
  159. return T;
  160. }
  161. /******************************************************************************
  162. void updateShapes(AnimatedSkeleton &anim_skel); // update 'shape_t' according to 'shape' and skeleton animation, 'anim_skel' must be set to the same skeleton which ragdoll was created from
  163. void Ragdoll::updateShape(AnimatedSkeleton &anim_skel)
  164. {
  165. if(T.skel==anim_skel.skeleton())REP(bones)shape_t[i]=shape[i]*anim_skel.bone(bone[i].skel_bone).matrix;
  166. }
  167. /******************************************************************************/
  168. Ragdoll& Ragdoll::fromSkel(C AnimatedSkeleton &anim_skel, C Vec &vel, Bool immediate_even_for_kinematic_ragdoll)
  169. {
  170. if(_skel==anim_skel.skeleton())
  171. {
  172. Bool scaled =(_scale!=1),
  173. kinematic=(immediate_even_for_kinematic_ragdoll ? false : T.kinematic());
  174. REPA(T)
  175. {
  176. Bone &rbon =bone(i);
  177. Actor &actor=rbon.actor;
  178. #if 1
  179. Matrix matrix=anim_skel.bones[rbon.skel_bone]._matrix;
  180. #else
  181. Matrix matrix=(i ? anim_skel.bone(rbon.skel_bone)._matrix : anim_skel.matrix);
  182. #endif
  183. if(scaled)matrix.orn()/=_scale;
  184. if(kinematic)actor.kinematicMoveTo(matrix);
  185. else actor.matrix (matrix).vel(vel).angVel(VecZero);
  186. }
  187. }
  188. return T;
  189. }
  190. Ragdoll& Ragdoll::toSkel(AnimatedSkeleton &anim_skel)
  191. {
  192. if(_skel==anim_skel.skeleton() && bones())
  193. {
  194. C Skeleton &skel=*_skel;
  195. // reset the orientation of non-ragdoll bones (and main and root) for default pose (the one from default Skeleton)
  196. anim_skel.root .clear();
  197. REPA(_resets)anim_skel.bones[_resets[i]].clear();
  198. #if 0
  199. {
  200. Byte sbone =_resets[i];
  201. Orient &bone_orn = anim_skel.bone(sbone).orn;
  202. SkelBone &skel_bone= skel.bone(sbone);
  203. Byte sparent = skel_bone.parent;
  204. if(sparent==0xFF)bone_orn=GetAnimOrient(skel_bone);
  205. else bone_orn=GetAnimOrient(skel_bone, &skel.bone(sparent));
  206. }
  207. #endif
  208. // set bone oriantation according to actors
  209. Matrix body= bone(0).actor.matrix();
  210. Matrix3 ibody; body.orn().inverse(ibody, true);
  211. for(Int i=1; i<bones(); i++) // skip the main bone (zero) because it's set in the reset
  212. {
  213. Bone &rbon = bone(i);
  214. Byte sbone = rbon.skel_bone,
  215. rparent = rbon.rbon_parent;
  216. AnimSkelBone &asbon =anim_skel.bones[sbone];
  217. C SkelBone &skel_bone= skel.bones[sbone];
  218. asbon.clear();
  219. if(InRange(rparent, T))asbon.orn=GetAnimOrient(skel_bone, rbon.actor.orn(), &skel.bones[skel_bone.parent], &bone(rparent).actor.orn());
  220. else asbon.orn=GetAnimOrient(skel_bone, rbon.actor.orn()*ibody);
  221. }
  222. anim_skel.updateMatrix(body);
  223. }
  224. return T;
  225. }
  226. Ragdoll& Ragdoll::toSkelBlend(AnimatedSkeleton &anim_skel, Flt blend)
  227. {
  228. if(_skel==anim_skel.skeleton() && bones())
  229. {
  230. Flt blend1=1-blend;
  231. C Skeleton &skel =*_skel;
  232. // reset the orientation of non-ragdoll bones (and main) for default pose (the one from default Skeleton)
  233. REPA(_resets)
  234. {
  235. Byte sbone =_resets[i];
  236. AnimSkelBone &asbon = anim_skel.bones[sbone];
  237. C SkelBone &skel_bone= skel.bones[sbone];
  238. Byte sparent = skel_bone.parent;
  239. asbon.orn*=blend1;
  240. asbon.rot*=blend1;
  241. asbon.pos*=blend1;
  242. if(sparent==0xFF)asbon.orn+=blend*GetAnimOrient(skel_bone);
  243. else asbon.orn+=blend*GetAnimOrient(skel_bone, &skel.bones[sparent]);
  244. }
  245. // set bone oriantation according to actors
  246. Matrix ragdoll_body=bone(0).actor.matrix();
  247. Matrix3 ibody; ragdoll_body.orn().inverse(ibody, true);
  248. for(Int i=1; i<bones(); i++) // skip the main bone (zero) because it's set in the reset
  249. {
  250. Bone &rbon = bone(i);
  251. Byte sbone = rbon.skel_bone,
  252. rparent = rbon.rbon_parent;
  253. AnimSkelBone &asbon =anim_skel.bones[sbone];
  254. C SkelBone &skel_bone= skel.bones[sbone];
  255. asbon.orn*=blend1;
  256. asbon.rot*=blend1;
  257. asbon.pos*=blend1;
  258. if(InRange(rparent, T))asbon.orn+=blend*GetAnimOrient(skel_bone, rbon.actor.orn(), &skel.bones[skel_bone.parent], &bone(rparent).actor.orn());
  259. else asbon.orn+=blend*GetAnimOrient(skel_bone, rbon.actor.orn()*ibody);
  260. }
  261. // convert root to matrix, and zero himself so it won't be taken into account
  262. Matrix temp=anim_skel.matrix(); temp.orn()/=anim_skel._scale; anim_skel.root.clear();
  263. // blend matrix with ragdoll main bone matrix
  264. ragdoll_body*=blend;
  265. temp *=blend1;
  266. temp+=ragdoll_body;
  267. temp.normalize();
  268. // update skeleton according to obtained matrix
  269. anim_skel.updateMatrix(temp);
  270. }
  271. return T;
  272. }
  273. /******************************************************************************
  274. Flt area (); // total surface area of shapes
  275. Flt volume(); // total volume of shapes
  276. Flt Ragdoll::area (){Flt a=0; REP(_bones)a+=shape[i].area (); return a*Sqr (scale);}
  277. Flt Ragdoll::volume(){Flt v=0; REP(_bones)v+=shape[i].volume(); return v*Cube(scale);}
  278. /******************************************************************************/
  279. Ragdoll& Ragdoll::pos (C Vec &pos ) {Vec delta=pos-T.pos(); REPAO(_bones).actor.pos(bone(i).actor.pos()+delta); return T;}
  280. Ragdoll& Ragdoll::vel (C Vec &vel ) {REPAO(_bones).actor.vel (vel ); return T;}
  281. Ragdoll& Ragdoll:: damping (Flt damping ) {REPAO(_bones).actor. damping (damping ); return T;}
  282. Ragdoll& Ragdoll::adamping (Flt damping ) {REPAO(_bones).actor.adamping (damping ); return T;}
  283. Ragdoll& Ragdoll::kinematic (Bool on ) {REPAO(_bones).actor.kinematic (on ); return T;}
  284. Ragdoll& Ragdoll::gravity (Bool on ) {REPAO(_bones).actor.gravity (on ); return T;}
  285. Ragdoll& Ragdoll::ray (Bool on ) {REPAO(_bones).actor.ray (on ); return T;}
  286. Ragdoll& Ragdoll::collision (Bool on ) {REPAO(_bones).actor.collision (on ); return T;}
  287. Ragdoll& Ragdoll::active (Bool on ) {REPAO(_bones).actor.active (on ); return T;}
  288. Ragdoll& Ragdoll::sleep (Bool sleep ) {REPAO(_bones).actor.sleep (sleep ); return T;}
  289. Ragdoll& Ragdoll::sleepEnergy(Flt energy ) {REPAO(_bones).actor.sleepEnergy(energy ); return T;}
  290. Ragdoll& Ragdoll::ccd (Bool on ) {REPAO(_bones).actor.ccd (on ); return T;}
  291. Ragdoll& Ragdoll::user (Ptr user ) {REPAO(_bones).actor.user (user ); return T;}
  292. Ragdoll& Ragdoll::obj (Ptr obj ) {REPAO(_bones).actor.obj (obj ); return T;}
  293. Ragdoll& Ragdoll::group (Byte group ) {REPAO(_bones).actor.group (group ); return T;}
  294. Ragdoll& Ragdoll::dominance (Byte dominance) {REPAO(_bones).actor.dominance (dominance); return T;}
  295. Ragdoll& Ragdoll::material (PhysMtrl *material ) {REPAO(_bones).actor.material (material ); return T;}
  296. Vec Ragdoll::pos ()C {return bones() ? bone(0).actor.pos () : 0 ;}
  297. Vec Ragdoll::vel ()C {return bones() ? bone(0).actor.vel () : 0 ;}
  298. Flt Ragdoll:: damping ()C {return bones() ? bone(0).actor. damping () : 0 ;}
  299. Flt Ragdoll::adamping ()C {return bones() ? bone(0).actor.adamping () : 0 ;}
  300. Bool Ragdoll::kinematic ()C {return bones() ? bone(0).actor.kinematic () : false;}
  301. Bool Ragdoll::gravity ()C {return bones() ? bone(0).actor.gravity () : false;}
  302. Bool Ragdoll::ray ()C {return bones() ? bone(0).actor.ray () : false;}
  303. Bool Ragdoll::collision ()C {return bones() ? bone(0).actor.collision () : false;}
  304. Ptr Ragdoll::user ()C {return bones() ? bone(0).actor.user () : null ;}
  305. Ptr Ragdoll::obj ()C {return bones() ? bone(0).actor.obj () : null ;}
  306. Byte Ragdoll::group ()C {return bones() ? bone(0).actor.group () : 0 ;}
  307. Byte Ragdoll::dominance ()C {return bones() ? bone(0).actor.dominance () : 0 ;}
  308. PhysMtrl* Ragdoll::material ()C {return bones() ? bone(0).actor.material () : null ;}
  309. Bool Ragdoll::sleep ()C {return bones() ? bone(0).actor.sleep () : false;}
  310. Flt Ragdoll::sleepEnergy()C {return bones() ? bone(0).actor.sleepEnergy() : 0 ;}
  311. Bool Ragdoll::ccd ()C {return bones() ? bone(0).actor.ccd () : false;}
  312. /******************************************************************************/
  313. Ragdoll& Ragdoll::ignore(Actor &actor, Bool ignore) {REPAO(_bones).actor.ignore(actor, ignore); return T;}
  314. /******************************************************************************/
  315. Int Ragdoll::findBoneI(CChar8 *name) {REPA(T)if(Equal(bone(i).name, name))return i; return -1;}
  316. Ragdoll::Bone* Ragdoll::findBone (CChar8 *name) {Int i=findBoneI(name); return (i<0) ? null : &bone(i);}
  317. Int Ragdoll:: getBoneI(CChar8 *name) {Int i=findBoneI(name); if(i<0)Exit(S+"Bone \""+name+"\" not found in Ragdoll."); return i;}
  318. Ragdoll::Bone& Ragdoll:: getBone (CChar8 *name) {return bone(getBoneI(name));}
  319. /******************************************************************************/
  320. Int Ragdoll::findBoneIndexFromSkelBone(Byte skel_bone_index)C
  321. {
  322. if(bones())
  323. {
  324. if(_skel && InRange(skel_bone_index, _skel->bones))for(;;)
  325. {
  326. if(_skel->bones[skel_bone_index].flag&BONE_RAGDOLL) // if skeleton bone should contain a bone in the ragdoll
  327. {
  328. REPA(T)if(bone(i).skel_bone==skel_bone_index)return i;
  329. }
  330. skel_bone_index=_skel->bones[skel_bone_index].parent;
  331. if(skel_bone_index==0xFF)break;
  332. }
  333. return 0;
  334. }
  335. return -1;
  336. }
  337. Int Ragdoll::findBoneIndexFromVtxMatrix(Byte matrix_index)C
  338. {
  339. return findBoneIndexFromSkelBone(matrix_index-1);
  340. }
  341. /******************************************************************************/
  342. void Ragdoll::draw(C Color &col)C
  343. {
  344. REPAO(_bones).actor.draw(col);
  345. }
  346. /******************************************************************************/
  347. #pragma pack(push, 1)
  348. struct RagdollDesc
  349. {
  350. Byte group, dominance, material;
  351. UInt user, flag;
  352. Flt sleep_energy;
  353. };
  354. struct RagdollActorDesc
  355. {
  356. Vec vel, ang_vel;
  357. Matrix matrix;
  358. };
  359. #pragma pack(pop)
  360. Bool Ragdoll::saveState(File &f, Bool include_matrix_vel)C
  361. {
  362. f.cmpUIntV(0);
  363. RagdollDesc desc;
  364. _Unaligned(desc.material , 0);
  365. Unaligned(desc.group , group());
  366. Unaligned(desc.dominance , dominance());
  367. _Unaligned(desc.user , (UIntPtr)user());
  368. Unaligned(desc.sleep_energy, sleepEnergy());
  369. UInt flag=0;
  370. if(kinematic())flag|=ACTOR_KINEMATIC;
  371. if(gravity ())flag|=ACTOR_GRAVITY;
  372. if(ray ())flag|=ACTOR_RAY;
  373. if(collision())flag|=ACTOR_COLLISION;
  374. if(sleep ())flag|=ACTOR_SLEEP;
  375. if(ccd ())flag|=ACTOR_CCD;
  376. Unaligned(desc.flag, flag);
  377. f<<desc;
  378. f.putBool(include_matrix_vel); if(include_matrix_vel)
  379. {
  380. f.putInt(bones()); FREPA(T)
  381. {
  382. C Actor &actor=bone(i).actor;
  383. RagdollActorDesc ad;
  384. Unaligned(ad.vel , actor.vel ());
  385. Unaligned(ad.ang_vel, actor.angVel());
  386. Unaligned(ad.matrix , actor.matrix());
  387. f<<ad;
  388. }
  389. }
  390. return f.ok();
  391. }
  392. Bool Ragdoll::loadState(File &f) // don't delete on fail, as here we're loading only state
  393. {
  394. switch(f.decUIntV())
  395. {
  396. case 0:
  397. {
  398. RagdollDesc desc; if(f.getFast(desc))
  399. {
  400. group ( Unaligned(desc.group ));
  401. dominance ( Unaligned(desc.dominance ));
  402. user (Ptr(Unaligned(desc.user )));
  403. sleepEnergy( Unaligned(desc.sleep_energy));
  404. kinematic(FlagTest(Unaligned(desc.flag), ACTOR_KINEMATIC));
  405. gravity (FlagTest(Unaligned(desc.flag), ACTOR_GRAVITY ));
  406. ray (FlagTest(Unaligned(desc.flag), ACTOR_RAY ));
  407. collision(FlagTest(Unaligned(desc.flag), ACTOR_COLLISION));
  408. sleep (FlagTest(Unaligned(desc.flag), ACTOR_SLEEP ));
  409. ccd (FlagTest(Unaligned(desc.flag), ACTOR_CCD ));
  410. if(f.getBool())
  411. {
  412. Int bones =f.getInt();
  413. if( bones!=T.bones ()) // number of bones doesn't match (we're dealing with a different ragdoll than before)
  414. {
  415. if(bones>=1) // if there was at least one bone saved
  416. {
  417. RagdollActorDesc ad; f>>ad; // load first bone
  418. f.skip((bones-1)*SIZE(ad)); // skip the rest
  419. FREPA(T) // set all bones basing on the first
  420. {
  421. bone(i).actor.vel(Unaligned(ad.vel)).angVel(Unaligned(ad.ang_vel)).matrix(Unaligned(ad.matrix));
  422. }
  423. }
  424. }else
  425. FREPA(T)
  426. {
  427. RagdollActorDesc ad; f>>ad;
  428. bone(i).actor.vel(Unaligned(ad.vel)).angVel(Unaligned(ad.ang_vel)).matrix(Unaligned(ad.matrix));
  429. }
  430. }
  431. if(f.ok())return true;
  432. }
  433. }break;
  434. }
  435. return false;
  436. }
  437. /******************************************************************************/
  438. }
  439. /******************************************************************************/