Spaces:
Running
Running
/** | |
* @author takahiro / http://github.com/takahirox | |
* | |
* Dependencies | |
* - mmd-parser https://github.com/takahirox/mmd-parser | |
*/ | |
THREE.MMDExporter = function () { | |
// Unicode to Shift_JIS table | |
var u2sTable; | |
function unicodeToShiftjis( str ) { | |
if ( u2sTable === undefined ) { | |
var encoder = new MMDParser.CharsetEncoder(); | |
var table = encoder.s2uTable; | |
u2sTable = {}; | |
var keys = Object.keys( table ); | |
for ( var i = 0, il = keys.length; i < il; i ++ ) { | |
var key = keys[ i ]; | |
var value = table[ key ]; | |
key = parseInt( key ); | |
u2sTable[ value ] = key; | |
} | |
} | |
var array = []; | |
for ( var i = 0, il = str.length; i < il; i ++ ) { | |
var code = str.charCodeAt( i ); | |
var value = u2sTable[ code ]; | |
if ( value === undefined ) { | |
throw 'cannot convert charcode 0x' + code.toString( 16 ); | |
} else if ( value > 0xff ) { | |
array.push( ( value >> 8 ) & 0xff ); | |
array.push( value & 0xff ); | |
} else { | |
array.push( value & 0xff ); | |
} | |
} | |
return new Uint8Array( array ); | |
} | |
function getBindBones( skin ) { | |
// any more efficient ways? | |
var poseSkin = skin.clone(); | |
poseSkin.pose(); | |
return poseSkin.skeleton.bones; | |
} | |
/* TODO: implement | |
// mesh -> pmd | |
this.parsePmd = function ( object ) { | |
}; | |
*/ | |
/* TODO: implement | |
// mesh -> pmx | |
this.parsePmx = function ( object ) { | |
}; | |
*/ | |
/* | |
* skeleton -> vpd | |
* Returns Shift_JIS encoded Uint8Array. Otherwise return strings. | |
*/ | |
this.parseVpd = function ( skin, outputShiftJis, useOriginalBones ) { | |
if ( skin.isSkinnedMesh !== true ) { | |
console.warn( 'THREE.MMDExporter: parseVpd() requires SkinnedMesh instance.' ); | |
return null; | |
} | |
function toStringsFromNumber( num ) { | |
if ( Math.abs( num ) < 1e-6 ) num = 0; | |
var a = num.toString(); | |
if ( a.indexOf( '.' ) === - 1 ) { | |
a += '.'; | |
} | |
a += '000000'; | |
var index = a.indexOf( '.' ); | |
var d = a.slice( 0, index ); | |
var p = a.slice( index + 1, index + 7 ); | |
return d + '.' + p; | |
} | |
function toStringsFromArray( array ) { | |
var a = []; | |
for ( var i = 0, il = array.length; i < il; i ++ ) { | |
a.push( toStringsFromNumber( array[ i ] ) ); | |
} | |
return a.join( ',' ); | |
} | |
skin.updateMatrixWorld( true ); | |
var bones = skin.skeleton.bones; | |
var bones2 = getBindBones( skin ); | |
var position = new THREE.Vector3(); | |
var quaternion = new THREE.Quaternion(); | |
var quaternion2 = new THREE.Quaternion(); | |
var matrix = new THREE.Matrix4(); | |
var array = []; | |
array.push( 'Vocaloid Pose Data file' ); | |
array.push( '' ); | |
array.push( ( skin.name !== '' ? skin.name.replace( /\s/g, '_' ) : 'skin' ) + '.osm;' ); | |
array.push( bones.length + ';' ); | |
array.push( '' ); | |
for ( var i = 0, il = bones.length; i < il; i ++ ) { | |
var bone = bones[ i ]; | |
var bone2 = bones2[ i ]; | |
/* | |
* use the bone matrix saved before solving IK. | |
* see CCDIKSolver for the detail. | |
*/ | |
if ( useOriginalBones === true && | |
bone.userData.ik !== undefined && | |
bone.userData.ik.originalMatrix !== undefined ) { | |
matrix.fromArray( bone.userData.ik.originalMatrix ); | |
} else { | |
matrix.copy( bone.matrix ); | |
} | |
position.setFromMatrixPosition( matrix ); | |
quaternion.setFromRotationMatrix( matrix ); | |
var pArray = position.sub( bone2.position ).toArray(); | |
var qArray = quaternion2.copy( bone2.quaternion ).conjugate().multiply( quaternion ).toArray(); | |
// right to left | |
pArray[ 2 ] = - pArray[ 2 ]; | |
qArray[ 0 ] = - qArray[ 0 ]; | |
qArray[ 1 ] = - qArray[ 1 ]; | |
array.push( 'Bone' + i + '{' + bone.name ); | |
array.push( ' ' + toStringsFromArray( pArray ) + ';' ); | |
array.push( ' ' + toStringsFromArray( qArray ) + ';' ); | |
array.push( '}' ); | |
array.push( '' ); | |
} | |
array.push( '' ); | |
var lines = array.join( '\n' ); | |
return ( outputShiftJis === true ) ? unicodeToShiftjis( lines ) : lines; | |
}; | |
/* TODO: implement | |
// animation + skeleton -> vmd | |
this.parseVmd = function ( object ) { | |
}; | |
*/ | |
}; | |