| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 | import {	Matrix4,	Quaternion,	Vector3} from '../../../build/three.module.js';import { MMDParser } from '../libs/mmdparser.module.js';/** * Dependencies *  - mmd-parser https://github.com/takahirox/mmd-parser */class MMDExporter {	/* TODO: implement	// mesh -> pmd	this.parsePmd = function ( object ) {	};	*/	/* TODO: implement	// mesh -> pmx	this.parsePmx = function ( object ) {	};	*/	/* TODO: implement	// animation + skeleton -> vmd	this.parseVmd = function ( object ) {	};	*/	/*	 * skeleton -> vpd	 * Returns Shift_JIS encoded Uint8Array. Otherwise return strings.	 */	parseVpd( 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;			let a = num.toString();			if ( a.indexOf( '.' ) === - 1 ) {				a += '.';			}			a += '000000';			const index = a.indexOf( '.' );			const d = a.slice( 0, index );			const p = a.slice( index + 1, index + 7 );			return d + '.' + p;		}		function toStringsFromArray( array ) {			const a = [];			for ( let i = 0, il = array.length; i < il; i ++ ) {				a.push( toStringsFromNumber( array[ i ] ) );			}			return a.join( ',' );		}		skin.updateMatrixWorld( true );		const bones = skin.skeleton.bones;		const bones2 = getBindBones( skin );		const position = new Vector3();		const quaternion = new Quaternion();		const quaternion2 = new Quaternion();		const matrix = new Matrix4();		const 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 ( let i = 0, il = bones.length; i < il; i ++ ) {			const bone = bones[ i ];			const 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 );			const pArray = position.sub( bone2.position ).toArray();			const 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( '' );		const lines = array.join( '\n' );		return ( outputShiftJis === true ) ? unicodeToShiftjis( lines ) : lines;	}}// Unicode to Shift_JIS tablelet u2sTable;function unicodeToShiftjis( str ) {	if ( u2sTable === undefined ) {		const encoder = new MMDParser.CharsetEncoder(); // eslint-disable-line no-undef		const table = encoder.s2uTable;		u2sTable = {};		const keys = Object.keys( table );		for ( let i = 0, il = keys.length; i < il; i ++ ) {			let key = keys[ i ];			const value = table[ key ];			key = parseInt( key );			u2sTable[ value ] = key;		}	}	const array = [];	for ( let i = 0, il = str.length; i < il; i ++ ) {		const code = str.charCodeAt( i );		const 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?	const poseSkin = skin.clone();	poseSkin.pose();	return poseSkin.skeleton.bones;}export { MMDExporter };
 |