OgreSkeletonLib_skelfns.ms 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. -----------------------------------------------------------------------------
  2. -- gets keyframes from the controllers animation
  3. -----------------------------------------------------------------------------
  4. function getTimeList obj firstframe lastframe =
  5. (
  6. local list,rotContr,posContr, ;
  7. list = #(firstframe) ;
  8. list2 = #() ; -- this is the list which will be returned.
  9. -- Biped_Objects and Bones don't have the same properties
  10. -- Biped_Objets
  11. if (isKindOf obj Biped_Object) then (
  12. for e in obj.controller.keys do (
  13. t =e.time ;
  14. if (t>firstFrame and t<=lastFrame) then
  15. append list t ;
  16. )
  17. )
  18. -- Bones
  19. else (
  20. rotContr = obj.rotation.controller ;
  21. posContr = obj.pos.controller ;
  22. for e in rotContr.keys do (
  23. t = e.time ;
  24. if (t>firstFrame and t<=lastFrame) then
  25. append list t ;
  26. )
  27. for e in posContr.keys do (
  28. t = e.time ;
  29. if (t>firstFrame and t<=lastFrame) then
  30. append list t ;
  31. )
  32. )
  33. -- if several keyframes have the same value, we keep just one
  34. keepLoneValues list list2 ;
  35. list2 ;
  36. )
  37. -----------------------------------------------------------------------------
  38. -- write <track />
  39. -- Selected keys belongs to [firstframe,lastFrame]
  40. -- time = (key.time - firstFrame)*length/(lastFrame-firstFrame)
  41. -- (e.g. first key has time 0.)
  42. -----------------------------------------------------------------------------
  43. function writeTrack sk boneId firstframe lastframe length scale flipYZ outFile=
  44. (
  45. local angle,timef,i,bname,d,mref,mparent ;
  46. -- displays information in the maxscript listener
  47. format "retrieving key information for % ...\n" (skinOps.GetBoneName sk boneId 1) ;
  48. -- gets bone acording to the parameter boneId
  49. bname= skinOps.GetBoneName sk boneId 1 ;
  50. replaceSpaces bname ;
  51. d = getNodeByName bname ;
  52. -- gets keyframe list
  53. timelist = getTimeList d firstframe lastframe ;
  54. -- track header
  55. format("\t\t\t\t<track bone = \"%\">\n") (replaceSpaces d.name) to:outFile ;
  56. format("\t\t\t\t\t<keyframes>\n") to:outFile ;
  57. -- gets initial transform at frame 0f
  58. at time 0f (
  59. initTform = d.transform ;
  60. if (not isRoot d) then (
  61. mparent = d.parent.transform ;
  62. initTform = initTform*inverse(mparent) ;
  63. )
  64. else if (flipYZ) then (
  65. format " - flipping root bone track..." ;
  66. initTform = flipYZTransform initTform ;
  67. )
  68. )
  69. -- for each frame in the list
  70. for i in timelist do
  71. (
  72. -- moves slider time and compute OGRE time
  73. at time i (
  74. timef = ((float) (i-firstFrame)*length)/(lastframe - firstframe ) ;
  75. -- First, rotation which depends on initial transformation
  76. Tform = d.transform ;
  77. -- if this is the root bone
  78. if (isRoot d) then (
  79. mparent = matrix3 1 ;
  80. -- if flipYZ == true
  81. if (flipYZ) then
  82. Tform = flipYZTransform Tform ;
  83. )
  84. else
  85. mparent = d.parent.transform ;
  86. -- computes rotation
  87. mref = initTform*mparent ;
  88. Tform = Tform*inverse(mref) ;
  89. -- rotation part is saved.
  90. rot = Tform.rotation as angleaxis ;
  91. angle = - degToRad (rot.angle) ; -- don't know why there must be this minus :((((((
  92. -- Then, position which depends on parent
  93. Tform=d.transform ;
  94. Tform=Tform*inverse(mparent) ;
  95. -- if this is the root bone and flipYZ == true
  96. if (isRoot d and flipYZ) then (
  97. Tform = flipYZTransform Tform ;
  98. )
  99. -- substracts position of the initial transform
  100. Tform.pos -= initTform.pos ;
  101. Tform.pos = Tform.pos * scale ;
  102. pos = Tform.pos ;
  103. -- writes them !
  104. format("\t\t\t\t\t\t<keyframe time=\"%\">\n") timef to: outFile ;
  105. format("\t\t\t\t\t\t\t<translate x=\"%\" y=\"%\" z=\"%\" />\n") pos.x pos.y pos.z to: outFile ;
  106. format("\t\t\t\t\t\t\t<rotate angle=\"%\">\n") angle to:outFile ;
  107. format("\t\t\t\t\t\t\t\t<axis x=\"%\" y=\"%\" z=\"%\" />\n") (rot.axis.x) (rot.axis.y) (rot.axis.z) to:outFile ;
  108. format("\t\t\t\t\t\t\t</rotate>\n") to:outFile ;
  109. format("\t\t\t\t\t\t</keyframe>\n") to:outFile ;
  110. )
  111. )
  112. -- track end
  113. format("\t\t\t\t\t</keyframes>\n") to:outFile ;
  114. format("\t\t\t\t</track>\n") d.name to: outFile ;
  115. )
  116. -------------------------------------------------------------------------------------------------
  117. ------------------------------------------- WRITE SKELETON --------------------------------------
  118. -------------------------------------------------------------------------------------------------
  119. -- Nota :
  120. -- A vertex 0 and a bone 0 are added because 3dsmax starts with vertex 1 and bone 1.
  121. ------------------
  122. -- write <bones />
  123. ------------------
  124. function writeB sk id scale flipYZ outFile =
  125. (
  126. -- gets bone acording to the parameter boneId
  127. bname= skinOps.GetBoneName sk id 1 ;
  128. replaceSpaces bname ;
  129. d = getNodeByName bname ;
  130. -- gets initial transform at frame 0f
  131. format("\t\t<bone id=\"%\" name=\"%\">\n") id (replaceSpaces d.name) to:outFile ;
  132. slidertime = 0f ;
  133. Tform = d.transform ;
  134. if (not isRoot d) then (
  135. mparent = d.parent.transform ;
  136. Tform = Tform*inverse(mparent) ;
  137. )
  138. Tform.pos = Tform.pos * scale ;
  139. if ((isRoot d) and flipYZ) then (
  140. format "- Flipping root bone... \n" ;
  141. Tform = flipYZTransform Tform ;
  142. )
  143. pos = Tform.pos ;
  144. rot = Tform.rotation as angleaxis ;
  145. angle = - degToRad (rot.angle) ; -- don't know why there must be this minus :((((((
  146. format("\t\t\t<position x=\"%\" y=\"%\" z=\"%\" />\n") pos.x pos.y pos.z to:outFile ;
  147. format("\t\t\t<rotation angle=\"%\">\n") angle to:outFile ;
  148. format("\t\t\t\t<axis x=\"%\" y=\"%\" z=\"%\" />\n") rot.axis.x rot.axis.y rot.axis.z to:outFile ;
  149. format("\t\t\t</rotation>\n") to:outFile ;
  150. format("\t\t</bone>\n") to:outFile ;
  151. )
  152. -----------------------------
  153. -- write Bones (using writeB)
  154. -----------------------------
  155. function writeBones sk scale flipYZ outFile =
  156. (
  157. local i ;
  158. format("\t<bones>\n") to:outFile;
  159. -- we create a virtual bone number 0.
  160. format("\t\t<bone id=\"0\" name=\"zzwxy\">\n") to:outFile ;
  161. format("\t\t\t<position x=\"0\" y=\"0\" z=\"0\" />\n") to:outFile ;
  162. format("\t\t\t<rotation angle=\"0\">\n") to:outFile ;
  163. format("\t\t\t\t<axis x=\"1\" y=\"0\" z=\"0\" />\n") to:outFile ;
  164. format("\t\t\t</rotation>\n") to:outFile ;
  165. format("\t\t</bone>\n") to:outFile ;
  166. i = 0 ;
  167. for i=1 to (skinOps.GetNumberBones sk) do
  168. (
  169. writeB sk i scale flipYZ outFile ;
  170. )
  171. format("\t</bones>\n") to:outFile;
  172. )
  173. -----------------------------------
  174. -- recursive fun to write hierarchy
  175. -----------------------------------
  176. function writeH b outFile =
  177. (
  178. if ( b.parent != undefined and (isKindOf b.parent BoneGeometry or iskindOf b.parent Biped_Object)) then
  179. (
  180. p = b.parent ;
  181. format("\t\t<boneparent bone=\"%\" parent=\"%\" />\n") (replaceSpaces b.name) (replaceSpaces p.name) to:outFile ;
  182. )
  183. childrenArray = b.children ;
  184. for i=1 to childrenArray.count do
  185. (
  186. if (isKindOf b BoneGeometry or iskindOf b Biped_Object) then
  187. writeH childrenArray[i] outFile ;
  188. )
  189. )
  190. --------------------------
  191. -- write <bonehierarchy />
  192. --------------------------
  193. function writeHierarchy sk outFile =
  194. (
  195. format("\t<bonehierarchy>\n") to:outFile ;
  196. roots = getRoots sk ;
  197. -- ecriture de la track pour le bone 0.
  198. format("\t\t<boneparent bone=\"zzwxy\" parent=\"%\" />\n") roots[1].name to:outFile ;
  199. for b in roots do
  200. (
  201. writeH b outFile;
  202. )
  203. format("\t</bonehierarchy>\n") to:outFile ;
  204. )
  205. -----------------------
  206. -- write <animations />
  207. -----------------------
  208. function writeAnim sk firstFrame lastFrame length scale flipYZ name outFile =
  209. (
  210. local i,n ;
  211. format("\t<animations>\n") to: outFile ;
  212. format("\t\t<animation name=\"%\" length=\"%\">\n") name length to:outFile ;
  213. format("\t\t\t<tracks>\n") to:outFile
  214. -- ecriture track 0
  215. format("\t\t\t\t<track bone = \"zzwxy\">\n") to: outFile ;
  216. format("\t\t\t\t\t<keyframes>\n") to:outFile ;
  217. format("\t\t\t\t\t\t<keyframe time=\"0\">\n") to:outFile ;
  218. format("\t\t\t\t\t\t\t<translate x=\"0\" y=\"0\" z=\"0\" />\n") to: outFile ;
  219. format("\t\t\t\t\t\t\t<rotate angle=\"0\">\n") to:outFile ;
  220. format("\t\t\t\t\t\t\t\t<axis x=\"1\" y=\"0\" z=\"0\" />\n") to:outFile ;
  221. format("\t\t\t\t\t\t\t</rotate>\n") to:outFile ;
  222. format("\t\t\t\t\t\t</keyframe>\n") to:outFile ;
  223. format("\t\t\t\t\t</keyframes>\n") to:outFile ;
  224. format("\t\t\t\t</track>\n") to: outFile ;
  225. n = skinOps.GetNumberBones sk ;
  226. liste = #(0,20,30,40) ;
  227. for i = 1 to n do
  228. writeTrack sk i firstframe lastframe length scale flipYZ outFile ;
  229. format("\t\t\t</tracks>\n") to:outFile
  230. format("\t\t</animation>\n") to: outFile ;
  231. format("\t</animations>\n") to: outFile ;
  232. )
  233. -------------------------------------------------------------
  234. -- write <skeleton /> main function
  235. -- write the animation in the file out_name + ".skeleton.xml"
  236. -- between the frame firstFrame and lastFrame
  237. -- and scale time according to length
  238. -------------------------------------------------------------
  239. function writeSkeleton pmesh exportOptions out_name =
  240. (
  241. local sk,n,keys,initialKeys,messages ;
  242. sk = getSkin pmesh ;
  243. if (sk == undefined) then
  244. (
  245. MessageBox "There is no skin modifier for this object" ;
  246. )
  247. else
  248. (
  249. -- in order to perform, skin should be opened
  250. max modify mode ;
  251. modPanel.setCurrentObject pmesh.modifiers[#Skin] ;
  252. format "------------------------------------------\n"
  253. format "------ OGRE skeleton Exporter Log ------\n"
  254. format "------------------------------------------\n"
  255. format "Exporter options :\n"
  256. format "- firstFrame: % \n- lastFrame: %\n" exportOptions.firstFrame exportOptions.lastFrame ;
  257. -- creates the output file
  258. outFile = createfile (out_name + ".skeleton.xml") ;
  259. -- writes header
  260. format("<skeleton>\n") to:outFile ;
  261. format "Writing bones :\n" ;
  262. writeBones sk exportOptions.scale exportOptions.flipYZ outFile ;
  263. format "Writing bone hierarchy.\n" ;
  264. writeHierarchy sk outFile ;
  265. format "Writing bone tracks.\n" ;
  266. writeAnim sk exportOptions.firstFrame exportOptions.lastFrame exportOptions.length exportOptions.scale exportOptions.flipYZ exportOptions.animName outFile ;
  267. -- ecriture, fin des balises
  268. format("</skeleton>\n") to: outFile ;
  269. format "------------------------------------------\n"
  270. format "---------- END ---------\n"
  271. format "------------------------------------------\n"
  272. close outFile ;
  273. messageBox "Exporting skeleton successful !"
  274. )
  275. )