MMDExporter.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * @author takahiro / http://github.com/takahirox
  3. *
  4. * Dependencies
  5. * - mmd-parser https://github.com/takahirox/mmd-parser
  6. */
  7. THREE.MMDExporter = function () {
  8. // Unicode to Shift_JIS table
  9. var u2sTable;
  10. function unicodeToShiftjis( str ) {
  11. if ( u2sTable === undefined ) {
  12. var encoder = new MMDParser.CharsetEncoder();
  13. var table = encoder.s2uTable;
  14. u2sTable = {};
  15. var keys = Object.keys( table );
  16. for ( var i = 0, il = keys.length; i < il; i ++ ) {
  17. var key = keys[ i ];
  18. var value = table[ key ];
  19. key = parseInt( key );
  20. u2sTable[ value ] = key;
  21. }
  22. }
  23. var array = [];
  24. for ( var i = 0, il = str.length; i < il; i ++ ) {
  25. var code = str.charCodeAt( i )
  26. var value = u2sTable[ code ];
  27. if ( value === undefined ) {
  28. throw 'cannot convert charcode 0x' + code.toString( 16 );
  29. } else if ( value > 0xff ) {
  30. array.push( ( value >> 8 ) & 0xff );
  31. array.push( value & 0xff );
  32. } else {
  33. array.push( value & 0xff );
  34. }
  35. }
  36. return new Uint8Array( array );
  37. }
  38. function getBindBones( skin ) {
  39. // any more efficient ways?
  40. var poseSkin = skin.clone();
  41. poseSkin.pose();
  42. return poseSkin.skeleton.bones;
  43. }
  44. /* TODO: implement
  45. // mesh -> pmd
  46. this.parsePmd = function ( object ) {
  47. };
  48. */
  49. /* TODO: implement
  50. // mesh -> pmx
  51. this.parsePmx = function ( object ) {
  52. };
  53. */
  54. /*
  55. * skeleton -> vpd
  56. * Returns Shift_JIS encoded Uint8Array. Otherwise return strings.
  57. */
  58. this.parseVpd = function ( skin, outputShiftJis, useOriginalBones ) {
  59. if ( skin.isSkinnedMesh !== true ) {
  60. console.warn( 'THREE.MMDExporter: parseVpd() requires SkinnedMesh instance.' );
  61. return null;
  62. }
  63. function toStringsFromNumber( num ) {
  64. if ( Math.abs( num ) < 1e-6 ) num = 0;
  65. var a = num.toString();
  66. if ( a.indexOf( '.' ) === -1 ) {
  67. a += '.';
  68. }
  69. a += '000000';
  70. var index = a.indexOf( '.' );
  71. var d = a.slice( 0, index );
  72. var p = a.slice( index + 1, index + 7 );
  73. return d + '.' + p;
  74. }
  75. function toStringsFromArray( array ) {
  76. var a = [];
  77. for ( var i = 0, il = array.length; i < il; i ++ ) {
  78. a.push( toStringsFromNumber( array[ i ] ) );
  79. }
  80. return a.join( ',' );
  81. }
  82. skin.updateMatrixWorld( true );
  83. var bones = skin.skeleton.bones;
  84. var bones2 = getBindBones( skin );
  85. var position = new THREE.Vector3();
  86. var quaternion = new THREE.Quaternion();
  87. var quaternion2 = new THREE.Quaternion();
  88. var matrix = new THREE.Matrix4();
  89. var array = [];
  90. array.push( 'Vocaloid Pose Data file' );
  91. array.push( '' );
  92. array.push( ( skin.name !== '' ? skin.name.replace( /\s/g, '_' ) : 'skin' ) + '.osm;' );
  93. array.push( bones.length + ';' );
  94. array.push( '' );
  95. for ( var i = 0, il = bones.length; i < il; i ++ ) {
  96. var bone = bones[ i ];
  97. var bone2 = bones2[ i ];
  98. /*
  99. * use the bone matrix saved before solving IK.
  100. * see CCDIKSolver for the detail.
  101. */
  102. if ( useOriginalBones === true &&
  103. bone.userData.ik !== undefined &&
  104. bone.userData.ik.originalMatrix !== undefined ) {
  105. matrix.fromArray( bone.userData.ik.originalMatrix );
  106. } else {
  107. matrix.copy( bone.matrix );
  108. }
  109. position.setFromMatrixPosition( matrix );
  110. quaternion.setFromRotationMatrix( matrix );
  111. var pArray = position.sub( bone2.position ).toArray();
  112. var qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray();
  113. // right to left
  114. pArray[ 2 ] = -pArray[ 2 ];
  115. qArray[ 0 ] = -qArray[ 0 ];
  116. qArray[ 1 ] = -qArray[ 1 ];
  117. array.push( 'Bone' + i + '{' + bone.name );
  118. array.push( ' ' + toStringsFromArray( pArray ) + ';' );
  119. array.push( ' ' + toStringsFromArray( qArray ) + ';' );
  120. array.push( '}' );
  121. array.push( '' );
  122. }
  123. array.push( '' );
  124. var lines = array.join( '\n' );
  125. return ( outputShiftJis === true ) ? unicodeToShiftjis( lines ) : lines;
  126. };
  127. /* TODO: implement
  128. // animation + skeleton -> vmd
  129. this.parseVmd = function ( object ) {
  130. };
  131. */
  132. };