Animated Skeleton.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. // FIXME: support MatrixM (it would be best if we keep Matrix for all bones, but only global offset as VecD somehow) however it's unlikely
  6. /******************************************************************************/
  7. // ANIM SKEL BONE
  8. /******************************************************************************/
  9. void AnimatedSkeletonBone::clear()
  10. {
  11. orn .zero();
  12. rot .zero();
  13. pos .zero();
  14. scale.zero();
  15. #if HAS_ANIM_COLOR
  16. color.set(1);
  17. #endif
  18. _force_custom=_world_space_transform=false;
  19. }
  20. void AnimatedSkeletonBone::clear(Flt blend)
  21. {
  22. if(blend>0)
  23. {
  24. if(blend>=1)clear();else
  25. {
  26. Flt blend1=1-blend;
  27. orn *=blend1;
  28. rot *=blend1;
  29. pos *=blend1;
  30. scale*=blend1;
  31. #if HAS_ANIM_COLOR
  32. color*=blend1; color+=blend; // color=Vec4(1)*blend + color*(1-blend);
  33. #endif
  34. if(_world_space_transform)_world_space_transform_matrix.identity(blend);
  35. }
  36. }
  37. }
  38. void AnimatedSkeletonBone::forceMatrix(C Matrix &matrix)
  39. {
  40. _force_custom =true;
  41. _force_custom_matrix=matrix;
  42. }
  43. /******************************************************************************/
  44. // ANIM SKEL
  45. /******************************************************************************/
  46. void AnimatedSkeleton::zero()
  47. {
  48. fur_stiffness=0;
  49. fur_gravity =0;
  50. fur_vel_scale=0;
  51. root.zero();
  52. _updated_vel=false;
  53. _scale =0;
  54. _skeleton =null;
  55. }
  56. AnimatedSkeleton::AnimatedSkeleton() {zero();}
  57. AnimatedSkeleton& AnimatedSkeleton::del()
  58. {
  59. bones.del();
  60. slots.del();
  61. zero(); return T;
  62. }
  63. AnimatedSkeleton& AnimatedSkeleton::create(C Skeleton *skeleton, Flt scale, C Matrix &initial_matrix) // !! 'initial_matrix' can be 'root._matrix' !!
  64. {
  65. _updated_vel=false;
  66. T._scale =scale;
  67. if(T._skeleton=skeleton)
  68. {
  69. bones.setNum(skeleton->bones.elms()); REPAO(bones).zero();
  70. slots.setNum(skeleton->slots.elms()); REPAO(slots).zero();
  71. }else
  72. {
  73. bones.clear();
  74. slots.clear();
  75. }
  76. fur_stiffness= 0.0001f;
  77. fur_gravity =-1;
  78. fur_vel_scale=-0.75f;
  79. Matrix temp=initial_matrix; // copy in case 'initial_matrix' is 'root._matrix'
  80. root.zero();
  81. root._center=temp.pos;
  82. root._matrix=temp;
  83. root._matrix.normalize(scale);
  84. return T;
  85. }
  86. AnimatedSkeleton& AnimatedSkeleton::create(AnimatedSkeleton &src)
  87. {
  88. if(&src!=this)
  89. {
  90. _scale =src._scale;
  91. _skeleton=src._skeleton;
  92. bones =src. bones;
  93. slots =src. slots;
  94. root=src.root;
  95. fur_gravity =src.fur_gravity ;
  96. fur_stiffness=src.fur_stiffness;
  97. fur_vel_scale=src.fur_vel_scale;
  98. _updated_vel=src._updated_vel;
  99. }
  100. return T;
  101. }
  102. /******************************************************************************/
  103. // GET
  104. /******************************************************************************/
  105. AnimSkelBone* AnimatedSkeleton::findBone (BONE_TYPE type, Int type_index, Int type_sub) {return skeleton() ? bones.addr(skeleton()->findBoneI(type, type_index, type_sub)) : null;}
  106. Int AnimatedSkeleton::findBoneI (BONE_TYPE type, Int type_index, Int type_sub)C {return skeleton() ? skeleton()->findBoneI(type, type_index, type_sub) : -1;}
  107. Byte AnimatedSkeleton::findBoneB (BONE_TYPE type, Int type_index, Int type_sub)C {return skeleton() ? skeleton()->findBoneB(type, type_index, type_sub) : 255;}
  108. SkelAnim* AnimatedSkeleton::findSkelAnim(C Str &name)C {return skeleton() ? skeleton()->findSkelAnim(name) : null;}
  109. SkelAnim* AnimatedSkeleton::findSkelAnim(C UID &id )C {return skeleton() ? skeleton()->findSkelAnim(id ) : null;}
  110. Int AnimatedSkeleton::findBoneI (CChar8 *name)C {return skeleton() ? skeleton()->findBoneI (name) : -1 ;}
  111. Int AnimatedSkeleton::findSlotI (CChar8 *name)C {return skeleton() ? skeleton()->findSlotI (name) : -1 ;}
  112. Byte AnimatedSkeleton::findSlotB (CChar8 *name)C {return skeleton() ? skeleton()->findSlotB (name) : 255 ;}
  113. AnimSkelBone* AnimatedSkeleton::findBone (CChar8 *name) {return bones.addr( findBoneI (name));}
  114. OrientP * AnimatedSkeleton::findSlot (CChar8 *name) {return slots.addr( findSlotI (name));}
  115. AnimSkelBone* AnimatedSkeleton:: getBone (CChar8 *name) {return bones.addr( getBoneI (name));}
  116. OrientP * AnimatedSkeleton:: getSlot (CChar8 *name) {return slots.addr( getSlotI (name));}
  117. Int AnimatedSkeleton:: getBoneI (CChar8 *name)C {Int i =findBoneI (name); if(i<0 )Exit(S+ "Bone \""+name +"\" not found in skeleton \""+Skeletons.name(skeleton())+"\"."); return i ;}
  118. Int AnimatedSkeleton:: getSlotI (CChar8 *name)C {Int i =findSlotI (name); if(i<0 )Exit(S+ "Slot \""+name +"\" not found in skeleton \""+Skeletons.name(skeleton())+"\"."); return i ;}
  119. SkelAnim* AnimatedSkeleton:: getSkelAnim(C Str &name)C {SkelAnim *skel_anim=findSkelAnim(name); if(!skel_anim && name.is ())Exit(S+"SkelAnim \""+name +"\" not found in skeleton \""+Skeletons.name(skeleton())+"\"."); return skel_anim;}
  120. SkelAnim* AnimatedSkeleton:: getSkelAnim(C UID &id )C {SkelAnim *skel_anim=findSkelAnim(id ); if(!skel_anim && id .valid())Exit(S+"SkelAnim \""+id.asCString()+"\" not found in skeleton \""+Skeletons.name(skeleton())+"\"."); return skel_anim;}
  121. /******************************************************************************/
  122. // SET
  123. /******************************************************************************/
  124. AnimatedSkeleton& AnimatedSkeleton::disable(Int i, Bool disable)
  125. {
  126. if(InRange(i, bones))bones[i]._disabled=disable;
  127. return T;
  128. }
  129. static void DisableChildren(AnimatedSkeleton &anim_skel, Int i, Bool disable)
  130. {
  131. if(C SkelBone *bone=anim_skel.skeleton()->bones.addr(i))
  132. REP(bone->children_num)
  133. {
  134. Int child_i=bone->children_offset+i;
  135. if(InRange(child_i, anim_skel.bones))
  136. {
  137. anim_skel.bones[child_i]._disabled=disable;
  138. DisableChildren(anim_skel, child_i, disable);
  139. }
  140. }
  141. }
  142. AnimatedSkeleton& AnimatedSkeleton::disableChildren(Int i, Bool disable)
  143. {
  144. if(InRange(i, bones))
  145. {
  146. Bool &disabled =bones[i]._disabled_children;
  147. if( disabled!=disable)
  148. {
  149. disabled=disable;
  150. if(skeleton())DisableChildren(T, i, disable); // test for 'skeleton' only once here and not everytime in 'DisableChildren'
  151. }
  152. }
  153. return T;
  154. }
  155. /******************************************************************************/
  156. // ANIMATE
  157. /******************************************************************************/
  158. AnimatedSkeleton& AnimatedSkeleton::clear()
  159. {
  160. root .clear();
  161. REPAO(bones).clear();
  162. return T;
  163. }
  164. AnimatedSkeleton& AnimatedSkeleton::clear(Flt blend)
  165. {
  166. root .clear(blend);
  167. REPAO(bones).clear(blend);
  168. return T;
  169. }
  170. struct AnimParamsEx : AnimParams
  171. {
  172. Bool replace;
  173. Flt blend ,
  174. blend1 ;
  175. AnimParamsEx(C Animation &animation, Flt time, Flt blend, Bool replace) : AnimParams(animation, time)
  176. {
  177. T.replace= replace;
  178. T.blend = blend ; // allow ranges >1 for example for big relative rotations
  179. T.blend1 =Sat(1-blend); // this needs to be clamped to 0..1 range because old keyframes are multiplied by this
  180. }
  181. };
  182. static void Animate(AnimSkelBone &asbon, C AnimKeys &keys, C AnimParamsEx &params)
  183. {
  184. if(!asbon._disabled)
  185. {
  186. // orientation
  187. if(keys.orns.elms())
  188. {
  189. Orient &bone_orn=asbon.orn, orn; keys.orn(orn, params);
  190. if(params.replace)bone_orn*=params.blend1;
  191. bone_orn+=params.blend*orn;
  192. }
  193. // position
  194. if(keys.poss.elms())
  195. {
  196. Vec &bone_pos=asbon.pos, pos; keys.pos(pos, params);
  197. if(params.replace)bone_pos*=params.blend1;
  198. bone_pos+=params.blend*pos;
  199. }
  200. // scale
  201. if(keys.scales.elms())
  202. {
  203. Vec &bone_scale=asbon.scale, scale; keys.scale(scale, params);
  204. if(params.replace)bone_scale*=params.blend1;
  205. bone_scale+=params.blend*scale;
  206. }
  207. #if HAS_ANIM_ROT
  208. // rotation
  209. if(keys.rots.elms())
  210. {
  211. AxisRoll &bone_rot=asbon.rot, rot; keys.rot(rot, params);
  212. if(params.replace)bone_rot.v4()*=params.blend1;
  213. bone_rot.v4()+=params.blend*rot.v4();
  214. }
  215. #endif
  216. #if HAS_ANIM_COLOR
  217. // color
  218. if(keys.colors.elms())
  219. {
  220. Vec4 &bone_color=asbon.color, color; keys.color(color, params);
  221. /*if(params.replace)*/bone_color*=params.blend1; // colors are always replaced
  222. bone_color+=params.blend*color;
  223. }
  224. #endif
  225. }
  226. }
  227. static void AnimRoot(AnimatedSkeleton &anim_skel, C Animation *animation, Flt time, Flt blend, Bool replace)
  228. {
  229. //if(blend>EPS_ANIM_BLEND) // this is already checked in methods calling this function
  230. if(animation)
  231. {
  232. AnimParamsEx params(*animation, time, blend, replace);
  233. Animate(anim_skel.root, animation->keys, params); // animate root
  234. }
  235. }
  236. /******************************************************************************/
  237. AnimatedSkeleton& AnimatedSkeleton::animate(C SkelAnim &skel_anim, Flt time, Flt blend, Bool replace)
  238. {
  239. if(blend>EPS_ANIM_BLEND)
  240. if(C Animation *animation=skel_anim.animation())
  241. {
  242. AnimParamsEx params(*animation, time, blend, replace);
  243. //Animate(root, animation->keys, params); // animate root - this is no longer done here, instead, root animations need to be processed manually
  244. REPA(animation->bones) // animate bones
  245. {
  246. Byte sbon=skel_anim.abonToSbon(i);
  247. if(InRange(sbon, bones))Animate(bones[sbon], animation->bones[i], params);
  248. }
  249. }
  250. return T;
  251. }
  252. AnimatedSkeleton& AnimatedSkeleton::animateRoot(C Animation *anim, Flt time) {if(anim)animateRoot(*anim, time); return T;}
  253. AnimatedSkeleton& AnimatedSkeleton::animateRoot(C Animation &anim, Flt time)
  254. {
  255. AnimParamsEx params(anim, time, 1, false);
  256. Animate(root, anim.keys, params); // animate root
  257. return T;
  258. }
  259. AnimatedSkeleton& AnimatedSkeleton::animateExactTime(C SkelAnim &skel_anim, Flt time) // this will not apply fraction for time, this function is needed when adjusting animations to make sure we process exact keyframes based on time, but still with looping support
  260. {
  261. if(C Animation *animation=skel_anim.animation())
  262. {
  263. AnimParamsEx params(*animation, time, 1, false); params.time=time; // re-apply time to remove possible fraction
  264. Animate(root, animation->keys, params); // animate root
  265. REPA(animation->bones) // animate bones
  266. {
  267. Byte sbon=skel_anim.abonToSbon(i);
  268. if(InRange(sbon, bones))Animate(bones[sbon], animation->bones[i], params);
  269. }
  270. }
  271. return T;
  272. }
  273. AnimatedSkeleton& AnimatedSkeleton::animate(C SkelAnim *skel_anim, Flt time, Flt blend, Bool replace) {if(skel_anim ) T.animate(*skel_anim , time, blend , replace); return T;}
  274. AnimatedSkeleton& AnimatedSkeleton::animate(C Motion &motion , Bool replace) {if(motion .is () ) T.animate(*motion.skel_anim , motion.time, motion.animBlend(), replace); return T;}
  275. AnimatedSkeleton& AnimatedSkeleton::animate(C Str &anim_name, Flt time, Flt blend, Bool replace) {if(anim_name.is () && blend>EPS_ANIM_BLEND)if(skeleton())T.animate(*getSkelAnim(anim_name), time, blend , replace);else AnimRoot(T, Animations(anim_name), time, blend, replace); return T;} // in these methods check 'blend' first to avoid unnecessary animation loads
  276. AnimatedSkeleton& AnimatedSkeleton::animate(C UID &anim_id , Flt time, Flt blend, Bool replace) {if(anim_id .valid() && blend>EPS_ANIM_BLEND)if(skeleton())T.animate(*getSkelAnim(anim_id ), time, blend , replace);else AnimRoot(T, Animations(anim_id ), time, blend, replace); return T;} // in these methods check 'blend' first to avoid unnecessary animation loads
  277. /******************************************************************************/
  278. static void UpdateRootBoneMatrix(AnimatedSkeleton &anim_skel, C Matrix &body_matrix)
  279. {
  280. AnimSkelBone &bone=anim_skel.root;
  281. if(bone._disabled)
  282. {
  283. #if 0 // slower
  284. bone._matrix.setScale(anim_skel._scale).mul(body_matrix);
  285. #else
  286. bone._matrix=body_matrix;
  287. bone._matrix.orn().scale(anim_skel._scale);
  288. #endif
  289. }else
  290. {
  291. Orient &bone_orn=bone.orn; // we can modify it directly, because we're just calling 'fix' on it
  292. // rotation
  293. if(bone.rot.any())
  294. {
  295. Vec axis =bone.rot.axis;
  296. Flt angle=axis.normalize();
  297. if(bone.rot.roll)
  298. {
  299. bone._matrix.orn().setRotateZ(bone.rot.roll)
  300. .rotate (axis, angle );
  301. }else
  302. {
  303. bone._matrix.orn().setRotate(axis, angle);
  304. }
  305. if(bone_orn.fix()) // orientation
  306. {
  307. bone._matrix.orn()*=Matrix3(bone_orn);
  308. }
  309. }else
  310. if(bone_orn.fix()) // orientation
  311. {
  312. bone._matrix.orn()=bone_orn;
  313. }else
  314. {
  315. // only position/scale
  316. bone._matrix=body_matrix;
  317. // apply skeleton scale
  318. if(anim_skel._scale!=1)bone._matrix.orn().scale(anim_skel._scale);
  319. // apply animation position
  320. if(bone.pos.any())bone._matrix.pos+=bone.pos*bone._matrix.orn();
  321. // apply animation scale
  322. if(bone.scale.any())
  323. {
  324. bone._matrix.x*=ScaleFactor(bone.scale.x);
  325. bone._matrix.y*=ScaleFactor(bone.scale.y);
  326. bone._matrix.z*=ScaleFactor(bone.scale.z);
  327. }
  328. return;
  329. }
  330. // set scale
  331. if(bone.scale.any())
  332. {
  333. bone._matrix.x*=ScaleFactor(bone.scale.x);
  334. bone._matrix.y*=ScaleFactor(bone.scale.y);
  335. bone._matrix.z*=ScaleFactor(bone.scale.z);
  336. }
  337. // set position
  338. bone._matrix.pos=bone.pos;
  339. if(anim_skel._scale!=1)bone._matrix.scale(anim_skel._scale);
  340. bone._matrix.mul(body_matrix);
  341. }
  342. }
  343. static void UpdateBoneMatrix(AnimatedSkeleton &anim_skel, Int i)
  344. {
  345. AnimSkelBone &bone =anim_skel. bones[i];
  346. C SkelBone &sbon =anim_skel.skeleton()->bones[i];
  347. C SkelBone *parent =anim_skel.skeleton()->bones.addr(sbon.parent);
  348. Matrix &parent_transform_matrix=anim_skel. boneRoot (sbon.parent)._matrix;
  349. if(bone._force_custom)bone._matrix=bone._force_custom_matrix;else
  350. if(bone._disabled )bone._matrix= parent_transform_matrix;else
  351. {
  352. Matrix3 parent_matrix; if(parent)parent_matrix=*parent;
  353. Orient bone_orn=bone.orn;
  354. /* Animation Formula:
  355. #1 Rotation
  356. Vec axis =bone.rot.axis ; // rotation in parent space
  357. Flt angle=axis.normalize();
  358. if(parent)axis*=parent_matrix; // rotation in world space
  359. bone.matrix.setPos(-sbon.pos )
  360. .rot ( sbon.dir , bone.rot.roll)
  361. .rot ( axis , angle)
  362. .move ( sbon.pos )
  363. .mul ( parent_transform_matrix);
  364. #2 Orientation
  365. Orient src =sbon ; // current orientation in world space
  366. Orient dest=bone_orn; dest.fix(); // target orientation in parent space
  367. if(parent)dest*=parent_matrix; // target orientation in world space
  368. Matrix3 transform=GetTransform(src, dest);
  369. bone.matrix.setPos(-sbon.pos)
  370. .mul (transform)
  371. .move ( sbon.pos)
  372. .mul (parent_transform_matrix);
  373. */
  374. // rotation
  375. if(bone.rot.any())
  376. {
  377. Vec axis =bone.rot.axis; // rotation in parent space
  378. Flt angle=axis.normalize();
  379. if(parent)axis*=parent_matrix; // rotation in world space
  380. if(bone.rot.roll)
  381. {
  382. bone._matrix.orn().setRotate(sbon.dir, bone.rot.roll)
  383. .rotate (axis , angle );
  384. }else
  385. {
  386. bone._matrix.orn().setRotate(axis, angle);
  387. }
  388. if(bone_orn.fix()) // orientation
  389. {
  390. if(parent)bone_orn.mul(parent_matrix, true); // transform target orientation from parent space to world space
  391. Matrix3 transform; GetTransform(transform, sbon, bone_orn); bone._matrix.orn()*=transform;
  392. }
  393. }else
  394. if(bone_orn.fix()) // orientation
  395. {
  396. if(parent)bone_orn.mul(parent_matrix, true); // transform target orientation from parent space to world space
  397. GetTransform(bone._matrix.orn(), sbon, bone_orn);
  398. }else
  399. {
  400. // set scale
  401. if(bone.scale.any())
  402. {
  403. bone._matrix.orn().identity();
  404. bone._matrix.orn().scale(sbon.cross(), ScaleFactor(bone.scale.x));
  405. bone._matrix.orn().scale(sbon.perp , ScaleFactor(bone.scale.y));
  406. bone._matrix.orn().scale(sbon.dir , ScaleFactor(bone.scale.z));
  407. goto scale_set;
  408. }
  409. // only position
  410. bone._matrix=parent_transform_matrix;
  411. if(bone.pos.any())
  412. {
  413. #if 1 // pos relative to parent
  414. bone._matrix.pos+=(parent ? bone.pos*parent_matrix : bone.pos)*parent_transform_matrix.orn();
  415. #else
  416. bone._matrix.pos+=bone.pos*parent_transform_matrix.orn();
  417. #endif
  418. }
  419. goto matrix_set;
  420. }
  421. // set scale
  422. if(bone.scale.any())
  423. {
  424. Orient sbon_transformed=sbon; sbon_transformed.mul(bone._matrix.orn(), true);
  425. bone._matrix.orn().scale(sbon_transformed.cross(), ScaleFactor(bone.scale.x));
  426. bone._matrix.orn().scale(sbon_transformed.perp , ScaleFactor(bone.scale.y));
  427. bone._matrix.orn().scale(sbon_transformed.dir , ScaleFactor(bone.scale.z));
  428. }
  429. scale_set:
  430. // set position
  431. bone._matrix.anchor(sbon.pos);
  432. #if 1 // pos relative to parent
  433. if(bone.pos.any())bone._matrix.pos+=(parent ? bone.pos*parent_matrix : bone.pos);
  434. #else
  435. bone._matrix.pos+=bone.pos;
  436. #endif
  437. bone._matrix*=parent_transform_matrix;
  438. }
  439. matrix_set:
  440. // world space transformation
  441. if(bone._world_space_transform)bone._matrix.transformAtPos(sbon.pos*bone._matrix, bone._world_space_transform_matrix);
  442. }
  443. static void UpdateSlot(AnimatedSkeleton &anim_skel, Int i)
  444. {
  445. C SkelSlot &skel_slot=anim_skel.skeleton()->slots[i];
  446. OrientP & slot=anim_skel. slots[i];
  447. slot=skel_slot;
  448. slot.mul(anim_skel.boneRoot(skel_slot.bone).matrix(), true);
  449. if(skel_slot.bone!=skel_slot.bone1)
  450. {
  451. OrientP secondary=skel_slot;
  452. secondary.mul(anim_skel.boneRoot(skel_slot.bone1).matrix(), true);
  453. slot+=secondary;
  454. slot.fix();
  455. slot.pos*=0.5f;
  456. }
  457. }
  458. /******************************************************************************/
  459. AnimatedSkeleton& AnimatedSkeleton::updateMatrix(C Matrix &body_matrix)
  460. {
  461. UpdateRootBoneMatrix(T, body_matrix);
  462. if(skeleton()) // test 'skeleton' once here, and not everytime in 'UpdateBoneMatrix' and 'UpdateSlot'
  463. {
  464. Int min_bones=minBones(); FREP(min_bones )UpdateBoneMatrix(T, i); // process bones in order to update parents first
  465. REP(minSlots())UpdateSlot (T, i); // order is not important, because slots are attached to bones (not slots)
  466. }
  467. return T;
  468. }
  469. /******************************************************************************/
  470. static void UpdateBoneMatrixRecursiveUp(AnimatedSkeleton &anim_skel, Int i)
  471. {
  472. Byte parent=anim_skel.skeleton()->bones[i].parent;
  473. if( parent<i)UpdateBoneMatrixRecursiveUp(anim_skel, parent); // first update parents, "parent<i" means that parent is !=0xFF (!= <null>), parent fits in minBones range and this prevents infinite loops (looped parent cycle)
  474. UpdateBoneMatrix (anim_skel, i); // now update self
  475. }
  476. AnimatedSkeleton& AnimatedSkeleton::updateMatrixParents(C Matrix &body_matrix, Int bone)
  477. {
  478. UpdateRootBoneMatrix (T, body_matrix); // first update root
  479. if(skeleton() && InRange(bone, minBones()))UpdateBoneMatrixRecursiveUp(T, bone ); // now update parents and self, test 'skeleton' once here, and not everytime in 'UpdateBoneMatrixRecursiveUp'
  480. return T;
  481. }
  482. /******************************************************************************/
  483. static void UpdateBoneMatrixRecursiveDown(AnimatedSkeleton &anim_skel, Int i, Int min_bones)
  484. {
  485. C SkelBone &bone=anim_skel.skeleton()->bones[i];
  486. UpdateBoneMatrix(anim_skel, i); // first update self
  487. for(Int i=Min(bone.children_offset+bone.children_num, min_bones); --i>=bone.children_offset; ) // now update children
  488. UpdateBoneMatrixRecursiveDown(anim_skel, i, min_bones);
  489. }
  490. AnimatedSkeleton& AnimatedSkeleton::updateMatrixChildren(Int bone) // this updates 'bone' too
  491. {
  492. if(skeleton()) // test 'skeleton' once here, and not everytime in 'UpdateBoneMatrixRecursiveDown' and 'UpdateSlot'
  493. {
  494. Int min_bones=minBones(); if(InRange(bone, min_bones))
  495. {
  496. UpdateBoneMatrixRecursiveDown(T, bone, min_bones);
  497. REP(minSlots())UpdateSlot (T, i ); // update slots once bones are ready (because slots are attached to bones)
  498. }
  499. }
  500. return T;
  501. }
  502. /******************************************************************************/
  503. AnimatedSkeleton& AnimatedSkeleton::forceMatrix(Int bone, C Matrix &matrix, Bool auto_update_matrixes)
  504. {
  505. if(InRange(bone, bones))
  506. {
  507. bones[bone].forceMatrix(matrix);
  508. if(auto_update_matrixes)updateMatrixChildren(bone); // this will update 'bone' too
  509. }
  510. return T;
  511. }
  512. AnimatedSkeleton& AnimatedSkeleton::transformInWorldSpace(Int bone, C Matrix3 &matrix, Bool auto_update_matrixes)
  513. {
  514. if(InRange(bone, bones))
  515. {
  516. AnimSkelBone &b=bones[bone];
  517. if(b._world_space_transform)b._world_space_transform_matrix*=matrix;else // if there was already a world transform, then adjust it
  518. {
  519. b._world_space_transform =true;
  520. b._world_space_transform_matrix=matrix;
  521. }
  522. if(auto_update_matrixes)updateMatrixChildren(bone); // this will update 'bone' too
  523. }
  524. return T;
  525. }
  526. AnimatedSkeleton& AnimatedSkeleton::transformInWorldSpace(Int bone, C Matrix &matrix, Bool auto_update_matrixes)
  527. {
  528. if(InRange(bone, bones))
  529. {
  530. AnimSkelBone &b=bones[bone];
  531. if(b._world_space_transform)b._world_space_transform_matrix*=matrix;else // if there was already a world transform, then adjust it
  532. {
  533. b._world_space_transform =true;
  534. b._world_space_transform_matrix=matrix;
  535. }
  536. if(auto_update_matrixes)updateMatrixChildren(bone); // this will update 'bone' too
  537. }
  538. return T;
  539. }
  540. /******************************************************************************/
  541. static Vec FurVel(C Vec &vel, Flt fur_vel_scale, Flt fur_gravity)
  542. {
  543. Vec fur_vel=vel*fur_vel_scale; fur_vel.y+=fur_gravity; fur_vel.clipLength(0.92f);
  544. return fur_vel;
  545. }
  546. AnimatedSkeleton& AnimatedSkeleton::vel(C Vec &vel)
  547. {
  548. Vec fur_vel=FurVel(vel, fur_vel_scale, fur_gravity);
  549. root._vel = vel;
  550. root._fur_vel=fur_vel;
  551. REPA(bones)
  552. {
  553. AnimSkelBone &bone=bones[i];
  554. bone._vel = vel;
  555. bone._fur_vel=fur_vel;
  556. }
  557. return T;
  558. }
  559. void AnimatedSkeleton::updateVelocities(Bool according_to_physics_step, Bool ragdoll_bones_only)
  560. {
  561. if(!_updated_vel) // not yet updated
  562. {
  563. root ._center=pos();
  564. if(skeleton())REP(minBones())bones[i]._center=skeleton()->bones[i].center()*bones[i].matrix();
  565. _updated_vel=true;
  566. }else
  567. {
  568. Flt time_mul;
  569. Vec fur_vel;
  570. if(according_to_physics_step && Physics.created())
  571. {
  572. if(! Physics.updated ())return;
  573. time_mul=1/Physics.updatedTime();
  574. }else
  575. {
  576. time_mul=((Time.d()>EPS) ? 1/Time.d() : 1);
  577. }
  578. // root
  579. root._vel =(pos()-root._center)*time_mul;
  580. root._center = pos(); fur_vel=FurVel(vel(), fur_vel_scale, fur_gravity);
  581. AdjustValTime( root._fur_vel, fur_vel, fur_stiffness);
  582. // bones
  583. if(skeleton())
  584. {
  585. Int min_bones=minBones(); FREP(min_bones) // order is important (parents first)
  586. {
  587. C SkelBone & sbon=skeleton()->bones[i];
  588. AnimSkelBone &asbon= bones[i];
  589. if(!ragdoll_bones_only || (sbon.flag&BONE_RAGDOLL))
  590. {
  591. Vec p= sbon.center() *asbon.matrix();
  592. asbon._vel =(p-asbon.center())*time_mul ; fur_vel=FurVel(asbon.vel(), fur_vel_scale, fur_gravity);
  593. asbon._center= p;
  594. AdjustValTime(asbon._fur_vel, fur_vel, fur_stiffness);
  595. }else // inherit values from the parent
  596. {
  597. AnimSkelBone &parent=boneRoot(sbon.parent);
  598. asbon._center =parent. center();
  599. asbon._vel =parent. vel();
  600. asbon._fur_vel=parent._fur_vel ;
  601. }
  602. }
  603. }
  604. }
  605. }
  606. /******************************************************************************/
  607. void AnimatedSkeleton::move(C Vec &d)
  608. {
  609. root +=d;
  610. REPAO(bones)+=d;
  611. REPAO(slots)+=d;
  612. }
  613. void AnimatedSkeleton::offset(C Vec &d)
  614. {
  615. root ._matrix+=d;
  616. REPAO(bones)._matrix+=d;
  617. REPAO(slots) +=d;
  618. }
  619. /******************************************************************************/
  620. void AnimatedSkeleton::getMatrixes(MemPtrN<Matrix, 256> matrixes)C
  621. {
  622. matrixes.setNum(bones.elms()+1);
  623. matrixes[ 0]= matrix();
  624. REPA(bones)matrixes[i+1]=bones[i].matrix();
  625. }
  626. /******************************************************************************/
  627. // DRAW
  628. /******************************************************************************/
  629. void AnimatedSkeleton::draw(C Color &bone_color, C Color &slot_color)C
  630. {
  631. if(bone_color.a && skeleton())REP (minBones())(skeleton()->bones[i]*bones[i].matrix()).draw(bone_color);
  632. if(slot_color.a )REPAO( slots ).draw(slot_color);
  633. }
  634. /******************************************************************************/
  635. // IO
  636. /******************************************************************************/
  637. Bool AnimatedSkeleton::save(File &f)C
  638. {
  639. f.putMulti(Byte(0), _scale, matrix()); // version
  640. f.putAsset(Skeletons.id(skeleton()));
  641. f.putMulti(fur_stiffness, fur_gravity, fur_vel_scale);
  642. return f.ok();
  643. }
  644. Bool AnimatedSkeleton::load(File &f)
  645. {
  646. switch(f.decUIntV()) // version
  647. {
  648. case 0:
  649. {
  650. f.getMulti(_scale, root._matrix); create(Skeletons(f.getAssetID()), _scale, root._matrix);
  651. f.getMulti(fur_stiffness, fur_gravity, fur_vel_scale);
  652. if(f.ok())return true;
  653. }break;
  654. }
  655. del(); return false;
  656. }
  657. /******************************************************************************/
  658. }
  659. /******************************************************************************/