Import BVH.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace BVH{ // so local structures are unique
  5. /******************************************************************************/
  6. enum CHANNEL : Byte
  7. {
  8. POS_X,
  9. POS_Y,
  10. POS_Z,
  11. ROT_X,
  12. ROT_Y,
  13. ROT_Z,
  14. };
  15. /******************************************************************************/
  16. struct JOINT
  17. {
  18. Bool has_end;
  19. Byte sbon_index;
  20. Int abon_index;
  21. Str name;
  22. Vec offset, end_offset, pos;
  23. Memc<CHANNEL> channels;
  24. Memx<JOINT > joints; // use 'Memx' because joints are referencing each other using 'parent'
  25. JOINT *parent;
  26. JOINT() {has_end=false; sbon_index=0xFF; abon_index=-1; offset.zero(); parent=null;}
  27. void import(FileTextEx &f, JOINT *parent)
  28. {
  29. T.parent=parent;
  30. f.getLine(name);
  31. if(f.getIn())for(; f.level(); )
  32. {
  33. if(f.cur("OFFSET"))
  34. {
  35. f.get(offset);
  36. pos=(parent ? parent->pos+offset : offset);
  37. }else
  38. if(f.cur("CHANNELS"))
  39. {
  40. REP(f.getInt())
  41. {
  42. CChar *channel=f.getWord();
  43. if(Equal(channel, "Xposition"))channels.New()=POS_X;else
  44. if(Equal(channel, "Yposition"))channels.New()=POS_Y;else
  45. if(Equal(channel, "Zposition"))channels.New()=POS_Z;else
  46. if(Equal(channel, "Xrotation"))channels.New()=ROT_X;else
  47. if(Equal(channel, "Yrotation"))channels.New()=ROT_Y;else
  48. if(Equal(channel, "Zrotation"))channels.New()=ROT_Z;
  49. }
  50. }else
  51. if(f.cur("JOINT"))joints.New().import(f, this);else
  52. if(f.cur("End" ) && f.getIn())
  53. {
  54. for(; f.level(); )
  55. {
  56. if(f.cur("OFFSET"))
  57. {
  58. f.get(end_offset);
  59. has_end=true;
  60. }
  61. }
  62. }
  63. }
  64. }
  65. void toBone(Skeleton &skeleton, Byte parent_index)
  66. {
  67. sbon_index=skeleton.bones.elms();
  68. SkelBone &sbon=skeleton.bones.New ();
  69. Set(sbon.name , name );
  70. sbon.parent=parent_index;
  71. sbon.pos =pos;
  72. Bool adjust=false;
  73. Vec end;
  74. if(joints.elms())
  75. {
  76. end.zero(); REPA(joints)end+=joints[i].pos; end/=joints.elms();
  77. adjust=true;
  78. }else
  79. if(has_end)
  80. {
  81. end=pos+end_offset;
  82. adjust=true;
  83. }
  84. if(adjust)
  85. {
  86. Matrix3 m; m.setRotation(sbon.dir, !(end-pos));
  87. sbon.dir *=m;
  88. sbon.perp *=m;
  89. sbon.length=Max(0.02f, Dist(end, sbon.pos));
  90. }
  91. FREPAO(joints).toBone(skeleton, sbon_index);
  92. }
  93. void toAnim(Animation &animation, Int frames)
  94. {
  95. if(channels.elms())
  96. {
  97. Bool has_pos=false,
  98. has_rot=false;
  99. REPA(channels)switch(channels[i])
  100. {
  101. case POS_X:
  102. case POS_Y:
  103. case POS_Z: has_pos=true; break;
  104. case ROT_X:
  105. case ROT_Y:
  106. case ROT_Z: has_rot=true; break;
  107. }
  108. abon_index=animation.bones.elms();
  109. AnimBone &abon=animation.bones.New(); abon.set((Str8)name);
  110. // clear anim keys data
  111. abon.poss.setNumZero(has_pos ? frames : 0);
  112. abon.orns.setNumZero(has_rot ? frames : 0);
  113. }
  114. FREPAO(joints).toAnim(animation, frames);
  115. }
  116. void loadFrame(Skeleton &skeleton, Animation &animation, FileTextEx &f, Int frame)
  117. {
  118. if(sbon_index!=0xFF && abon_index>=0)
  119. {
  120. SkelBone &sbon=skeleton .bones[sbon_index];
  121. AnimBone &abon=animation.bones[abon_index];
  122. Matrix3 m(1);
  123. FREPA(channels)switch(channels[i])
  124. {
  125. case POS_X: f.get(abon.poss[frame].pos.x); break;
  126. case POS_Y: f.get(abon.poss[frame].pos.y); break;
  127. case POS_Z: f.get(abon.poss[frame].pos.z); break;
  128. case ROT_X: m=Matrix().setRotateX(DegToRad(f.getFlt()))*m; break;
  129. case ROT_Y: m=Matrix().setRotateY(DegToRad(f.getFlt()))*m; break;
  130. case ROT_Z: m=Matrix().setRotateZ(DegToRad(f.getFlt()))*m; break;
  131. }
  132. if(abon.poss.elms())abon.poss[frame].time=frame;
  133. if(abon.orns.elms())abon.orns[frame].time=frame;
  134. if(abon.orns.elms())
  135. {
  136. C SkelBone *parent=skeleton.bones.addr(sbon.parent);
  137. Matrix3 parent_matrix_inv; if(parent)parent->inverse(parent_matrix_inv);
  138. Orient &orn=abon.orns[frame].orn;
  139. orn =sbon;
  140. orn*=m;
  141. if(parent)orn*=parent_matrix_inv;
  142. }
  143. }
  144. FREPAO(joints).loadFrame(skeleton, animation, f, frame);
  145. }
  146. };
  147. /******************************************************************************/
  148. static void CreateAnimation(Skeleton &skeleton, XAnimation &animation, JOINT &root, FileTextEx &f)
  149. {
  150. Int frames=0;
  151. Dbl frame_time=1;
  152. f.getWord(); f.get(frames );
  153. f.getWord(); f.getWord(); f.get(frame_time);
  154. if(frames>0)
  155. {
  156. root.toAnim (animation.anim, frames);
  157. FREP(frames)root.loadFrame(skeleton, animation.anim, f, i);
  158. // finalize
  159. if(frame_time)animation.fps=1/frame_time;
  160. animation.anim.length(frames , false); // set current length
  161. animation.anim.length(frames*frame_time, true ); // rescale keyframes
  162. animation.anim.setTangents().setRootMatrix();
  163. }
  164. }
  165. /******************************************************************************/
  166. } // namespace BVH
  167. /******************************************************************************/
  168. Bool ImportBVH(C Str &name, Skeleton *skeleton, XAnimation *animation)
  169. {
  170. if(skeleton )skeleton ->del();
  171. if(animation)animation->del();
  172. using namespace BVH;
  173. FileTextEx f; if(f.read(name))
  174. {
  175. Skeleton temp, *skel=(skeleton ? skeleton : animation ? &temp : null); // if skel not specified, but we want animation, then we have to process it
  176. JOINT root;
  177. for(; f.level(); )
  178. {
  179. if(f.cur("ROOT"))
  180. {
  181. if(skel)
  182. {
  183. root.import(f, null);
  184. root.toBone(*skel, 0xFF);
  185. }
  186. }else
  187. if(f.cur("MOTION"))
  188. {
  189. if(animation)CreateAnimation(*skel, *animation, root, f);
  190. break;
  191. }
  192. }
  193. if(skel ) skel -> mirrorX().sortBones().setBoneTypes();
  194. if(animation) animation->anim.mirrorX().setBoneTypeIndexesFromSkeleton(*skel);
  195. if(skeleton ){skel ->setBoneShapes(); if(skeleton!=skel)Swap(*skeleton, *skel);}
  196. return true;
  197. }
  198. return false;
  199. }
  200. /******************************************************************************/
  201. }
  202. /******************************************************************************/