Skeleton.h 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. /******************************************************************************
  2. Use 'Skeleton' as a base static (non-animated) skeleton, that contain bones and slots in their initial pose.
  3. Use 'AnimatedSkeleton' to animate a base static 'Skeleton', by applying 'Animation's on the 'AnimatedSkeleton'.
  4. /******************************************************************************/
  5. // STATIC SKELETON
  6. /******************************************************************************/
  7. enum BONE_TYPE : Byte
  8. {
  9. BONE_UNKNOWN ,
  10. BONE_SPINE , // pelvis, hips, chest, torso, rib cage
  11. BONE_SHOULDER , // clavicle, collarbone
  12. BONE_UPPER_ARM, // arm
  13. BONE_LOWER_ARM, // forearm
  14. BONE_HAND , // wrist, palm
  15. BONE_FINGER ,
  16. BONE_UPPER_LEG, // thigh
  17. BONE_LOWER_LEG, // calf, crus, shin
  18. BONE_FOOT , // ankle
  19. BONE_TOE ,
  20. BONE_NECK ,
  21. BONE_HEAD ,
  22. BONE_JAW ,
  23. BONE_TONGUE ,
  24. BONE_NOSE , // snout
  25. BONE_EYE ,
  26. BONE_EYELID ,
  27. BONE_EYEBROW ,
  28. BONE_EAR ,
  29. BONE_BREAST ,
  30. BONE_BUTT ,
  31. BONE_TAIL ,
  32. BONE_WING ,
  33. BONE_CAPE , // cloak
  34. BONE_HAIR ,
  35. BONE_NUM , // number of BONE_TYPE elements
  36. // alternative names
  37. BONE_ARM =BONE_UPPER_ARM,
  38. BONE_FOREARM=BONE_LOWER_ARM,
  39. BONE_THIGH =BONE_UPPER_LEG,
  40. BONE_CALF =BONE_LOWER_LEG,
  41. };
  42. enum BONE_FLAG
  43. {
  44. BONE_RAGDOLL=1<<0, // if this option is enabled then the bone will be used to create an actor in the Ragdoll
  45. };
  46. struct BoneID
  47. {
  48. Char8 name[32] ; // name , default=""
  49. BONE_TYPE type ; // BONE_TYPE , default=BONE_UNKNOWN
  50. SByte type_index; // type index , default=0, negative value means that this bone is on the left side, for example if there are 2 bones of BONE_HAND 'type', one with 'type_index'=-1 (left hand), other with 'type_index'=0 (right hand)
  51. Byte type_sub ; // type sub-index, default=0, sub-index is used to distinguish how deep in the parent<->child relation the bone is, for example if a skeleton has 2 hands each with 1 finger, each finger is made out of 3 bones (6 bones total for 2 fingers), then finger bones will have 'type_index' -1 (left) and 0 (right), and 'type_sub' set to 0, 1, 2, giving a total of 6 combinations
  52. BoneID& set(CChar8 *name, BONE_TYPE type=BONE_UNKNOWN, Int type_index=0, Int type_sub=0); // set name, type, type_index and type_sub
  53. BoneID& id() {return T;}
  54. C BoneID& id()C {return T;}
  55. Bool operator==(C BoneID &id)C;
  56. Bool operator!=(C BoneID &id)C {return !(T==id);}
  57. BoneID() {set(null);}
  58. };
  59. typedef SkeletonBone SkelBone;
  60. STRUCT2(SkeletonBone , OrientP , BoneID) // Skeleton Bone
  61. //{
  62. Byte parent , // bone parent index , default=0xFF, 0xFF=none
  63. children_offset, // offset of children in 'Skeleton.bones'
  64. children_num , // number of children
  65. flag ; // BONE_FLAG , default=0
  66. Flt length , // bone length , default=0.3
  67. width ; // bone width , default=0.2
  68. Vec offset ; // bone offset applied to 'shape', default=(0, 0, 0)
  69. Capsule shape ; // shape covering the bone, automatically set by 'Skeleton.setBoneShapes' method, depending on bone position, orientation, length, width and being a ragdoll bone
  70. // get
  71. Vec to ()C {return pos +dir * length ;} // get bone ending position
  72. Flt toY()C {return pos.y+dir.y* length ;} // get bone ending position Y
  73. Vec center ()C {return pos +dir *(length*0.5f);} // get bone center position
  74. Flt centerY()C {return pos.y+dir.y*(length*0.5f);} // get bone center position Y
  75. // set
  76. SkeletonBone& setFromTo(C Vec &from, C Vec &to); // set bone position, direction and length according to 'from' and 'to' position parameters and adjust existing 'perp' to match the new settings
  77. SkeletonBone& operator+=(C Vec &v);
  78. SkeletonBone& operator-=(C Vec &v);
  79. SkeletonBone& operator*=(C Vec &v);
  80. SkeletonBone& operator*=(C Matrix3 &m);
  81. SkeletonBone& operator/=(C Matrix3 &m);
  82. SkeletonBone& operator*=(C Matrix &m);
  83. SkeletonBone& operator/=(C Matrix &m);
  84. SkeletonBone operator* (C Matrix &m)C {return SkeletonBone(T)*=m;}
  85. SkeletonBone& transform(C Matrix3 &matrix) {return T*=matrix;} // transform by matrix
  86. SkeletonBone& transform(C Matrix &matrix) {return T*=matrix;} // transform by matrix
  87. SkeletonBone& mirrorX(); // mirror in X axis
  88. #if EE_PRIVATE
  89. SkeletonBone& mirrorY(); // mirror in Y axis
  90. SkeletonBone& mirrorZ(); // mirror in Z axis
  91. SkeletonBone& rightToLeft(); // convert right to left hand coordinate system
  92. #endif
  93. // draw
  94. void draw(C Color &color)C; // this can be optionally called outside of Render function
  95. // io
  96. void save(TextNode &node, C Skeleton *owner=null)C; // save as text
  97. SkeletonBone();
  98. };
  99. typedef SkeletonSlot SkelSlot;
  100. STRUCT( SkeletonSlot , OrientP) // Skeleton Slot
  101. //{
  102. Char8 name[32]; // name
  103. Byte bone , // bone index to which slot belongs, 0xFF=none
  104. bone1 ; // secondary bone index to which slot belongs, 0xFF=none, for best performance this should be set to the same value as 'bone' (to have only one parent), if this is different than 'bone' then slot will be set as average based on 2 bone parents
  105. void setParent(Byte bone) {T.bone=T.bone1=bone;}
  106. #if EE_PRIVATE
  107. SkeletonSlot& operator=(C OrientP &ornp) {SCAST(OrientP, T)=ornp; return T;}
  108. #endif
  109. // io
  110. void save(TextNode &node, C Skeleton *owner=null)C; // save as text
  111. SkeletonSlot();
  112. };
  113. /******************************************************************************/
  114. struct Skeleton // Animation Skeleton - base skeleton used by 'AnimatedSkeleton'
  115. {
  116. Mems<SkelBone> bones; // skeleton bones
  117. Mems<SkelSlot> slots; // skeleton slots
  118. // get
  119. Bool is()C {return bones.elms() || slots.elms();} // if has any data
  120. #if EE_PRIVATE
  121. Int boneParents(Int bone)C; // get total number of parents that a bone has, 0 if none
  122. Int boneLevel (Int bone)C; // get bone level
  123. Int bonesSharedParent(MemPtr<Byte, 256> bones)C; // get nearest parent which all bones share, or 0xFF if none
  124. Int hierarchyDistance(Int bone_a, Int bone_b )C; // get hierarchy distance between bones
  125. SkelAnim* findSkelAnim(C Str &name)C {return _skel_anims.get(name);} // find skeleton animation, null on fail
  126. SkelAnim* findSkelAnim(C UID &id )C {return _skel_anims.get(id );} // find skeleton animation, null on fail
  127. SkelAnim* getSkelAnim(C Str &name)C {return _skel_anims (name);} // get skeleton animation, Exit on fail
  128. SkelAnim* getSkelAnim(C UID &id )C {return _skel_anims (id );} // get skeleton animation, Exit on fail
  129. #endif
  130. Int findBoneI( BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone index, -1 on fail
  131. Byte findBoneB( BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone byte index, 255 on fail
  132. SkelBone* findBone ( BONE_TYPE type, Int type_index=0, Int type_sub=0) ; // find bone , null on fail
  133. C SkelBone* findBone ( BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone , null on fail
  134. Int findBoneI(CChar8 *name, BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone index, -1 on fail, bones are first compared against the specified 'name', if there's no exact match and the 'type' is specified (not BONE_UNKNOWN) then type parameters are used for searching
  135. SkelBone* findBone (CChar8 *name, BONE_TYPE type, Int type_index=0, Int type_sub=0) ; // find bone , null on fail, bones are first compared against the specified 'name', if there's no exact match and the 'type' is specified (not BONE_UNKNOWN) then type parameters are used for searching
  136. C SkelBone* findBone (CChar8 *name, BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone , null on fail, bones are first compared against the specified 'name', if there's no exact match and the 'type' is specified (not BONE_UNKNOWN) then type parameters are used for searching
  137. Int getBoneI( BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone index, Exit on fail
  138. SkelBone& getBone ( BONE_TYPE type, Int type_index=0, Int type_sub=0) ; // find bone , Exit on fail
  139. C SkelBone& getBone ( BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone , Exit on fail
  140. Int findBoneI(CChar8 *name)C; // find bone index, -1 on fail
  141. SkelBone* findBone (CChar8 *name) ; // find bone , null on fail
  142. C SkelBone* findBone (CChar8 *name)C; // find bone , null on fail
  143. Int findSlotI(CChar8 *name)C; // find slot index, -1 on fail
  144. Byte findSlotB(CChar8 *name)C; // find slot byte index, 255 on fail
  145. SkelSlot* findSlot (CChar8 *name) ; // find slot , null on fail
  146. C SkelSlot* findSlot (CChar8 *name)C; // find slot , null on fail
  147. Int getBoneI(CChar8 *name)C; // get bone index, Exit on fail
  148. Int getSlotI(CChar8 *name)C; // get slot index, Exit on fail
  149. SkelBone& getBone (CChar8 *name) ; // get bone , Exit on fail
  150. C SkelBone& getBone (CChar8 *name)C; // get bone , Exit on fail
  151. SkelSlot& getSlot (CChar8 *name) ; // get slot , Exit on fail
  152. C SkelSlot& getSlot (CChar8 *name)C; // get slot , Exit on fail
  153. Bool contains (Int parent, Int child )C; // if 'parent' bone contains 'child' bone
  154. Int boneParent (Int bone )C; // get bone parent, if bone has no parent, or its parent index is invalid then -1 is returned
  155. Int boneRoot (Int bone )C; // get bone root , this iterates bones starting from 'bone' through its parents and returns the last encountered bone that has no parent, if 'bone' has no parent then 'bone' is returned, if 'bone' is not a valid bone index, then -1 is returned
  156. Int findParent (Int bone, BONE_TYPE type)C; // get index of the first parent of 'bone' which has 'type' BONE_TYPE , -1 is returned if none were found
  157. Int findRagdollParent(Int bone )C; // get index of the first parent of 'bone' which has 'BONE_RAGDOLL' enabled, -1 is returned if none were found
  158. UInt memUsage()C; // get memory usage
  159. void getSkin(C Vec &pos, VecB4 &blend, VecB4 &matrix)C; // get bone 'blend matrix' skinning according to 'pos' position
  160. // transform
  161. Skeleton& operator+=(C Vec &move ) {return T.move (move );} // move
  162. Skeleton& operator*=(C Matrix3 &matrix) {return T.transform(matrix);} // transform by matrix
  163. Skeleton& operator*=(C Matrix &matrix) {return T.transform(matrix);} // transform by matrix
  164. Skeleton& move ( C Vec &move); // move
  165. Skeleton& scale (C Vec &scale ); // scale
  166. Skeleton& scaleMove(C Vec &scale, C Vec &move); // scale and move
  167. Skeleton& transform(C Matrix3 &matrix ); // transform by matrix
  168. Skeleton& transform(C Matrix &matrix ); // transform by matrix
  169. Skeleton& animate (C AnimatedSkeleton &anim_skel ); // transform bones according to current 'anim_skel' skeleton pose
  170. #if EE_PRIVATE
  171. Skeleton& mirrorX (); // mirror in X axis
  172. Skeleton& mirrorY (); // mirror in Y axis
  173. Skeleton& mirrorZ (); // mirror in Z axis
  174. Skeleton& rightToLeft(); // convert from right hand to left hand coordinate system
  175. #endif
  176. // operations
  177. Skeleton& setBoneTypes (); // automatically set 'SkelBone.type, type_index, type_sub' for all bones in this Skeleton, this method should be called after making changes to skeleton bones
  178. Skeleton& setBoneShapes(); // automatically set 'SkelBone.shape' for all bones in this Skeleton, this method should be called after making changes to skeleton bones
  179. Bool setBoneParent(Int child, Int parent, MemPtr<Byte, 256> old_to_new=null); // set 'parent' as the parent of 'child' bone, if 'old_to_new' is passed it will be set as bone remap "old_to_new[old_index]=new_index", false is returned if no change was made (in that case 'old_to_new' will be empty)
  180. Bool removeBone (Int i , MemPtr<Byte, 256> old_to_new=null); // remove i-th bone , if 'old_to_new' is passed it will be set as bone remap "old_to_new[old_index]=new_index", false is returned if no change was made (in that case 'old_to_new' will be empty)
  181. Skeleton& add (C Skeleton &src , MemPtr<Byte, 256> old_to_new=null); // add bones and slots from 'src' to self , if 'old_to_new' is passed it will be set as bone remap "old_to_new[old_index]=new_index"
  182. Skeleton& addSlots (C Skeleton &src ); // add slots from 'src' to self
  183. Skeleton& sortBones ( MemPtr<Byte, 256> old_to_new=null); // sort bones in parent<->child order and calculate children count and offsets, this is required when changing bone parents, if 'old_to_new' is passed it will be set as bone remap "old_to_new[old_index]=new_index"
  184. #if EE_PRIVATE
  185. Skeleton& setBoneLengths( ); // automatically set bone lengths
  186. void boneRemap ( C MemPtr<Byte, 256> &old_to_new );
  187. #endif
  188. // draw
  189. void draw(C Color &bone_color, C Color &slot_color=TRANSPARENT, Flt slot_size=0.2f)C; // draw bones and slots, this can be optionally called outside of Render function
  190. // io
  191. void operator=(C Str &name) ; // load, Exit on fail
  192. void operator=(C UID &id ) ; // load, Exit on fail
  193. Bool save (C Str &name)C; // save, false on fail
  194. Bool load (C Str &name) ; // load, false on fail
  195. Bool save(File &f)C; // save, false on fail
  196. Bool load(File &f) ; // load, false on fail
  197. void save(MemPtr<TextNode> nodes)C; // save as text
  198. Skeleton& del(); // delete manually
  199. Skeleton();
  200. Skeleton(C Skeleton &src); // create from 'src'
  201. Skeleton& operator=(C Skeleton &src); // create from 'src'
  202. private:
  203. mutable Cache<SkelAnim> _skel_anims;
  204. };
  205. /******************************************************************************/
  206. // ANIMATED SKELETON
  207. /******************************************************************************/
  208. typedef AnimatedSkeletonBone AnimSkelBone;
  209. struct AnimatedSkeletonBone // Bone of an Animated Skeleton
  210. {
  211. // these parameters may be manually changed during animation process, they are in parent space:
  212. Orient orn ; // target orientation
  213. AxisRoll rot ; // relative rotation
  214. Vec pos , // offset position
  215. scale; // scale factor
  216. // these parameters may be accessed after animation and matrix updates (using 'updateMatrix' method), they are in world space:
  217. C Vec & center()C {return _center;} // bone center position, this parameter may be inaccurate for bones which don't have BONE_RAGDOLL flag enabled
  218. C Vec & vel ()C {return _vel ;} // bone velocity , this parameter may be inaccurate for bones which don't have BONE_RAGDOLL flag enabled
  219. C Matrix& matrix()C {return _matrix;} // this is the transformation matrix, which transforms source bone 'SkelBone' and source 'Mesh' into their final positions (source_data * matrix = final_world_space_position)
  220. // operations
  221. void clear( ); // clear 'orn rot pos scale'
  222. void clear(Flt blend); // partially clear 'orn rot pos scale', this method is similar to 'clear()' however it does not perform full reset of the bone. Instead, smooth reset is applied depending on 'blend' value (0=no reset, 1=full reset)
  223. void forceMatrix(C Matrix &matrix); // force usage of custom transformation 'matrix' for this bone, if used then the bone will ignore its transformations from the animations
  224. #if EE_PRIVATE
  225. void operator+=(C Vec &d) {_center+=d; _matrix+=d;}
  226. void zero() {Zero(T);}
  227. #endif
  228. #if !EE_PRIVATE
  229. private:
  230. #endif
  231. Bool _disabled, _disabled_children, _force_custom, _world_space_transform;
  232. Vec _center, _vel, _fur_vel;
  233. Matrix _matrix, _force_custom_matrix, _world_space_transform_matrix;
  234. };
  235. /******************************************************************************/
  236. typedef AnimatedSkeleton AnimSkel;
  237. struct AnimatedSkeleton // Animated Skeleton - used for animating meshes
  238. {
  239. Flt fur_stiffness, // determines the speed of fur velocities changes, 0..1 , default= 0.0001
  240. fur_gravity , // gravity which affects fur velocities , -Inf..Inf, default=-1
  241. fur_vel_scale; // how much does skeleton movement affect fur velocities , -Inf..Inf, default=-0.75
  242. AnimSkelBone root ; // root transformed skeleton bone
  243. FixedMems<AnimSkelBone> bones ; // transformed skeleton bone array
  244. FixedMems<OrientP > slots ; // transformed skeleton slot array
  245. // manage
  246. AnimatedSkeleton& del ( ); // delete manually
  247. AnimatedSkeleton& create(const_mem_addr C Skeleton *skeleton, Flt scale=1, C Matrix &initial_matrix=MatrixIdentity); // create from 'skeleton' object, 'scale'=skeleton scale, 'initial_matrix'=matrix set for the root bone (its scale is ignored)
  248. AnimatedSkeleton& create( AnimatedSkeleton &src ); // create from 'src'
  249. // get
  250. C Skeleton* skeleton( )C {return _skeleton ;} // get source skeleton
  251. Flt scale ( )C {return _scale ;} // get animated skeleton scale
  252. AnimSkelBone& boneRoot(Int i) {return InRange(i, bones) ? bones[i] : root;} // get i-th transformed bone or root if index is out of range
  253. C AnimSkelBone& boneRoot(Int i)C {return ConstCast(T).boneRoot(i) ;} // get i-th transformed bone or root if index is out of range
  254. C Vec & pos ( )C {return root.matrix().pos ;} // get root position
  255. C Matrix& matrix ( )C {return root.matrix() ;} // get root matrix
  256. C Vec & vel ( )C {return root.vel () ;} // get root velocity
  257. SkelAnim* findSkelAnim(C Str &name )C; // find skeleton animation, null on fail
  258. SkelAnim* findSkelAnim(C UID &id )C; // find skeleton animation, null on fail
  259. AnimSkelBone* findBone (BONE_TYPE type, Int type_index=0, Int type_sub=0) ; // find bone , null on fail
  260. Int findBoneI (BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone index , -1 on fail
  261. Byte findBoneB (BONE_TYPE type, Int type_index=0, Int type_sub=0)C; // find bone byte index , 255 on fail
  262. Int findBoneI (CChar8 *name )C; // find bone index , -1 on fail
  263. Int findSlotI (CChar8 *name )C; // find slot index , -1 on fail
  264. Byte findSlotB (CChar8 *name )C; // find slot byte index , 255 on fail
  265. AnimSkelBone* findBone (CChar8 *name ) ; // find bone , null on fail
  266. OrientP * findSlot (CChar8 *name ) ; // find transformed slot , null on fail, slot will have correct orientation after 'updateMatrix' has been called
  267. SkelAnim* getSkelAnim(C Str &name )C; // get skeleton animation, Exit on fail
  268. SkelAnim* getSkelAnim(C UID &id )C; // get skeleton animation, Exit on fail
  269. Int getBoneI (CChar8 *name )C; // get bone index , Exit on fail
  270. Int getSlotI (CChar8 *name )C; // get slot index , Exit on fail
  271. AnimSkelBone* getBone (CChar8 *name ) ; // get bone , Exit on fail
  272. OrientP * getSlot (CChar8 *name ) ; // get transformed slot , Exit on fail, slot will have correct orientation after 'updateMatrix' has been called
  273. void getMatrixes(MemPtrN<Matrix, 256> matrixes)C; // get all bone transformation matrixes, including the root bone as the first one
  274. // set
  275. AnimatedSkeleton& disable (Int i, Bool disable); // disables/enables animation of i-th bone
  276. AnimatedSkeleton& disableChildren(Int i, Bool disable); // disables/enables animation of i-th bone's children
  277. AnimatedSkeleton& vel(C Vec &vel); // force custom velocity to root and all bones
  278. // animate
  279. // prepare
  280. AnimatedSkeleton& clear( ); // clear 'AnimSkelBone' bones 'orn rot pos scale', call this method once before applying all animations to prepare for animating
  281. AnimatedSkeleton& clear(Flt blend); // partially clear 'AnimSkelBone' bones 'orn rot pos scale', this method is similar to 'clear()' however it does not perform full reset of the bones. Instead, smooth reset is applied depending on 'blend' value (0=no reset, 1=full reset)
  282. // modify using animations
  283. AnimatedSkeleton& animate(C SkelAnim &skel_anim, Flt time, Flt blend=1, Bool replace=false); // modify 'AnimSkelBone' bones 'orn rot pos scale' according to animation object , 'time'=time position of the animation, 'blend'=blending factor of animation (0..1), if 'replace'=true then previous animations applied to the skeleton will be multiplied by "1-blend" value making them less important
  284. AnimatedSkeleton& animate(C SkelAnim *skel_anim, Flt time, Flt blend=1, Bool replace=false); // modify 'AnimSkelBone' bones 'orn rot pos scale' according to animation object , 'time'=time position of the animation, 'blend'=blending factor of animation (0..1), if 'replace'=true then previous animations applied to the skeleton will be multiplied by "1-blend" value making them less important
  285. AnimatedSkeleton& animate(C Str &anim_name, Flt time, Flt blend=1, Bool replace=false); // modify 'AnimSkelBone' bones 'orn rot pos scale' according to animation file name , 'time'=time position of the animation, 'blend'=blending factor of animation (0..1), if 'replace'=true then previous animations applied to the skeleton will be multiplied by "1-blend" value making them less important, prefer using other 'animate' methods as this one is slower
  286. AnimatedSkeleton& animate(C UID &anim_id , Flt time, Flt blend=1, Bool replace=false); // modify 'AnimSkelBone' bones 'orn rot pos scale' according to animation file name ID, 'time'=time position of the animation, 'blend'=blending factor of animation (0..1), if 'replace'=true then previous animations applied to the skeleton will be multiplied by "1-blend" value making them less important, prefer using other 'animate' methods as this one is slower
  287. AnimatedSkeleton& animate(C Motion &motion , Bool replace ); // modify 'AnimSkelBone' bones 'orn rot pos scale' according to animation motion , if 'replace'=true then previous animations applied to the skeleton will be multiplied by "1-blend" value making them less important
  288. AnimatedSkeleton& animateRoot(C Animation &anim, Flt time); // modify 'AnimSkelBone' root 'orn rot pos scale' according to animation object, 'time'=time position of the animation
  289. AnimatedSkeleton& animateRoot(C Animation *anim, Flt time); // modify 'AnimSkelBone' root 'orn rot pos scale' according to animation object, 'time'=time position of the animation
  290. // build final transformation matrixes (this takes into account applied animations and custom modifications)
  291. AnimatedSkeleton& updateMatrix (C Matrix &root_matrix=MatrixIdentity ); // update 'AnimSkelBone' bones 'matrix' according to bones 'orn rot pos scale' and 'root_matrix', this should be called after animating and applying manual modifications, 'root_matrix' must be normalized, this method also sets skeleton slots according to bone matrixes
  292. AnimatedSkeleton& updateMatrixParents (C Matrix &root_matrix , Int bone); // update 'AnimSkelBone' bones 'matrix' according to bones 'orn rot pos scale' and 'root_matrix', update occurs only on 'bone' bone and its parents , 'root_matrix' must be normalized
  293. AnimatedSkeleton& updateMatrixChildren( Int bone); // update 'AnimSkelBone' bones 'matrix' according to bones 'orn rot pos scale' , update occurs only on 'bone' bone and its children
  294. // apply custom modifications (this can be called before or after 'updateMatrix' methods)
  295. AnimatedSkeleton& forceMatrix(Int bone, C Matrix &matrix, Bool auto_update_matrixes=true); // force usage of custom transformation 'matrix' for 'bone', if used then the bone will ignore its transformations from the animations, if 'auto_update_matrixes' is set to true then 'updateMatrixChildren(bone)' will be called automatically
  296. AnimatedSkeleton& transformInWorldSpace(Int bone, C Matrix3 &matrix, Bool auto_update_matrixes=true); // transform bone by world space 'matrix', if 'auto_update_matrixes' is set to true then 'updateMatrixChildren(bone)' will be called automatically
  297. AnimatedSkeleton& transformInWorldSpace(Int bone, C Matrix &matrix, Bool auto_update_matrixes=true); // transform bone by world space 'matrix', if 'auto_update_matrixes' is set to true then 'updateMatrixChildren(bone)' will be called automatically
  298. // update
  299. void updateVelocities(Bool according_to_physics_step=true, Bool ragdoll_bones_only=true); // update velocities 'vel, bone.vel' and bone center positions 'bone.center' according to root and bone matrixes 'matrix bone[].matrix'. This needs to be called once per frame after all animations, modifications and matrix updates ('updateMatrix'). 'according_to_physics_step' if update the velocities according to the physics update time step in this frame, if it's set to false, then the velocities will always be calculated. 'ragdoll_bones_only'=if calculate precise velocities only for bones which have 'BONE_RAGDOLL' flag enabled
  300. // transform
  301. void move (C Vec &delta); // move the whole skeleton , this method is to be used for distant position modifications, it will not affect bone velocities, you can call this method optionally after matrix updates ('updateMatrix')
  302. void offset(C Vec &delta); // apply offset to root matrix, bone matrixes, and transformed slots by vector, this method is to be used for smooth local position modifications, it will affect bone velocities, you can call this method optionally after matrix updates ('updateMatrix')
  303. // draw
  304. void setMatrix()C; // set active rendering matrixes and velocities ('matrix, bone.matrix, vel, bone.vel') to the GPU shader data, call this right before drawing skinned meshes (when using mesh draw methods which don't accept matrix or skeleton parameter, if they do accept such parameters, then those methods will automatically set proper matrixes and you don't need to call 'setMatrix' manually)
  305. void draw (C Color &bone_color, C Color &slot_color=TRANSPARENT)C; // draw animated bones and slots, this can be optionally called outside of Render function
  306. // io
  307. Bool save(File &f)C; // save, does not include current animation pose, false on fail
  308. Bool load(File &f) ; // load, does not include current animation pose, false on fail
  309. #if EE_PRIVATE
  310. void zero();
  311. void setFurVel()C; // set fur velocities
  312. Int minBones ()C {return Min(bones.elms(), skeleton()->bones.elms());} // !! this does not check for "skeleton!=null" !!
  313. Int minSlots ()C {return Min(slots.elms(), skeleton()->slots.elms());} // !! this does not check for "skeleton!=null" !!
  314. 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
  315. #endif
  316. AnimatedSkeleton();
  317. #if !EE_PRIVATE
  318. private:
  319. #endif
  320. Bool _updated_vel;
  321. Flt _scale;
  322. C Skeleton *_skeleton;
  323. struct Instance
  324. {
  325. Int solid, blend, shadow;
  326. Instance() {solid=blend=shadow=-1;}
  327. }mutable _instance;
  328. };
  329. /******************************************************************************/
  330. struct BoneMap
  331. {
  332. #if EE_PRIVATE
  333. void create(C Skeleton &skeleton); // create from 'skeleton'
  334. Int alloc (Int bones, Int name_size); // allocate memory and return its total size
  335. Bool is()C {return _bones>0;} // if has any data
  336. Int nameSize ( )C; // get size needed for bone names
  337. Char8* nameStart( )C; // get start of the bone name memory
  338. CChar8* name (Int i)C; // get i-th bone name
  339. Int find(CChar8 *name )C; // find bone, -1 on fail
  340. Int find(CChar8 *name, BONE_TYPE type, Int type_index, Int type_sub)C; // find bone, -1 on fail
  341. Bool same(C Skeleton &skeleton)C; // if contains the same data as the 'skeleton'
  342. void remap( C MemPtr<Byte, 256> &old_to_new ) ; // remap
  343. void setRemap(C Skeleton &skeleton, MemPtr<Byte, 256> old_to_new, Bool by_name=false)C; // set remap that maps from current bone mapping to 'skeleton' bone mapping, 'by_name'=if remap by name only and ignore type/indexes
  344. Bool save(File &f)C;
  345. Bool load(File &f) ;
  346. Bool saveOld1(File &f)C;
  347. Bool loadOld1(File &f) ;
  348. Bool saveOld (File &f)C;
  349. Bool loadOld (File &f) ;
  350. #endif
  351. void del();
  352. ~BoneMap() {del();}
  353. BoneMap() {_bone=null; _bones=0;}
  354. BoneMap(C BoneMap &src);
  355. void operator=(C BoneMap &src);
  356. private:
  357. #if EE_PRIVATE
  358. struct Bone
  359. {
  360. BONE_TYPE type ;
  361. SByte type_index ;
  362. Byte type_sub ;
  363. Byte parent ;
  364. U16 name_offset;
  365. };
  366. Bone *_bone; // right after '_bone' array, array of bone names is allocated (using Char8)
  367. #else
  368. Ptr _bone;
  369. #endif
  370. Int _bones;
  371. };
  372. /******************************************************************************/
  373. extern Cache<Skeleton> Skeletons; // Skeleton Cache
  374. /******************************************************************************/
  375. CChar8* BoneName(BONE_TYPE type); // get name of the specified bone type
  376. /******************************************************************************/
  377. #if EE_PRIVATE
  378. #define VIRTUAL_ROOT_BONE 1 // if set to 1, then: mesh.vtx.matrix=0 is a special virtual root bone, and bone indexes start from 1, matrix=bone+1 -> matrix=1 is bone=0, matrix=2 is bone=1, ..; if VIRTUAL_ROOT_BONE set to 0, then there's no virtual root bone, and vtx matrix is the same as bone index, currently only VIRTUAL_ROOT_BONE==1 is supported so don't change !!
  379. #endif
  380. /******************************************************************************/