MMDLoader.js 46.8 KB
Newer Older
M
r119  
Mr.doob 已提交
1
console.warn( "THREE.MMDLoader: As part of the transition to ES6 Modules, the files in 'examples/js' were deprecated in May 2020 (r117) and will be deleted in December 2020 (r124). You can find more information about developing using ES6 Modules in https://threejs.org/docs/#manual/en/introduction/Installation." );
M
r74  
Mr.doob 已提交
2 3
/**
 * Dependencies
M
r83  
Mr.doob 已提交
4
 *  - mmd-parser https://github.com/takahirox/mmd-parser
M
r74  
Mr.doob 已提交
5
 *  - THREE.TGALoader
M
r82  
Mr.doob 已提交
6
 *  - THREE.OutlineEffect
M
r74  
Mr.doob 已提交
7
 *
M
r93  
Mr.doob 已提交
8 9
 * MMDLoader creates Three.js Objects from MMD resources as
 * PMD, PMX, VMD, and VPD files.
M
r74  
Mr.doob 已提交
10
 *
M
r93  
Mr.doob 已提交
11 12
 * PMD/PMX is a model data format, VMD is a motion data format
 * VPD is a posing data format used in MMD(Miku Miku Dance).
M
r74  
Mr.doob 已提交
13 14
 *
 * MMD official site
M
r115  
Mr.doob 已提交
15
 *  - https://sites.google.com/view/evpvp/
M
r74  
Mr.doob 已提交
16
 *
M
r93  
Mr.doob 已提交
17 18
 * PMD, VMD format (in Japanese)
 *  - http://blog.goo.ne.jp/torisu_tetosuki/e/209ad341d3ece2b1b4df24abf619d6e4
M
r74  
Mr.doob 已提交
19 20
 *
 * PMX format
M
r93  
Mr.doob 已提交
21
 *  - https://gist.github.com/felixjones/f8a06bd48f9da9a4539f
M
r74  
Mr.doob 已提交
22 23 24 25 26
 *
 * TODO
 *  - light motion in vmd support.
 *  - SDEF support.
 *  - uv/material/bone morphing support.
M
r76  
Mr.doob 已提交
27
 *  - more precise grant skinning support.
M
r74  
Mr.doob 已提交
28 29 30
 *  - shadow support.
 */

M
r93  
Mr.doob 已提交
31
THREE.MMDLoader = ( function () {
M
r74  
Mr.doob 已提交
32

M
r93  
Mr.doob 已提交
33 34 35 36
	/**
	 * @param {THREE.LoadingManager} manager
	 */
	function MMDLoader( manager ) {
M
r83  
Mr.doob 已提交
37

M
r109  
Mr.doob 已提交
38
		THREE.Loader.call( this, manager );
M
r74  
Mr.doob 已提交
39

M
r93  
Mr.doob 已提交
40
		this.loader = new THREE.FileLoader( this.manager );
M
r74  
Mr.doob 已提交
41

M
r93  
Mr.doob 已提交
42 43 44
		this.parser = null; // lazy generation
		this.meshBuilder = new MeshBuilder( this.manager );
		this.animationBuilder = new AnimationBuilder();
M
r74  
Mr.doob 已提交
45

M
r83  
Mr.doob 已提交
46
	}
M
r74  
Mr.doob 已提交
47

M
r109  
Mr.doob 已提交
48
	MMDLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
M
r74  
Mr.doob 已提交
49

M
r93  
Mr.doob 已提交
50
		constructor: MMDLoader,
M
r74  
Mr.doob 已提交
51

M
r99  
Mr.doob 已提交
52 53 54 55 56 57 58 59 60 61 62
		/**
		 * @param {string} animationPath
		 * @return {THREE.MMDLoader}
		 */
		setAnimationPath: function ( animationPath ) {

			this.animationPath = animationPath;
			return this;

		},

M
r93  
Mr.doob 已提交
63
		// Load MMD assets as Three.js Object
M
r74  
Mr.doob 已提交
64

M
r93  
Mr.doob 已提交
65 66 67 68 69 70 71 72 73
		/**
		 * Loads Model file (.pmd or .pmx) as a THREE.SkinnedMesh.
		 *
		 * @param {string} url - url to Model(.pmd or .pmx) file
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		load: function ( url, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
74

M
r93  
Mr.doob 已提交
75
			var builder = this.meshBuilder.setCrossOrigin( this.crossOrigin );
M
r74  
Mr.doob 已提交
76

M
r99  
Mr.doob 已提交
77 78 79 80
			// resource path

			var resourcePath;

M
r109  
Mr.doob 已提交
81
			if ( this.resourcePath !== '' ) {
M
r99  
Mr.doob 已提交
82 83 84

				resourcePath = this.resourcePath;

M
r109  
Mr.doob 已提交
85
			} else if ( this.path !== '' ) {
M
r99  
Mr.doob 已提交
86 87 88 89 90 91 92 93 94

				resourcePath = this.path;

			} else {

				resourcePath = THREE.LoaderUtils.extractUrlBase( url );

			}

M
r93  
Mr.doob 已提交
95
			var modelExtension = this._extractExtension( url ).toLowerCase();
M
r83  
Mr.doob 已提交
96

M
r93  
Mr.doob 已提交
97 98
			// Should I detect by seeing header?
			if ( modelExtension !== 'pmd' && modelExtension !== 'pmx' ) {
M
r83  
Mr.doob 已提交
99

M
r93  
Mr.doob 已提交
100
				if ( onError ) onError( new Error( 'THREE.MMDLoader: Unknown model file extension .' + modelExtension + '.' ) );
M
r74  
Mr.doob 已提交
101

M
r93  
Mr.doob 已提交
102
				return;
M
r83  
Mr.doob 已提交
103

M
r93  
Mr.doob 已提交
104
			}
M
r74  
Mr.doob 已提交
105

M
r93  
Mr.doob 已提交
106
			this[ modelExtension === 'pmd' ? 'loadPMD' : 'loadPMX' ]( url, function ( data ) {
M
r74  
Mr.doob 已提交
107

M
r99  
Mr.doob 已提交
108
				onLoad(	builder.build( data, resourcePath, onProgress, onError )	);
M
r74  
Mr.doob 已提交
109

M
r93  
Mr.doob 已提交
110
			}, onProgress, onError );
M
r74  
Mr.doob 已提交
111

M
r93  
Mr.doob 已提交
112
		},
M
r74  
Mr.doob 已提交
113

M
r93  
Mr.doob 已提交
114 115 116 117 118 119 120 121 122 123 124
		/**
		 * Loads Motion file(s) (.vmd) as a THREE.AnimationClip.
		 * If two or more files are specified, they'll be merged.
		 *
		 * @param {string|Array<string>} url - url(s) to animation(.vmd) file(s)
		 * @param {THREE.SkinnedMesh|THREE.Camera} object - tracks will be fitting to this object
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		loadAnimation: function ( url, object, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
125

M
r93  
Mr.doob 已提交
126
			var builder = this.animationBuilder;
M
r74  
Mr.doob 已提交
127

M
r93  
Mr.doob 已提交
128
			this.loadVMD( url, function ( vmd ) {
M
r74  
Mr.doob 已提交
129

M
r93  
Mr.doob 已提交
130 131 132
				onLoad( object.isCamera
					? builder.buildCameraAnimation( vmd )
					: builder.build( vmd, object ) );
M
r74  
Mr.doob 已提交
133

M
r93  
Mr.doob 已提交
134
			}, onProgress, onError );
M
r74  
Mr.doob 已提交
135

M
r93  
Mr.doob 已提交
136
		},
M
r74  
Mr.doob 已提交
137

M
r93  
Mr.doob 已提交
138 139 140 141 142 143 144 145 146 147 148 149
		/**
		 * Loads mode file and motion file(s) as an object containing
		 * a THREE.SkinnedMesh and a THREE.AnimationClip.
		 * Tracks of THREE.AnimationClip are fitting to the model.
		 *
		 * @param {string} modelUrl - url to Model(.pmd or .pmx) file
		 * @param {string|Array{string}} vmdUrl - url(s) to animation(.vmd) file
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		loadWithAnimation: function ( modelUrl, vmdUrl, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
150

M
r93  
Mr.doob 已提交
151
			var scope = this;
M
r74  
Mr.doob 已提交
152

M
r93  
Mr.doob 已提交
153
			this.load( modelUrl, function ( mesh ) {
M
r74  
Mr.doob 已提交
154

M
r93  
Mr.doob 已提交
155
				scope.loadAnimation( vmdUrl, mesh, function ( animation ) {
M
r74  
Mr.doob 已提交
156

M
r93  
Mr.doob 已提交
157 158 159 160
					onLoad( {
						mesh: mesh,
						animation: animation
					} );
M
r74  
Mr.doob 已提交
161

M
r93  
Mr.doob 已提交
162
				}, onProgress, onError );
M
r74  
Mr.doob 已提交
163

M
r93  
Mr.doob 已提交
164
			}, onProgress, onError );
M
r74  
Mr.doob 已提交
165

M
r93  
Mr.doob 已提交
166
		},
M
r74  
Mr.doob 已提交
167

M
r93  
Mr.doob 已提交
168
		// Load MMD assets as Object data parsed by MMDParser
M
r74  
Mr.doob 已提交
169

M
r93  
Mr.doob 已提交
170 171 172 173 174 175 176 177 178
		/**
		 * Loads .pmd file as an Object.
		 *
		 * @param {string} url - url to .pmd file
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		loadPMD: function ( url, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
179

M
r93  
Mr.doob 已提交
180
			var parser = this._getParser();
M
r74  
Mr.doob 已提交
181

M
r93  
Mr.doob 已提交
182 183
			this.loader
				.setMimeType( undefined )
M
r99  
Mr.doob 已提交
184
				.setPath( this.path )
M
r93  
Mr.doob 已提交
185
				.setResponseType( 'arraybuffer' )
M
r119  
Mr.doob 已提交
186
				.setRequestHeader( this.requestHeader )
M
r93  
Mr.doob 已提交
187
				.load( url, function ( buffer ) {
M
r74  
Mr.doob 已提交
188

M
r93  
Mr.doob 已提交
189
					onLoad( parser.parsePmd( buffer, true ) );
M
r74  
Mr.doob 已提交
190

M
r93  
Mr.doob 已提交
191
				}, onProgress, onError );
M
r74  
Mr.doob 已提交
192

M
r93  
Mr.doob 已提交
193
		},
M
r74  
Mr.doob 已提交
194

M
r93  
Mr.doob 已提交
195 196 197 198 199 200 201 202 203
		/**
		 * Loads .pmx file as an Object.
		 *
		 * @param {string} url - url to .pmx file
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		loadPMX: function ( url, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
204

M
r93  
Mr.doob 已提交
205
			var parser = this._getParser();
M
r74  
Mr.doob 已提交
206

M
r93  
Mr.doob 已提交
207 208
			this.loader
				.setMimeType( undefined )
M
r99  
Mr.doob 已提交
209
				.setPath( this.path )
M
r93  
Mr.doob 已提交
210
				.setResponseType( 'arraybuffer' )
M
r119  
Mr.doob 已提交
211
				.setRequestHeader( this.requestHeader )
M
r93  
Mr.doob 已提交
212
				.load( url, function ( buffer ) {
M
r74  
Mr.doob 已提交
213

M
r93  
Mr.doob 已提交
214
					onLoad( parser.parsePmx( buffer, true ) );
M
r74  
Mr.doob 已提交
215

M
r93  
Mr.doob 已提交
216
				}, onProgress, onError );
M
r74  
Mr.doob 已提交
217

M
r93  
Mr.doob 已提交
218
		},
M
r74  
Mr.doob 已提交
219

M
r93  
Mr.doob 已提交
220 221 222 223 224 225 226 227 228 229
		/**
		 * Loads .vmd file as an Object. If two or more files are specified
		 * they'll be merged.
		 *
		 * @param {string|Array<string>} url - url(s) to .vmd file(s)
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
		loadVMD: function ( url, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
230

M
r93  
Mr.doob 已提交
231
			var urls = Array.isArray( url ) ? url : [ url ];
M
r74  
Mr.doob 已提交
232

M
r93  
Mr.doob 已提交
233 234
			var vmds = [];
			var vmdNum = urls.length;
M
r74  
Mr.doob 已提交
235

M
r93  
Mr.doob 已提交
236
			var parser = this._getParser();
M
r74  
Mr.doob 已提交
237

M
r93  
Mr.doob 已提交
238 239
			this.loader
				.setMimeType( undefined )
M
r99  
Mr.doob 已提交
240
				.setPath( this.animationPath )
M
r119  
Mr.doob 已提交
241 242
				.setResponseType( 'arraybuffer' )
				.setRequestHeader( this.requestHeader );
M
r74  
Mr.doob 已提交
243

M
r93  
Mr.doob 已提交
244
			for ( var i = 0, il = urls.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
245

M
r93  
Mr.doob 已提交
246
				this.loader.load( urls[ i ], function ( buffer ) {
M
r74  
Mr.doob 已提交
247

M
r93  
Mr.doob 已提交
248
					vmds.push( parser.parseVmd( buffer, true ) );
M
r74  
Mr.doob 已提交
249

M
r93  
Mr.doob 已提交
250
					if ( vmds.length === vmdNum ) onLoad( parser.mergeVmds( vmds ) );
M
r74  
Mr.doob 已提交
251

M
r93  
Mr.doob 已提交
252
				}, onProgress, onError );
M
r74  
Mr.doob 已提交
253

M
r83  
Mr.doob 已提交
254
			}
M
r74  
Mr.doob 已提交
255

M
r93  
Mr.doob 已提交
256
		},
M
r74  
Mr.doob 已提交
257

M
r93  
Mr.doob 已提交
258 259 260 261 262 263 264 265 266
		/**
		 * Loads .vpd file as an Object.
		 *
		 * @param {string} url - url to .vpd file
		 * @param {boolean} isUnicode
		 * @param {function} onLoad
		 * @param {function} onProgress
		 * @param {function} onError
		 */
M
r96  
Mr.doob 已提交
267
		loadVPD: function ( url, isUnicode, onLoad, onProgress, onError ) {
M
r74  
Mr.doob 已提交
268

M
r93  
Mr.doob 已提交
269
			var parser = this._getParser();
M
r74  
Mr.doob 已提交
270

M
r93  
Mr.doob 已提交
271 272
			this.loader
				.setMimeType( isUnicode ? undefined : 'text/plain; charset=shift_jis' )
M
r99  
Mr.doob 已提交
273
				.setPath( this.animationPath )
M
r93  
Mr.doob 已提交
274
				.setResponseType( 'text' )
M
r119  
Mr.doob 已提交
275
				.setRequestHeader( this.requestHeader )
M
r93  
Mr.doob 已提交
276
				.load( url, function ( text ) {
M
r74  
Mr.doob 已提交
277

M
r93  
Mr.doob 已提交
278
					onLoad( parser.parseVpd( text, true ) );
M
r74  
Mr.doob 已提交
279

M
r93  
Mr.doob 已提交
280
				}, onProgress, onError );
M
r74  
Mr.doob 已提交
281

M
r93  
Mr.doob 已提交
282
		},
M
r74  
Mr.doob 已提交
283

M
r93  
Mr.doob 已提交
284
		// private methods
M
r74  
Mr.doob 已提交
285

M
r93  
Mr.doob 已提交
286
		_extractExtension: function ( url ) {
M
r74  
Mr.doob 已提交
287

M
r93  
Mr.doob 已提交
288 289
			var index = url.lastIndexOf( '.' );
			return index < 0 ? '' : url.slice( index + 1 );
M
r74  
Mr.doob 已提交
290

M
r93  
Mr.doob 已提交
291
		},
M
r74  
Mr.doob 已提交
292

M
r93  
Mr.doob 已提交
293
		_getParser: function () {
M
r74  
Mr.doob 已提交
294

M
r93  
Mr.doob 已提交
295
			if ( this.parser === null ) {
M
r74  
Mr.doob 已提交
296

M
r93  
Mr.doob 已提交
297
				if ( typeof MMDParser === 'undefined' ) {
M
r74  
Mr.doob 已提交
298

M
r93  
Mr.doob 已提交
299
					throw new Error( 'THREE.MMDLoader: Import MMDParser https://github.com/takahirox/mmd-parser' );
M
r74  
Mr.doob 已提交
300

M
r93  
Mr.doob 已提交
301
				}
M
r74  
Mr.doob 已提交
302

M
r120  
Mr.doob 已提交
303
				this.parser = new MMDParser.Parser(); // eslint-disable-line no-undef
M
r74  
Mr.doob 已提交
304

M
r83  
Mr.doob 已提交
305
			}
M
r74  
Mr.doob 已提交
306

M
r93  
Mr.doob 已提交
307
			return this.parser;
M
r74  
Mr.doob 已提交
308

M
r83  
Mr.doob 已提交
309
		}
M
r74  
Mr.doob 已提交
310

M
r109  
Mr.doob 已提交
311
	} );
M
r74  
Mr.doob 已提交
312

M
r93  
Mr.doob 已提交
313
	// Utilities
M
r74  
Mr.doob 已提交
314

M
r93  
Mr.doob 已提交
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
	/*
	 * base64 encoded defalut toon textures toon00.bmp - toon10.bmp.
	 * We don't need to request external toon image files.
	 * This idea is from http://www20.atpages.jp/katwat/three.js_r58/examples/mytest37/mmd.three.js
	 */
	var DEFAULT_TOON_TEXTURES = [
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/bWiiMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh8aBHZBl14e8wAAAABJRU5ErkJggg==',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOUlEQVRYR+3WMREAMAwDsYY/yoDI7MLwIiP40+RJklfcCCBAgAABAgTqArfb/QMCCBAgQIAAgbbAB3z/e0F3js2cAAAAAElFTkSuQmCC',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAN0lEQVRYR+3WQREAMBACsZ5/B5ilMvgEBTt5cW37hjsBBAgQIECAwFwgyfYPCCBAgAABAgTWAh81dWyx0gFwKAAAAABJRU5ErkJggg==',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAOklEQVRYR+3WoREAMAwDsWb/UQtCy9wxTOQJ/oQ8SXKKGwEECBAgQIBAXeDt7f4BAQQIECBAgEBb4AOz8Hzx7WLY4wAAAABJRU5ErkJggg==',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABPUlEQVRYR+1XwW7CMAy1+f9fZOMysSEOEweEOPRNdm3HbdOyIhAcklPrOs/PLy9RygBALxzcCDQFmgJNgaZAU6Ap0BR4PwX8gsRMVLssMRH5HcpzJEaWL7EVg9F1IHRlyqQohgVr4FGUlUcMJSjcUlDw0zvjeun70cLWmneoyf7NgBTQSniBTQQSuJAZsOnnaczjIMb5hCiuHKxokCrJfVnrctyZL0PkJAJe1HMil4nxeyi3Ypfn1kX51jpPvo/JeCNC4PhVdHdJw2XjBR8brF8PEIhNVn12AgP7uHsTBguBn53MUZCqv7Lp07Pn5k1Ro+uWmUNn7D+M57rtk7aG0Vo73xyF/fbFf0bPJjDXngnGocDTdFhygZjwUQrMNrDcmZlQT50VJ/g/UwNyHpu778+yW+/ksOz/BFo54P4AsUXMfRq7XWsAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACMElEQVRYR+2Xv4pTQRTGf2dubhLdICiii2KnYKHVolhauKWPoGAnNr6BD6CvIVaihYuI2i1ia0BY0MZGRHQXjZj/mSPnnskfNWiWZUlzJ5k7M2cm833nO5Mziej2DWWJRUoCpQKlAntSQCqgw39/iUWAGmh37jrRnVsKlgpiqmkoGVABA7E57fvY+pJDdgKqF6HzFCSADkDq+F6AHABtQ+UMVE5D7zXod7fFNhTEckTbj5XQgHzNN+5tQvc5NG7C6BNkp6D3EmpXHDR+dQAjFLchW3VS9rlw3JBh+B7ys5Cf9z0GW1C/7P32AyBAOAz1q4jGliIH3YPuBnSfQX4OGreTIgEYQb/pBDtPnEQ4CivXYPAWBk13oHrB54yA9QuSn2H4AcKRpEILDt0BUzj+RLR1V5EqjD66NPRBVpLcQwjHoHYJOhsQv6U4mnzmrIXJCFr4LDwm/xBUoboG9XX4cc9VKdYoSA2yk5NQLJaKDUjTBoveG3Z2TElTxwjNK4M3LEZgUdDdruvcXzKBpStgp2NPiWi3ks9ZXxIoFVi+AvHLdc9TqtjL3/aYjpPlrzOcEnK62Szhimdd7xX232zFDTgtxezOu3WNMRLjiKgjtOhHVMd1loynVHvOgjuIIJMaELEqhJAV/RCSLbWTcfPFakFgFlALTRRvx+ok6Hlp/Q+v3fmx90bMyUzaEAhmM3KvHlXTL5DxnbGf/1M8RNNACLL5MNtPxP/mypJAqcDSFfgFhpYqWUzhTEAAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII=',
		'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAL0lEQVRYR+3QQREAAAzCsOFfNJPBJ1XQS9r2hsUAAQIECBAgQIAAAQIECBAgsBZ4MUx/ofm2I/kAAAAASUVORK5CYII='
	];

	// Builders. They build Three.js object from Object data parsed by MMDParser.

	/**
	 * @param {THREE.LoadingManager} manager
	 */
	function MeshBuilder( manager ) {
M
r74  
Mr.doob 已提交
340

M
r93  
Mr.doob 已提交
341 342
		this.geometryBuilder = new GeometryBuilder();
		this.materialBuilder = new MaterialBuilder( manager );
M
r74  
Mr.doob 已提交
343

M
r83  
Mr.doob 已提交
344
	}
M
r74  
Mr.doob 已提交
345

M
r93  
Mr.doob 已提交
346
	MeshBuilder.prototype = {
M
r74  
Mr.doob 已提交
347

M
r93  
Mr.doob 已提交
348
		constructor: MeshBuilder,
M
r74  
Mr.doob 已提交
349

M
r94  
Mr.doob 已提交
350
		crossOrigin: 'anonymous',
M
r74  
Mr.doob 已提交
351

M
r93  
Mr.doob 已提交
352 353 354 355 356
		/**
		 * @param {string} crossOrigin
		 * @return {MeshBuilder}
		 */
		setCrossOrigin: function ( crossOrigin ) {
M
r74  
Mr.doob 已提交
357

M
r93  
Mr.doob 已提交
358 359
			this.crossOrigin = crossOrigin;
			return this;
M
r74  
Mr.doob 已提交
360

M
r93  
Mr.doob 已提交
361
		},
M
r74  
Mr.doob 已提交
362

M
r93  
Mr.doob 已提交
363 364
		/**
		 * @param {Object} data - parsed PMD/PMX data
M
r99  
Mr.doob 已提交
365
		 * @param {string} resourcePath
M
r93  
Mr.doob 已提交
366 367 368 369
		 * @param {function} onProgress
		 * @param {function} onError
		 * @return {THREE.SkinnedMesh}
		 */
M
r99  
Mr.doob 已提交
370
		build: function ( data, resourcePath, onProgress, onError ) {
M
r74  
Mr.doob 已提交
371

M
r93  
Mr.doob 已提交
372 373
			var geometry = this.geometryBuilder.build( data );
			var material = this.materialBuilder
M
r96  
Mr.doob 已提交
374
				.setCrossOrigin( this.crossOrigin )
M
r99  
Mr.doob 已提交
375
				.setResourcePath( resourcePath )
M
r96  
Mr.doob 已提交
376
				.build( data, geometry, onProgress, onError );
M
r74  
Mr.doob 已提交
377

M
r93  
Mr.doob 已提交
378
			var mesh = new THREE.SkinnedMesh( geometry, material );
M
r74  
Mr.doob 已提交
379

M
r99  
Mr.doob 已提交
380 381 382
			var skeleton = new THREE.Skeleton( initBones( mesh ) );
			mesh.bind( skeleton );

M
r93  
Mr.doob 已提交
383
			// console.log( mesh ); // for console debug
M
r74  
Mr.doob 已提交
384

M
r93  
Mr.doob 已提交
385
			return mesh;
M
r74  
Mr.doob 已提交
386 387 388 389 390

		}

	};

M
r99  
Mr.doob 已提交
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
	// TODO: Try to remove this function

	function initBones( mesh ) {

		var geometry = mesh.geometry;

		var bones = [], bone, gbone;
		var i, il;

		if ( geometry && geometry.bones !== undefined ) {

			// first, create array of 'Bone' objects from geometry data

			for ( i = 0, il = geometry.bones.length; i < il; i ++ ) {

				gbone = geometry.bones[ i ];

				// create new 'Bone' object

				bone = new THREE.Bone();
				bones.push( bone );

				// apply values

				bone.name = gbone.name;
				bone.position.fromArray( gbone.pos );
				bone.quaternion.fromArray( gbone.rotq );
				if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl );

			}

			// second, create bone hierarchy

			for ( i = 0, il = geometry.bones.length; i < il; i ++ ) {

				gbone = geometry.bones[ i ];

				if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) {

					// subsequent bones in the hierarchy

					bones[ gbone.parent ].add( bones[ i ] );

				} else {

					// topmost bone, immediate child of the skinned mesh

					mesh.add( bones[ i ] );

				}

			}

		}

		// now the bones are part of the scene graph and children of the skinned mesh.
		// let's update the corresponding matrices

		mesh.updateMatrixWorld( true );

		return bones;

	}

M
r93  
Mr.doob 已提交
455
	//
M
r74  
Mr.doob 已提交
456

M
r93  
Mr.doob 已提交
457
	function GeometryBuilder() {
M
r74  
Mr.doob 已提交
458

M
r93  
Mr.doob 已提交
459
	}
M
r74  
Mr.doob 已提交
460

M
r93  
Mr.doob 已提交
461
	GeometryBuilder.prototype = {
M
r74  
Mr.doob 已提交
462

M
r93  
Mr.doob 已提交
463
		constructor: GeometryBuilder,
M
r74  
Mr.doob 已提交
464

M
r93  
Mr.doob 已提交
465 466 467 468 469
		/**
		 * @param {Object} data - parsed PMD/PMX data
		 * @return {THREE.BufferGeometry}
		 */
		build: function ( data ) {
M
r83  
Mr.doob 已提交
470

M
r93  
Mr.doob 已提交
471 472 473 474
			// for geometry
			var positions = [];
			var uvs = [];
			var normals = [];
M
r74  
Mr.doob 已提交
475

M
r93  
Mr.doob 已提交
476
			var indices = [];
M
r74  
Mr.doob 已提交
477

M
r93  
Mr.doob 已提交
478
			var groups = [];
M
r74  
Mr.doob 已提交
479

M
r93  
Mr.doob 已提交
480 481 482
			var bones = [];
			var skinIndices = [];
			var skinWeights = [];
M
r74  
Mr.doob 已提交
483

M
r93  
Mr.doob 已提交
484 485
			var morphTargets = [];
			var morphPositions = [];
M
r74  
Mr.doob 已提交
486

M
r93  
Mr.doob 已提交
487 488
			var iks = [];
			var grants = [];
M
r74  
Mr.doob 已提交
489

M
r93  
Mr.doob 已提交
490 491
			var rigidBodies = [];
			var constraints = [];
M
r74  
Mr.doob 已提交
492

M
r93  
Mr.doob 已提交
493 494 495
			// for work
			var offset = 0;
			var boneTypeTable = {};
M
r74  
Mr.doob 已提交
496

M
r93  
Mr.doob 已提交
497
			// positions, normals, uvs, skinIndices, skinWeights
M
r74  
Mr.doob 已提交
498

M
r93  
Mr.doob 已提交
499
			for ( var i = 0; i < data.metadata.vertexCount; i ++ ) {
M
r74  
Mr.doob 已提交
500

M
r93  
Mr.doob 已提交
501
				var v = data.vertices[ i ];
M
r74  
Mr.doob 已提交
502

M
r93  
Mr.doob 已提交
503
				for ( var j = 0, jl = v.position.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
504

M
r93  
Mr.doob 已提交
505
					positions.push( v.position[ j ] );
M
r74  
Mr.doob 已提交
506

M
r83  
Mr.doob 已提交
507
				}
M
r74  
Mr.doob 已提交
508

M
r93  
Mr.doob 已提交
509
				for ( var j = 0, jl = v.normal.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
510

M
r93  
Mr.doob 已提交
511
					normals.push( v.normal[ j ] );
M
r74  
Mr.doob 已提交
512

M
r83  
Mr.doob 已提交
513
				}
M
r74  
Mr.doob 已提交
514

M
r93  
Mr.doob 已提交
515
				for ( var j = 0, jl = v.uv.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
516

M
r93  
Mr.doob 已提交
517
					uvs.push( v.uv[ j ] );
M
r74  
Mr.doob 已提交
518

M
r93  
Mr.doob 已提交
519
				}
M
r74  
Mr.doob 已提交
520

M
r93  
Mr.doob 已提交
521
				for ( var j = 0; j < 4; j ++ ) {
M
r74  
Mr.doob 已提交
522

M
r93  
Mr.doob 已提交
523
					skinIndices.push( v.skinIndices.length - 1 >= j ? v.skinIndices[ j ] : 0.0 );
M
r74  
Mr.doob 已提交
524

M
r93  
Mr.doob 已提交
525
				}
M
r74  
Mr.doob 已提交
526

M
r93  
Mr.doob 已提交
527
				for ( var j = 0; j < 4; j ++ ) {
M
r74  
Mr.doob 已提交
528

M
r93  
Mr.doob 已提交
529
					skinWeights.push( v.skinWeights.length - 1 >= j ? v.skinWeights[ j ] : 0.0 );
M
r74  
Mr.doob 已提交
530

M
r83  
Mr.doob 已提交
531
				}
M
r74  
Mr.doob 已提交
532

M
r83  
Mr.doob 已提交
533
			}
M
r74  
Mr.doob 已提交
534

M
r93  
Mr.doob 已提交
535
			// indices
M
r74  
Mr.doob 已提交
536

M
r93  
Mr.doob 已提交
537
			for ( var i = 0; i < data.metadata.faceCount; i ++ ) {
M
r74  
Mr.doob 已提交
538

M
r93  
Mr.doob 已提交
539
				var face = data.faces[ i ];
M
r74  
Mr.doob 已提交
540

M
r93  
Mr.doob 已提交
541
				for ( var j = 0, jl = face.indices.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
542

M
r93  
Mr.doob 已提交
543
					indices.push( face.indices[ j ] );
M
r74  
Mr.doob 已提交
544

M
r93  
Mr.doob 已提交
545
				}
M
r74  
Mr.doob 已提交
546

M
r83  
Mr.doob 已提交
547
			}
M
r74  
Mr.doob 已提交
548

M
r93  
Mr.doob 已提交
549
			// groups
M
r74  
Mr.doob 已提交
550

M
r93  
Mr.doob 已提交
551
			for ( var i = 0; i < data.metadata.materialCount; i ++ ) {
M
r74  
Mr.doob 已提交
552

M
r93  
Mr.doob 已提交
553
				var material = data.materials[ i ];
M
r74  
Mr.doob 已提交
554

M
r93  
Mr.doob 已提交
555 556 557 558
				groups.push( {
					offset: offset * 3,
					count: material.faceCount * 3
				} );
M
r74  
Mr.doob 已提交
559

M
r93  
Mr.doob 已提交
560
				offset += material.faceCount;
M
r74  
Mr.doob 已提交
561

M
r93  
Mr.doob 已提交
562
			}
M
r74  
Mr.doob 已提交
563

M
r93  
Mr.doob 已提交
564
			// bones
M
r74  
Mr.doob 已提交
565

M
r93  
Mr.doob 已提交
566
			for ( var i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
M
r74  
Mr.doob 已提交
567

M
r93  
Mr.doob 已提交
568 569
				var body = data.rigidBodies[ i ];
				var value = boneTypeTable[ body.boneIndex ];
M
r74  
Mr.doob 已提交
570

M
r93  
Mr.doob 已提交
571 572
				// keeps greater number if already value is set without any special reasons
				value = value === undefined ? body.type : Math.max( body.type, value );
M
r74  
Mr.doob 已提交
573

M
r93  
Mr.doob 已提交
574
				boneTypeTable[ body.boneIndex ] = value;
M
r74  
Mr.doob 已提交
575

M
r83  
Mr.doob 已提交
576
			}
M
r74  
Mr.doob 已提交
577

M
r93  
Mr.doob 已提交
578
			for ( var i = 0; i < data.metadata.boneCount; i ++ ) {
M
r74  
Mr.doob 已提交
579

M
r93  
Mr.doob 已提交
580
				var boneData = data.bones[ i ];
M
r74  
Mr.doob 已提交
581

M
r93  
Mr.doob 已提交
582 583 584 585 586 587 588 589
				var bone = {
					parent: boneData.parentIndex,
					name: boneData.name,
					pos: boneData.position.slice( 0, 3 ),
					rotq: [ 0, 0, 0, 1 ],
					scl: [ 1, 1, 1 ],
					rigidBodyType: boneTypeTable[ i ] !== undefined ? boneTypeTable[ i ] : - 1
				};
M
r74  
Mr.doob 已提交
590

M
r93  
Mr.doob 已提交
591
				if ( bone.parent !== - 1 ) {
M
r74  
Mr.doob 已提交
592

M
r93  
Mr.doob 已提交
593 594 595
					bone.pos[ 0 ] -= data.bones[ bone.parent ].position[ 0 ];
					bone.pos[ 1 ] -= data.bones[ bone.parent ].position[ 1 ];
					bone.pos[ 2 ] -= data.bones[ bone.parent ].position[ 2 ];
M
r74  
Mr.doob 已提交
596

M
r93  
Mr.doob 已提交
597
				}
M
r74  
Mr.doob 已提交
598

M
r93  
Mr.doob 已提交
599
				bones.push( bone );
M
r74  
Mr.doob 已提交
600

M
r83  
Mr.doob 已提交
601
			}
M
r74  
Mr.doob 已提交
602

M
r93  
Mr.doob 已提交
603
			// iks
M
r74  
Mr.doob 已提交
604

M
r93  
Mr.doob 已提交
605 606
			// TODO: remove duplicated codes between PMD and PMX
			if ( data.metadata.format === 'pmd' ) {
M
r74  
Mr.doob 已提交
607

M
r93  
Mr.doob 已提交
608
				for ( var i = 0; i < data.metadata.ikCount; i ++ ) {
M
r74  
Mr.doob 已提交
609

M
r93  
Mr.doob 已提交
610
					var ik = data.iks[ i ];
M
r74  
Mr.doob 已提交
611

M
r93  
Mr.doob 已提交
612 613 614 615 616 617 618
					var param = {
						target: ik.target,
						effector: ik.effector,
						iteration: ik.iteration,
						maxAngle: ik.maxAngle * 4,
						links: []
					};
M
r74  
Mr.doob 已提交
619

M
r93  
Mr.doob 已提交
620
					for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
621

M
r93  
Mr.doob 已提交
622 623 624
						var link = {};
						link.index = ik.links[ j ].index;
						link.enabled = true;
M
r74  
Mr.doob 已提交
625

M
r93  
Mr.doob 已提交
626
						if ( data.bones[ link.index ].name.indexOf( 'ひざ' ) >= 0 ) {
M
r74  
Mr.doob 已提交
627

M
r93  
Mr.doob 已提交
628
							link.limitation = new THREE.Vector3( 1.0, 0.0, 0.0 );
M
r74  
Mr.doob 已提交
629

M
r83  
Mr.doob 已提交
630
						}
M
r74  
Mr.doob 已提交
631

M
r93  
Mr.doob 已提交
632
						param.links.push( link );
M
r74  
Mr.doob 已提交
633

M
r93  
Mr.doob 已提交
634
					}
M
r74  
Mr.doob 已提交
635

M
r93  
Mr.doob 已提交
636
					iks.push( param );
M
r74  
Mr.doob 已提交
637

M
r93  
Mr.doob 已提交
638
				}
M
r74  
Mr.doob 已提交
639

M
r93  
Mr.doob 已提交
640
			} else {
M
r74  
Mr.doob 已提交
641

M
r93  
Mr.doob 已提交
642
				for ( var i = 0; i < data.metadata.boneCount; i ++ ) {
M
r74  
Mr.doob 已提交
643

M
r93  
Mr.doob 已提交
644
					var ik = data.bones[ i ].ik;
M
r74  
Mr.doob 已提交
645

M
r93  
Mr.doob 已提交
646
					if ( ik === undefined ) continue;
M
r74  
Mr.doob 已提交
647

M
r93  
Mr.doob 已提交
648 649 650 651 652 653 654
					var param = {
						target: i,
						effector: ik.effector,
						iteration: ik.iteration,
						maxAngle: ik.maxAngle,
						links: []
					};
M
r74  
Mr.doob 已提交
655

M
r93  
Mr.doob 已提交
656
					for ( var j = 0, jl = ik.links.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
657

M
r93  
Mr.doob 已提交
658 659 660
						var link = {};
						link.index = ik.links[ j ].index;
						link.enabled = true;
M
r74  
Mr.doob 已提交
661

M
r93  
Mr.doob 已提交
662
						if ( ik.links[ j ].angleLimitation === 1 ) {
M
r74  
Mr.doob 已提交
663

M
r93  
Mr.doob 已提交
664 665
							// Revert if rotationMin/Max doesn't work well
							// link.limitation = new THREE.Vector3( 1.0, 0.0, 0.0 );
M
r74  
Mr.doob 已提交
666

M
r93  
Mr.doob 已提交
667 668
							var rotationMin = ik.links[ j ].lowerLimitationAngle;
							var rotationMax = ik.links[ j ].upperLimitationAngle;
M
r74  
Mr.doob 已提交
669

M
r93  
Mr.doob 已提交
670 671
							// Convert Left to Right coordinate by myself because
							// MMDParser doesn't convert. It's a MMDParser's bug
M
r74  
Mr.doob 已提交
672

M
r93  
Mr.doob 已提交
673 674 675 676 677 678
							var tmp1 = - rotationMax[ 0 ];
							var tmp2 = - rotationMax[ 1 ];
							rotationMax[ 0 ] = - rotationMin[ 0 ];
							rotationMax[ 1 ] = - rotationMin[ 1 ];
							rotationMin[ 0 ] = tmp1;
							rotationMin[ 1 ] = tmp2;
M
r74  
Mr.doob 已提交
679

M
r93  
Mr.doob 已提交
680 681
							link.rotationMin = new THREE.Vector3().fromArray( rotationMin );
							link.rotationMax = new THREE.Vector3().fromArray( rotationMax );
M
r74  
Mr.doob 已提交
682

M
r93  
Mr.doob 已提交
683
						}
M
r74  
Mr.doob 已提交
684

M
r93  
Mr.doob 已提交
685
						param.links.push( link );
M
r74  
Mr.doob 已提交
686

M
r83  
Mr.doob 已提交
687
					}
M
r74  
Mr.doob 已提交
688

M
r93  
Mr.doob 已提交
689
					iks.push( param );
M
r74  
Mr.doob 已提交
690

M
r83  
Mr.doob 已提交
691
				}
M
r74  
Mr.doob 已提交
692

M
r93  
Mr.doob 已提交
693
			}
M
r74  
Mr.doob 已提交
694

M
r93  
Mr.doob 已提交
695
			// grants
M
r74  
Mr.doob 已提交
696

M
r93  
Mr.doob 已提交
697
			if ( data.metadata.format === 'pmx' ) {
M
r74  
Mr.doob 已提交
698

M
r93  
Mr.doob 已提交
699
				for ( var i = 0; i < data.metadata.boneCount; i ++ ) {
M
r74  
Mr.doob 已提交
700

M
r93  
Mr.doob 已提交
701 702
					var boneData = data.bones[ i ];
					var grant = boneData.grant;
M
r74  
Mr.doob 已提交
703

M
r93  
Mr.doob 已提交
704
					if ( grant === undefined ) continue;
M
r74  
Mr.doob 已提交
705

M
r93  
Mr.doob 已提交
706 707 708 709 710 711 712 713 714
					var param = {
						index: i,
						parentIndex: grant.parentIndex,
						ratio: grant.ratio,
						isLocal: grant.isLocal,
						affectRotation: grant.affectRotation,
						affectPosition: grant.affectPosition,
						transformationClass: boneData.transformationClass
					};
M
r74  
Mr.doob 已提交
715

M
r93  
Mr.doob 已提交
716
					grants.push( param );
M
r74  
Mr.doob 已提交
717

M
r93  
Mr.doob 已提交
718
				}
M
r74  
Mr.doob 已提交
719

M
r93  
Mr.doob 已提交
720
				grants.sort( function ( a, b ) {
M
r74  
Mr.doob 已提交
721

M
r93  
Mr.doob 已提交
722
					return a.transformationClass - b.transformationClass;
M
r74  
Mr.doob 已提交
723

M
r93  
Mr.doob 已提交
724
				} );
M
r74  
Mr.doob 已提交
725

M
r93  
Mr.doob 已提交
726
			}
M
r74  
Mr.doob 已提交
727

M
r93  
Mr.doob 已提交
728
			// morph
M
r74  
Mr.doob 已提交
729

M
r93  
Mr.doob 已提交
730
			function updateAttributes( attribute, morph, ratio ) {
M
r74  
Mr.doob 已提交
731

M
r93  
Mr.doob 已提交
732
				for ( var i = 0; i < morph.elementCount; i ++ ) {
M
r74  
Mr.doob 已提交
733

M
r93  
Mr.doob 已提交
734
					var element = morph.elements[ i ];
M
r74  
Mr.doob 已提交
735

M
r93  
Mr.doob 已提交
736
					var index;
M
r74  
Mr.doob 已提交
737

M
r93  
Mr.doob 已提交
738
					if ( data.metadata.format === 'pmd' ) {
M
r74  
Mr.doob 已提交
739

M
r93  
Mr.doob 已提交
740
						index = data.morphs[ 0 ].elements[ element.index ].index;
M
r74  
Mr.doob 已提交
741

M
r93  
Mr.doob 已提交
742
					} else {
M
r74  
Mr.doob 已提交
743

M
r93  
Mr.doob 已提交
744
						index = element.index;
M
r74  
Mr.doob 已提交
745

M
r93  
Mr.doob 已提交
746
					}
M
r74  
Mr.doob 已提交
747

M
r93  
Mr.doob 已提交
748 749 750
					attribute.array[ index * 3 + 0 ] += element.position[ 0 ] * ratio;
					attribute.array[ index * 3 + 1 ] += element.position[ 1 ] * ratio;
					attribute.array[ index * 3 + 2 ] += element.position[ 2 ] * ratio;
M
r74  
Mr.doob 已提交
751

M
r93  
Mr.doob 已提交
752
				}
M
r74  
Mr.doob 已提交
753

M
r93  
Mr.doob 已提交
754
			}
M
r74  
Mr.doob 已提交
755

M
r93  
Mr.doob 已提交
756
			for ( var i = 0; i < data.metadata.morphCount; i ++ ) {
M
r74  
Mr.doob 已提交
757

M
r93  
Mr.doob 已提交
758 759
				var morph = data.morphs[ i ];
				var params = { name: morph.name };
M
r74  
Mr.doob 已提交
760

M
r93  
Mr.doob 已提交
761 762
				var attribute = new THREE.Float32BufferAttribute( data.metadata.vertexCount * 3, 3 );
				attribute.name = morph.name;
M
r74  
Mr.doob 已提交
763

M
r93  
Mr.doob 已提交
764
				for ( var j = 0; j < data.metadata.vertexCount * 3; j ++ ) {
M
r74  
Mr.doob 已提交
765

M
r93  
Mr.doob 已提交
766
					attribute.array[ j ] = positions[ j ];
M
r74  
Mr.doob 已提交
767

M
r93  
Mr.doob 已提交
768
				}
M
r74  
Mr.doob 已提交
769

M
r93  
Mr.doob 已提交
770
				if ( data.metadata.format === 'pmd' ) {
M
r74  
Mr.doob 已提交
771

M
r93  
Mr.doob 已提交
772
					if ( i !== 0 ) {
M
r74  
Mr.doob 已提交
773

M
r93  
Mr.doob 已提交
774
						updateAttributes( attribute, morph, 1.0 );
M
r86  
Mr.doob 已提交
775

M
r93  
Mr.doob 已提交
776
					}
M
r74  
Mr.doob 已提交
777

M
r93  
Mr.doob 已提交
778
				} else {
M
r74  
Mr.doob 已提交
779

M
r93  
Mr.doob 已提交
780
					if ( morph.type === 0 ) { // group
M
r74  
Mr.doob 已提交
781

M
r93  
Mr.doob 已提交
782
						for ( var j = 0; j < morph.elementCount; j ++ ) {
M
r74  
Mr.doob 已提交
783

M
r93  
Mr.doob 已提交
784 785
							var morph2 = data.morphs[ morph.elements[ j ].index ];
							var ratio = morph.elements[ j ].ratio;
M
r74  
Mr.doob 已提交
786

M
r93  
Mr.doob 已提交
787
							if ( morph2.type === 1 ) {
M
r74  
Mr.doob 已提交
788

M
r93  
Mr.doob 已提交
789
								updateAttributes( attribute, morph2, ratio );
M
r74  
Mr.doob 已提交
790

M
r93  
Mr.doob 已提交
791
							} else {
M
r74  
Mr.doob 已提交
792

M
r93  
Mr.doob 已提交
793
								// TODO: implement
M
r74  
Mr.doob 已提交
794

M
r93  
Mr.doob 已提交
795
							}
M
r74  
Mr.doob 已提交
796

M
r93  
Mr.doob 已提交
797
						}
M
r74  
Mr.doob 已提交
798

M
r93  
Mr.doob 已提交
799
					} else if ( morph.type === 1 ) { // vertex
M
r74  
Mr.doob 已提交
800

M
r93  
Mr.doob 已提交
801
						updateAttributes( attribute, morph, 1.0 );
M
r74  
Mr.doob 已提交
802

M
r93  
Mr.doob 已提交
803
					} else if ( morph.type === 2 ) { // bone
M
r74  
Mr.doob 已提交
804

M
r93  
Mr.doob 已提交
805
						// TODO: implement
M
r74  
Mr.doob 已提交
806

M
r93  
Mr.doob 已提交
807
					} else if ( morph.type === 3 ) { // uv
M
r74  
Mr.doob 已提交
808

M
r93  
Mr.doob 已提交
809
						// TODO: implement
M
r74  
Mr.doob 已提交
810

M
r93  
Mr.doob 已提交
811
					} else if ( morph.type === 4 ) { // additional uv1
M
r83  
Mr.doob 已提交
812

M
r93  
Mr.doob 已提交
813
						// TODO: implement
M
r74  
Mr.doob 已提交
814

M
r93  
Mr.doob 已提交
815
					} else if ( morph.type === 5 ) { // additional uv2
M
r74  
Mr.doob 已提交
816

M
r93  
Mr.doob 已提交
817
						// TODO: implement
M
r74  
Mr.doob 已提交
818

M
r93  
Mr.doob 已提交
819
					} else if ( morph.type === 6 ) { // additional uv3
M
r74  
Mr.doob 已提交
820

M
r93  
Mr.doob 已提交
821
						// TODO: implement
M
r74  
Mr.doob 已提交
822

M
r93  
Mr.doob 已提交
823
					} else if ( morph.type === 7 ) { // additional uv4
M
r74  
Mr.doob 已提交
824

M
r93  
Mr.doob 已提交
825
						// TODO: implement
M
r74  
Mr.doob 已提交
826

M
r93  
Mr.doob 已提交
827
					} else if ( morph.type === 8 ) { // material
M
r74  
Mr.doob 已提交
828

M
r93  
Mr.doob 已提交
829
						// TODO: implement
M
r74  
Mr.doob 已提交
830

M
r93  
Mr.doob 已提交
831
					}
M
r74  
Mr.doob 已提交
832

M
r93  
Mr.doob 已提交
833
				}
M
r74  
Mr.doob 已提交
834

M
r93  
Mr.doob 已提交
835 836
				morphTargets.push( params );
				morphPositions.push( attribute );
M
r74  
Mr.doob 已提交
837

M
r93  
Mr.doob 已提交
838
			}
M
r74  
Mr.doob 已提交
839

M
r93  
Mr.doob 已提交
840
			// rigid bodies from rigidBodies field.
M
r74  
Mr.doob 已提交
841

M
r93  
Mr.doob 已提交
842
			for ( var i = 0; i < data.metadata.rigidBodyCount; i ++ ) {
M
r74  
Mr.doob 已提交
843

M
r93  
Mr.doob 已提交
844 845
				var rigidBody = data.rigidBodies[ i ];
				var params = {};
M
r74  
Mr.doob 已提交
846

M
r93  
Mr.doob 已提交
847
				for ( var key in rigidBody ) {
M
r74  
Mr.doob 已提交
848

M
r93  
Mr.doob 已提交
849
					params[ key ] = rigidBody[ key ];
M
r74  
Mr.doob 已提交
850

M
r93  
Mr.doob 已提交
851
				}
M
r74  
Mr.doob 已提交
852

M
r93  
Mr.doob 已提交
853 854 855 856 857 858
				/*
				 * RigidBody position parameter in PMX seems global position
				 * while the one in PMD seems offset from corresponding bone.
				 * So unify being offset.
				 */
				if ( data.metadata.format === 'pmx' ) {
M
r74  
Mr.doob 已提交
859

M
r93  
Mr.doob 已提交
860
					if ( params.boneIndex !== - 1 ) {
M
r74  
Mr.doob 已提交
861

M
r93  
Mr.doob 已提交
862 863 864 865
						var bone = data.bones[ params.boneIndex ];
						params.position[ 0 ] -= bone.position[ 0 ];
						params.position[ 1 ] -= bone.position[ 1 ];
						params.position[ 2 ] -= bone.position[ 2 ];
M
r74  
Mr.doob 已提交
866

M
r93  
Mr.doob 已提交
867
					}
M
r74  
Mr.doob 已提交
868

M
r93  
Mr.doob 已提交
869
				}
M
r74  
Mr.doob 已提交
870

M
r93  
Mr.doob 已提交
871
				rigidBodies.push( params );
M
r74  
Mr.doob 已提交
872

M
r83  
Mr.doob 已提交
873
			}
M
r74  
Mr.doob 已提交
874

M
r93  
Mr.doob 已提交
875
			// constraints from constraints field.
M
r74  
Mr.doob 已提交
876

M
r93  
Mr.doob 已提交
877
			for ( var i = 0; i < data.metadata.constraintCount; i ++ ) {
M
r74  
Mr.doob 已提交
878

M
r93  
Mr.doob 已提交
879 880
				var constraint = data.constraints[ i ];
				var params = {};
M
r74  
Mr.doob 已提交
881

M
r93  
Mr.doob 已提交
882
				for ( var key in constraint ) {
M
r74  
Mr.doob 已提交
883

M
r93  
Mr.doob 已提交
884
					params[ key ] = constraint[ key ];
M
r74  
Mr.doob 已提交
885

M
r93  
Mr.doob 已提交
886
				}
M
r74  
Mr.doob 已提交
887

M
r93  
Mr.doob 已提交
888 889
				var bodyA = rigidBodies[ params.rigidBodyIndex1 ];
				var bodyB = rigidBodies[ params.rigidBodyIndex2 ];
M
r74  
Mr.doob 已提交
890

M
r93  
Mr.doob 已提交
891 892
				// Refer to http://www20.atpages.jp/katwat/wp/?p=4135
				if ( bodyA.type !== 0 && bodyB.type === 2 ) {
M
r74  
Mr.doob 已提交
893

M
r93  
Mr.doob 已提交
894 895
					if ( bodyA.boneIndex !== - 1 && bodyB.boneIndex !== - 1 &&
					     data.bones[ bodyB.boneIndex ].parentIndex === bodyA.boneIndex ) {
M
r74  
Mr.doob 已提交
896

M
r93  
Mr.doob 已提交
897
						bodyB.type = 1;
M
r74  
Mr.doob 已提交
898

M
r93  
Mr.doob 已提交
899
					}
M
r74  
Mr.doob 已提交
900

M
r93  
Mr.doob 已提交
901
				}
M
r74  
Mr.doob 已提交
902

M
r93  
Mr.doob 已提交
903
				constraints.push( params );
M
r74  
Mr.doob 已提交
904

M
r93  
Mr.doob 已提交
905
			}
M
r74  
Mr.doob 已提交
906

M
r93  
Mr.doob 已提交
907
			// build BufferGeometry.
M
r74  
Mr.doob 已提交
908

M
r93  
Mr.doob 已提交
909
			var geometry = new THREE.BufferGeometry();
M
r74  
Mr.doob 已提交
910

M
r110  
Mr.doob 已提交
911 912 913 914 915
			geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
			geometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
			geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
			geometry.setAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 ) );
			geometry.setAttribute( 'skinWeight', new THREE.Float32BufferAttribute( skinWeights, 4 ) );
M
r93  
Mr.doob 已提交
916
			geometry.setIndex( indices );
M
r74  
Mr.doob 已提交
917

M
r93  
Mr.doob 已提交
918
			for ( var i = 0, il = groups.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
919

M
r93  
Mr.doob 已提交
920
				geometry.addGroup( groups[ i ].offset, groups[ i ].count, i );
M
r74  
Mr.doob 已提交
921

M
r93  
Mr.doob 已提交
922
			}
M
r74  
Mr.doob 已提交
923

M
r93  
Mr.doob 已提交
924
			geometry.bones = bones;
M
r74  
Mr.doob 已提交
925

M
r93  
Mr.doob 已提交
926 927
			geometry.morphTargets = morphTargets;
			geometry.morphAttributes.position = morphPositions;
M
r111  
Mr.doob 已提交
928
			geometry.morphTargetsRelative = false;
M
r74  
Mr.doob 已提交
929

M
r93  
Mr.doob 已提交
930 931 932 933 934 935 936 937
			geometry.userData.MMD = {
				bones: bones,
				iks: iks,
				grants: grants,
				rigidBodies: rigidBodies,
				constraints: constraints,
				format: data.metadata.format
			};
M
r74  
Mr.doob 已提交
938

M
r93  
Mr.doob 已提交
939
			geometry.computeBoundingSphere();
M
r74  
Mr.doob 已提交
940

M
r93  
Mr.doob 已提交
941
			return geometry;
M
r74  
Mr.doob 已提交
942

M
r93  
Mr.doob 已提交
943
		}
M
r74  
Mr.doob 已提交
944

M
r93  
Mr.doob 已提交
945
	};
M
r74  
Mr.doob 已提交
946

M
r93  
Mr.doob 已提交
947
	//
M
r74  
Mr.doob 已提交
948

M
r93  
Mr.doob 已提交
949 950 951 952
	/**
	 * @param {THREE.LoadingManager} manager
	 */
	function MaterialBuilder( manager ) {
M
r74  
Mr.doob 已提交
953

M
r93  
Mr.doob 已提交
954
		this.manager = manager;
M
r74  
Mr.doob 已提交
955

M
r93  
Mr.doob 已提交
956 957
		this.textureLoader = new THREE.TextureLoader( this.manager );
		this.tgaLoader = null; // lazy generation
M
r74  
Mr.doob 已提交
958

M
r93  
Mr.doob 已提交
959
	}
M
r74  
Mr.doob 已提交
960

M
r93  
Mr.doob 已提交
961
	MaterialBuilder.prototype = {
M
r74  
Mr.doob 已提交
962

M
r93  
Mr.doob 已提交
963
		constructor: MaterialBuilder,
M
r74  
Mr.doob 已提交
964

M
r94  
Mr.doob 已提交
965
		crossOrigin: 'anonymous',
M
r74  
Mr.doob 已提交
966

M
r99  
Mr.doob 已提交
967
		resourcePath: undefined,
M
r74  
Mr.doob 已提交
968

M
r93  
Mr.doob 已提交
969 970 971 972 973
		/**
		 * @param {string} crossOrigin
		 * @return {MaterialBuilder}
		 */
		setCrossOrigin: function ( crossOrigin ) {
M
r74  
Mr.doob 已提交
974

M
r93  
Mr.doob 已提交
975 976
			this.crossOrigin = crossOrigin;
			return this;
M
r74  
Mr.doob 已提交
977

M
r93  
Mr.doob 已提交
978
		},
M
r74  
Mr.doob 已提交
979

M
r93  
Mr.doob 已提交
980
		/**
M
r99  
Mr.doob 已提交
981
		 * @param {string} resourcePath
M
r93  
Mr.doob 已提交
982 983
		 * @return {MaterialBuilder}
		 */
M
r99  
Mr.doob 已提交
984
		setResourcePath: function ( resourcePath ) {
M
r74  
Mr.doob 已提交
985

M
r99  
Mr.doob 已提交
986
			this.resourcePath = resourcePath;
M
r93  
Mr.doob 已提交
987
			return this;
M
r74  
Mr.doob 已提交
988

M
r93  
Mr.doob 已提交
989
		},
M
r74  
Mr.doob 已提交
990

M
r93  
Mr.doob 已提交
991 992 993 994 995 996 997
		/**
		 * @param {Object} data - parsed PMD/PMX data
		 * @param {THREE.BufferGeometry} geometry - some properties are dependend on geometry
		 * @param {function} onProgress
		 * @param {function} onError
		 * @return {Array<THREE.MeshToonMaterial>}
		 */
M
r106  
Mr.doob 已提交
998
		build: function ( data, geometry /*, onProgress, onError */ ) {
M
r74  
Mr.doob 已提交
999

M
r93  
Mr.doob 已提交
1000
			var materials = [];
M
r74  
Mr.doob 已提交
1001

M
r93  
Mr.doob 已提交
1002
			var textures = {};
M
r74  
Mr.doob 已提交
1003

M
r93  
Mr.doob 已提交
1004
			this.textureLoader.setCrossOrigin( this.crossOrigin );
M
r74  
Mr.doob 已提交
1005

M
r93  
Mr.doob 已提交
1006
			// materials
M
r74  
Mr.doob 已提交
1007

M
r93  
Mr.doob 已提交
1008
			for ( var i = 0; i < data.metadata.materialCount; i ++ ) {
M
r74  
Mr.doob 已提交
1009

M
r93  
Mr.doob 已提交
1010
				var material = data.materials[ i ];
M
r74  
Mr.doob 已提交
1011

M
r93  
Mr.doob 已提交
1012
				var params = { userData: {} };
M
r74  
Mr.doob 已提交
1013

M
r93  
Mr.doob 已提交
1014
				if ( material.name !== undefined ) params.name = material.name;
M
r74  
Mr.doob 已提交
1015

M
r93  
Mr.doob 已提交
1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
				/*
				 * Color
				 *
				 * MMD         MeshToonMaterial
				 * diffuse  -  color
				 * ambient  -  emissive * a
				 *               (a = 1.0 without map texture or 0.2 with map texture)
				 *
				 * MeshToonMaterial doesn't have ambient. Set it to emissive instead.
				 * It'll be too bright if material has map texture so using coef 0.2.
				 */
				params.color = new THREE.Color().fromArray( material.diffuse );
				params.opacity = material.diffuse[ 3 ];
				params.emissive = new THREE.Color().fromArray( material.ambient );
				params.transparent = params.opacity !== 1.0;
M
r74  
Mr.doob 已提交
1031

M
r94  
Mr.doob 已提交
1032
				//
M
r74  
Mr.doob 已提交
1033

M
r93  
Mr.doob 已提交
1034 1035 1036
				params.skinning = geometry.bones.length > 0 ? true : false;
				params.morphTargets = geometry.morphTargets.length > 0 ? true : false;
				params.fog = true;
M
r74  
Mr.doob 已提交
1037

M
r93  
Mr.doob 已提交
1038
				// blend
M
r74  
Mr.doob 已提交
1039

M
r93  
Mr.doob 已提交
1040 1041 1042 1043 1044
				params.blending = THREE.CustomBlending;
				params.blendSrc = THREE.SrcAlphaFactor;
				params.blendDst = THREE.OneMinusSrcAlphaFactor;
				params.blendSrcAlpha = THREE.SrcAlphaFactor;
				params.blendDstAlpha = THREE.DstAlphaFactor;
M
r74  
Mr.doob 已提交
1045

M
r93  
Mr.doob 已提交
1046
				// side
M
r74  
Mr.doob 已提交
1047

M
r93  
Mr.doob 已提交
1048
				if ( data.metadata.format === 'pmx' && ( material.flag & 0x1 ) === 1 ) {
M
r74  
Mr.doob 已提交
1049

M
r93  
Mr.doob 已提交
1050
					params.side = THREE.DoubleSide;
M
r74  
Mr.doob 已提交
1051

M
r93  
Mr.doob 已提交
1052
				} else {
M
r74  
Mr.doob 已提交
1053

M
r93  
Mr.doob 已提交
1054
					params.side = params.opacity === 1.0 ? THREE.FrontSide : THREE.DoubleSide;
M
r74  
Mr.doob 已提交
1055

M
r93  
Mr.doob 已提交
1056
				}
M
r74  
Mr.doob 已提交
1057

M
r93  
Mr.doob 已提交
1058
				if ( data.metadata.format === 'pmd' ) {
M
r74  
Mr.doob 已提交
1059

M
r93  
Mr.doob 已提交
1060
					// map, envMap
M
r74  
Mr.doob 已提交
1061

M
r93  
Mr.doob 已提交
1062
					if ( material.fileName ) {
M
r74  
Mr.doob 已提交
1063

M
r93  
Mr.doob 已提交
1064 1065
						var fileName = material.fileName;
						var fileNames = fileName.split( '*' );
M
r74  
Mr.doob 已提交
1066

M
r93  
Mr.doob 已提交
1067 1068
						// fileNames[ 0 ]: mapFileName
						// fileNames[ 1 ]: envMapFileName( optional )
M
r74  
Mr.doob 已提交
1069

M
r93  
Mr.doob 已提交
1070
						params.map = this._loadTexture( fileNames[ 0 ], textures );
M
r83  
Mr.doob 已提交
1071

M
r93  
Mr.doob 已提交
1072
						if ( fileNames.length > 1 ) {
M
r74  
Mr.doob 已提交
1073

M
r93  
Mr.doob 已提交
1074
							var extension = fileNames[ 1 ].slice( - 4 ).toLowerCase();
M
r74  
Mr.doob 已提交
1075

M
r93  
Mr.doob 已提交
1076 1077
							params.envMap = this._loadTexture(
								fileNames[ 1 ],
M
r118  
Mr.doob 已提交
1078
								textures
M
r93  
Mr.doob 已提交
1079
							);
M
r74  
Mr.doob 已提交
1080

M
r93  
Mr.doob 已提交
1081 1082 1083
							params.combine = extension === '.sph'
								? THREE.MultiplyOperation
								: THREE.AddOperation;
M
r74  
Mr.doob 已提交
1084

M
r93  
Mr.doob 已提交
1085
						}
M
r74  
Mr.doob 已提交
1086

M
r93  
Mr.doob 已提交
1087
					}
M
r74  
Mr.doob 已提交
1088

M
r93  
Mr.doob 已提交
1089
					// gradientMap
M
r77  
Mr.doob 已提交
1090

M
r93  
Mr.doob 已提交
1091 1092 1093
					var toonFileName = ( material.toonIndex === - 1 )
						? 'toon00.bmp'
						: data.toonTextures[ material.toonIndex ].fileName;
M
r77  
Mr.doob 已提交
1094

M
r93  
Mr.doob 已提交
1095 1096 1097 1098 1099 1100 1101 1102
					params.gradientMap = this._loadTexture(
						toonFileName,
						textures,
						{
							isToonTexture: true,
							isDefaultToonTexture: this._isDefaultToonTexture( toonFileName )
						}
					);
M
r77  
Mr.doob 已提交
1103

M
r93  
Mr.doob 已提交
1104
					// parameters for OutlineEffect
M
r74  
Mr.doob 已提交
1105

M
r93  
Mr.doob 已提交
1106 1107 1108 1109 1110 1111
					params.userData.outlineParameters = {
						thickness: material.edgeFlag === 1 ? 0.003 : 0.0,
						color: [ 0, 0, 0 ],
						alpha: 1.0,
						visible: material.edgeFlag === 1
					};
M
r74  
Mr.doob 已提交
1112

M
r93  
Mr.doob 已提交
1113
				} else {
M
r74  
Mr.doob 已提交
1114

M
r93  
Mr.doob 已提交
1115
					// map
M
r74  
Mr.doob 已提交
1116

M
r93  
Mr.doob 已提交
1117
					if ( material.textureIndex !== - 1 ) {
M
r74  
Mr.doob 已提交
1118

M
r93  
Mr.doob 已提交
1119
						params.map = this._loadTexture( data.textures[ material.textureIndex ], textures );
M
r74  
Mr.doob 已提交
1120

M
r93  
Mr.doob 已提交
1121
					}
M
r74  
Mr.doob 已提交
1122

M
r93  
Mr.doob 已提交
1123
					// envMap TODO: support m.envFlag === 3
M
r74  
Mr.doob 已提交
1124

M
r93  
Mr.doob 已提交
1125
					if ( material.envTextureIndex !== - 1 && ( material.envFlag === 1 || material.envFlag == 2 ) ) {
M
r74  
Mr.doob 已提交
1126

M
r93  
Mr.doob 已提交
1127 1128
						params.envMap = this._loadTexture(
							data.textures[ material.envTextureIndex ],
M
r118  
Mr.doob 已提交
1129
							textures
M
r93  
Mr.doob 已提交
1130
						);
M
r74  
Mr.doob 已提交
1131

M
r93  
Mr.doob 已提交
1132 1133 1134
						params.combine = material.envFlag === 1
							? THREE.MultiplyOperation
							: THREE.AddOperation;
M
r74  
Mr.doob 已提交
1135

M
r93  
Mr.doob 已提交
1136
					}
M
r74  
Mr.doob 已提交
1137

M
r93  
Mr.doob 已提交
1138
					// gradientMap
M
r74  
Mr.doob 已提交
1139

M
r93  
Mr.doob 已提交
1140
					var toonFileName, isDefaultToon;
M
r74  
Mr.doob 已提交
1141

M
r93  
Mr.doob 已提交
1142
					if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) {
M
r74  
Mr.doob 已提交
1143

M
r93  
Mr.doob 已提交
1144 1145
						toonFileName = 'toon' + ( '0' + ( material.toonIndex + 1 ) ).slice( - 2 ) + '.bmp';
						isDefaultToon = true;
M
r74  
Mr.doob 已提交
1146

M
r93  
Mr.doob 已提交
1147
					} else {
M
r74  
Mr.doob 已提交
1148

M
r93  
Mr.doob 已提交
1149 1150
						toonFileName = data.textures[ material.toonIndex ];
						isDefaultToon = false;
M
r74  
Mr.doob 已提交
1151

M
r93  
Mr.doob 已提交
1152
					}
M
r74  
Mr.doob 已提交
1153

M
r93  
Mr.doob 已提交
1154 1155 1156 1157 1158 1159 1160 1161
					params.gradientMap = this._loadTexture(
						toonFileName,
						textures,
						{
							isToonTexture: true,
							isDefaultToonTexture: isDefaultToon
						}
					);
M
r74  
Mr.doob 已提交
1162

M
r93  
Mr.doob 已提交
1163 1164
					// parameters for OutlineEffect
					params.userData.outlineParameters = {
M
r96  
Mr.doob 已提交
1165
						thickness: material.edgeSize / 300, // TODO: better calculation?
M
r93  
Mr.doob 已提交
1166 1167 1168 1169
						color: material.edgeColor.slice( 0, 3 ),
						alpha: material.edgeColor[ 3 ],
						visible: ( material.flag & 0x10 ) !== 0 && material.edgeSize > 0.0
					};
M
r74  
Mr.doob 已提交
1170

M
r93  
Mr.doob 已提交
1171
				}
M
r74  
Mr.doob 已提交
1172

M
r93  
Mr.doob 已提交
1173
				if ( params.map !== undefined ) {
M
r74  
Mr.doob 已提交
1174

M
r93  
Mr.doob 已提交
1175
					if ( ! params.transparent ) {
M
r74  
Mr.doob 已提交
1176

M
r93  
Mr.doob 已提交
1177
						this._checkImageTransparency( params.map, geometry, i );
M
r74  
Mr.doob 已提交
1178

M
r93  
Mr.doob 已提交
1179
					}
M
r74  
Mr.doob 已提交
1180

M
r93  
Mr.doob 已提交
1181
					params.emissive.multiplyScalar( 0.2 );
M
r74  
Mr.doob 已提交
1182

M
r93  
Mr.doob 已提交
1183
				}
M
r74  
Mr.doob 已提交
1184

M
r93  
Mr.doob 已提交
1185
				materials.push( new THREE.MeshToonMaterial( params ) );
M
r74  
Mr.doob 已提交
1186

M
r93  
Mr.doob 已提交
1187
			}
M
r74  
Mr.doob 已提交
1188

M
r93  
Mr.doob 已提交
1189
			if ( data.metadata.format === 'pmx' ) {
M
r74  
Mr.doob 已提交
1190

M
r93  
Mr.doob 已提交
1191
				// set transparent true if alpha morph is defined.
M
r74  
Mr.doob 已提交
1192

M
r93  
Mr.doob 已提交
1193
				function checkAlphaMorph( elements, materials ) {
M
r74  
Mr.doob 已提交
1194

M
r93  
Mr.doob 已提交
1195
					for ( var i = 0, il = elements.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1196

M
r93  
Mr.doob 已提交
1197
						var element = elements[ i ];
M
r74  
Mr.doob 已提交
1198

M
r93  
Mr.doob 已提交
1199
						if ( element.index === - 1 ) continue;
M
r74  
Mr.doob 已提交
1200

M
r93  
Mr.doob 已提交
1201
						var material = materials[ element.index ];
M
r74  
Mr.doob 已提交
1202

M
r93  
Mr.doob 已提交
1203
						if ( material.opacity !== element.diffuse[ 3 ] ) {
M
r74  
Mr.doob 已提交
1204

M
r93  
Mr.doob 已提交
1205
							material.transparent = true;
M
r74  
Mr.doob 已提交
1206

M
r93  
Mr.doob 已提交
1207
						}
M
r74  
Mr.doob 已提交
1208

M
r93  
Mr.doob 已提交
1209
					}
M
r74  
Mr.doob 已提交
1210

M
r93  
Mr.doob 已提交
1211
				}
M
r74  
Mr.doob 已提交
1212

M
r93  
Mr.doob 已提交
1213
				for ( var i = 0, il = data.morphs.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1214

M
r93  
Mr.doob 已提交
1215 1216
					var morph = data.morphs[ i ];
					var elements = morph.elements;
M
r74  
Mr.doob 已提交
1217

M
r93  
Mr.doob 已提交
1218
					if ( morph.type === 0 ) {
M
r74  
Mr.doob 已提交
1219

M
r93  
Mr.doob 已提交
1220
						for ( var j = 0, jl = elements.length; j < jl; j ++ ) {
M
r74  
Mr.doob 已提交
1221

M
r93  
Mr.doob 已提交
1222
							var morph2 = data.morphs[ elements[ j ].index ];
M
r76  
Mr.doob 已提交
1223

M
r93  
Mr.doob 已提交
1224
							if ( morph2.type !== 8 ) continue;
M
r76  
Mr.doob 已提交
1225

M
r93  
Mr.doob 已提交
1226
							checkAlphaMorph( morph2.elements, materials );
M
r76  
Mr.doob 已提交
1227

M
r93  
Mr.doob 已提交
1228
						}
M
r76  
Mr.doob 已提交
1229

M
r93  
Mr.doob 已提交
1230
					} else if ( morph.type === 8 ) {
M
r76  
Mr.doob 已提交
1231

M
r93  
Mr.doob 已提交
1232
						checkAlphaMorph( elements, materials );
M
r76  
Mr.doob 已提交
1233

M
r93  
Mr.doob 已提交
1234
					}
M
r76  
Mr.doob 已提交
1235

M
r93  
Mr.doob 已提交
1236
				}
M
r76  
Mr.doob 已提交
1237

M
r93  
Mr.doob 已提交
1238
			}
M
r76  
Mr.doob 已提交
1239

M
r93  
Mr.doob 已提交
1240
			return materials;
M
r76  
Mr.doob 已提交
1241

M
r93  
Mr.doob 已提交
1242
		},
M
r76  
Mr.doob 已提交
1243

M
r93  
Mr.doob 已提交
1244
		// private methods
M
r76  
Mr.doob 已提交
1245

M
r93  
Mr.doob 已提交
1246
		_getTGALoader: function () {
M
r76  
Mr.doob 已提交
1247

M
r93  
Mr.doob 已提交
1248
			if ( this.tgaLoader === null ) {
M
r76  
Mr.doob 已提交
1249

M
r93  
Mr.doob 已提交
1250
				if ( THREE.TGALoader === undefined ) {
M
r76  
Mr.doob 已提交
1251

M
r93  
Mr.doob 已提交
1252
					throw new Error( 'THREE.MMDLoader: Import THREE.TGALoader' );
M
r76  
Mr.doob 已提交
1253

M
r93  
Mr.doob 已提交
1254
				}
M
r76  
Mr.doob 已提交
1255

M
r93  
Mr.doob 已提交
1256
				this.tgaLoader = new THREE.TGALoader( this.manager );
M
r76  
Mr.doob 已提交
1257

M
r93  
Mr.doob 已提交
1258
			}
M
r76  
Mr.doob 已提交
1259

M
r93  
Mr.doob 已提交
1260
			return this.tgaLoader;
M
r76  
Mr.doob 已提交
1261

M
r93  
Mr.doob 已提交
1262
		},
M
r76  
Mr.doob 已提交
1263

M
r93  
Mr.doob 已提交
1264
		_isDefaultToonTexture: function ( name ) {
M
r76  
Mr.doob 已提交
1265

M
r93  
Mr.doob 已提交
1266
			if ( name.length !== 10 ) return false;
M
r76  
Mr.doob 已提交
1267

M
r93  
Mr.doob 已提交
1268
			return /toon(10|0[0-9])\.bmp/.test( name );
M
r76  
Mr.doob 已提交
1269

M
r93  
Mr.doob 已提交
1270
		},
M
r76  
Mr.doob 已提交
1271

M
r93  
Mr.doob 已提交
1272
		_loadTexture: function ( filePath, textures, params, onProgress, onError ) {
M
r76  
Mr.doob 已提交
1273

M
r93  
Mr.doob 已提交
1274
			params = params || {};
M
r82  
Mr.doob 已提交
1275

M
r93  
Mr.doob 已提交
1276
			var scope = this;
M
r74  
Mr.doob 已提交
1277

M
r93  
Mr.doob 已提交
1278
			var fullPath;
M
r74  
Mr.doob 已提交
1279

M
r93  
Mr.doob 已提交
1280
			if ( params.isDefaultToonTexture === true ) {
M
r83  
Mr.doob 已提交
1281

M
r93  
Mr.doob 已提交
1282
				var index;
M
r74  
Mr.doob 已提交
1283

M
r93  
Mr.doob 已提交
1284
				try {
M
r74  
Mr.doob 已提交
1285

M
r115  
Mr.doob 已提交
1286
					index = parseInt( filePath.match( /toon([0-9]{2})\.bmp$/ )[ 1 ] );
M
r74  
Mr.doob 已提交
1287

M
r93  
Mr.doob 已提交
1288
				} catch ( e ) {
M
r74  
Mr.doob 已提交
1289

M
r93  
Mr.doob 已提交
1290 1291
					console.warn( 'THREE.MMDLoader: ' + filePath + ' seems like a '
						+ 'not right default texture path. Using toon00.bmp instead.' );
M
r74  
Mr.doob 已提交
1292

M
r93  
Mr.doob 已提交
1293
					index = 0;
M
r80  
Mr.doob 已提交
1294

M
r93  
Mr.doob 已提交
1295
				}
M
r80  
Mr.doob 已提交
1296

M
r93  
Mr.doob 已提交
1297
				fullPath = DEFAULT_TOON_TEXTURES[ index ];
M
r80  
Mr.doob 已提交
1298

M
r93  
Mr.doob 已提交
1299
			} else {
M
r83  
Mr.doob 已提交
1300

M
r99  
Mr.doob 已提交
1301
				fullPath = this.resourcePath + filePath;
M
r74  
Mr.doob 已提交
1302

M
r93  
Mr.doob 已提交
1303
			}
M
r74  
Mr.doob 已提交
1304

M
r93  
Mr.doob 已提交
1305
			if ( textures[ fullPath ] !== undefined ) return textures[ fullPath ];
M
r74  
Mr.doob 已提交
1306

M
r109  
Mr.doob 已提交
1307
			var loader = this.manager.getHandler( fullPath );
M
r74  
Mr.doob 已提交
1308

M
r93  
Mr.doob 已提交
1309
			if ( loader === null ) {
M
r74  
Mr.doob 已提交
1310

M
r93  
Mr.doob 已提交
1311 1312 1313
				loader = ( filePath.slice( - 4 ).toLowerCase() === '.tga' )
					? this._getTGALoader()
					: this.textureLoader;
M
r74  
Mr.doob 已提交
1314

M
r93  
Mr.doob 已提交
1315
			}
M
r74  
Mr.doob 已提交
1316

M
r93  
Mr.doob 已提交
1317
			var texture = loader.load( fullPath, function ( t ) {
M
r74  
Mr.doob 已提交
1318

M
r93  
Mr.doob 已提交
1319 1320 1321 1322
				// MMD toon texture is Axis-Y oriented
				// but Three.js gradient map is Axis-X oriented.
				// So here replaces the toon texture image with the rotated one.
				if ( params.isToonTexture === true ) {
M
r74  
Mr.doob 已提交
1323

M
r93  
Mr.doob 已提交
1324
					t.image = scope._getRotatedImage( t.image );
M
r74  
Mr.doob 已提交
1325

M
r104  
Mr.doob 已提交
1326 1327 1328
					t.magFilter = THREE.NearestFilter;
					t.minFilter = THREE.NearestFilter;

M
r93  
Mr.doob 已提交
1329
				}
M
r74  
Mr.doob 已提交
1330

M
r93  
Mr.doob 已提交
1331 1332 1333
				t.flipY = false;
				t.wrapS = THREE.RepeatWrapping;
				t.wrapT = THREE.RepeatWrapping;
M
r74  
Mr.doob 已提交
1334

M
r93  
Mr.doob 已提交
1335
				for ( var i = 0; i < texture.readyCallbacks.length; i ++ ) {
M
r74  
Mr.doob 已提交
1336

M
r93  
Mr.doob 已提交
1337
					texture.readyCallbacks[ i ]( texture );
M
r74  
Mr.doob 已提交
1338

M
r93  
Mr.doob 已提交
1339
				}
M
r74  
Mr.doob 已提交
1340

M
r93  
Mr.doob 已提交
1341
				delete texture.readyCallbacks;
M
r83  
Mr.doob 已提交
1342

M
r93  
Mr.doob 已提交
1343
			}, onProgress, onError );
M
r83  
Mr.doob 已提交
1344

M
r93  
Mr.doob 已提交
1345
			texture.readyCallbacks = [];
M
r83  
Mr.doob 已提交
1346

M
r93  
Mr.doob 已提交
1347
			textures[ fullPath ] = texture;
M
r83  
Mr.doob 已提交
1348

M
r93  
Mr.doob 已提交
1349
			return texture;
M
r83  
Mr.doob 已提交
1350

M
r93  
Mr.doob 已提交
1351
		},
M
r83  
Mr.doob 已提交
1352

M
r93  
Mr.doob 已提交
1353
		_getRotatedImage: function ( image ) {
M
r83  
Mr.doob 已提交
1354

M
r93  
Mr.doob 已提交
1355 1356
			var canvas = document.createElement( 'canvas' );
			var context = canvas.getContext( '2d' );
M
r83  
Mr.doob 已提交
1357

M
r93  
Mr.doob 已提交
1358 1359
			var width = image.width;
			var height = image.height;
M
r83  
Mr.doob 已提交
1360

M
r93  
Mr.doob 已提交
1361 1362
			canvas.width = width;
			canvas.height = height;
M
r83  
Mr.doob 已提交
1363

M
r93  
Mr.doob 已提交
1364 1365 1366 1367 1368
			context.clearRect( 0, 0, width, height );
			context.translate( width / 2.0, height / 2.0 );
			context.rotate( 0.5 * Math.PI ); // 90.0 * Math.PI / 180.0
			context.translate( - width / 2.0, - height / 2.0 );
			context.drawImage( image, 0, 0 );
M
r83  
Mr.doob 已提交
1369

M
r93  
Mr.doob 已提交
1370
			return context.getImageData( 0, 0, width, height );
M
r83  
Mr.doob 已提交
1371

M
r93  
Mr.doob 已提交
1372
		},
M
r83  
Mr.doob 已提交
1373

M
r93  
Mr.doob 已提交
1374 1375
		// Check if the partial image area used by the texture is transparent.
		_checkImageTransparency: function ( map, geometry, groupIndex ) {
M
r83  
Mr.doob 已提交
1376

M
r93  
Mr.doob 已提交
1377
			map.readyCallbacks.push( function ( texture ) {
M
r83  
Mr.doob 已提交
1378

M
r93  
Mr.doob 已提交
1379 1380
				// Is there any efficient ways?
				function createImageData( image ) {
M
r83  
Mr.doob 已提交
1381

M
r93  
Mr.doob 已提交
1382 1383 1384
					var canvas = document.createElement( 'canvas' );
					canvas.width = image.width;
					canvas.height = image.height;
M
r83  
Mr.doob 已提交
1385

M
r93  
Mr.doob 已提交
1386 1387
					var context = canvas.getContext( '2d' );
					context.drawImage( image, 0, 0 );
M
r88  
Mr.doob 已提交
1388

M
r93  
Mr.doob 已提交
1389
					return context.getImageData( 0, 0, canvas.width, canvas.height );
M
r83  
Mr.doob 已提交
1390

M
r93  
Mr.doob 已提交
1391
				}
M
r83  
Mr.doob 已提交
1392

M
r93  
Mr.doob 已提交
1393
				function detectImageTransparency( image, uvs, indices ) {
M
r83  
Mr.doob 已提交
1394

M
r93  
Mr.doob 已提交
1395 1396 1397 1398
					var width = image.width;
					var height = image.height;
					var data = image.data;
					var threshold = 253;
M
r83  
Mr.doob 已提交
1399

M
r93  
Mr.doob 已提交
1400
					if ( data.length / ( width * height ) !== 4 ) return false;
M
r83  
Mr.doob 已提交
1401

M
r93  
Mr.doob 已提交
1402
					for ( var i = 0; i < indices.length; i += 3 ) {
M
r83  
Mr.doob 已提交
1403

M
r93  
Mr.doob 已提交
1404
						var centerUV = { x: 0.0, y: 0.0 };
M
r83  
Mr.doob 已提交
1405

M
r93  
Mr.doob 已提交
1406
						for ( var j = 0; j < 3; j ++ ) {
M
r83  
Mr.doob 已提交
1407

M
r93  
Mr.doob 已提交
1408 1409
							var index = indices[ i * 3 + j ];
							var uv = { x: uvs[ index * 2 + 0 ], y: uvs[ index * 2 + 1 ] };
M
r83  
Mr.doob 已提交
1410

M
r93  
Mr.doob 已提交
1411
							if ( getAlphaByUv( image, uv ) < threshold ) return true;
M
r83  
Mr.doob 已提交
1412

M
r93  
Mr.doob 已提交
1413 1414
							centerUV.x += uv.x;
							centerUV.y += uv.y;
M
r83  
Mr.doob 已提交
1415

M
r93  
Mr.doob 已提交
1416
						}
M
r83  
Mr.doob 已提交
1417

M
r93  
Mr.doob 已提交
1418 1419
						centerUV.x /= 3;
						centerUV.y /= 3;
M
r83  
Mr.doob 已提交
1420

M
r93  
Mr.doob 已提交
1421
						if ( getAlphaByUv( image, centerUV ) < threshold ) return true;
M
r83  
Mr.doob 已提交
1422

M
r93  
Mr.doob 已提交
1423
					}
M
r83  
Mr.doob 已提交
1424

M
r93  
Mr.doob 已提交
1425
					return false;
M
r83  
Mr.doob 已提交
1426

M
r93  
Mr.doob 已提交
1427
				}
M
r83  
Mr.doob 已提交
1428

M
r93  
Mr.doob 已提交
1429 1430 1431 1432 1433 1434 1435 1436
				/*
				 * This method expects
				 *   texture.flipY = false
				 *   texture.wrapS = THREE.RepeatWrapping
				 *   texture.wrapT = THREE.RepeatWrapping
				 * TODO: more precise
				 */
				function getAlphaByUv( image, uv ) {
M
r83  
Mr.doob 已提交
1437

M
r93  
Mr.doob 已提交
1438 1439
					var width = image.width;
					var height = image.height;
M
r83  
Mr.doob 已提交
1440

M
r93  
Mr.doob 已提交
1441 1442
					var x = Math.round( uv.x * width ) % width;
					var y = Math.round( uv.y * height ) % height;
M
r83  
Mr.doob 已提交
1443

M
r93  
Mr.doob 已提交
1444 1445
					if ( x < 0 ) x += width;
					if ( y < 0 ) y += height;
M
r83  
Mr.doob 已提交
1446

M
r93  
Mr.doob 已提交
1447
					var index = y * width + x;
M
r83  
Mr.doob 已提交
1448

M
r93  
Mr.doob 已提交
1449
					return image.data[ index * 4 + 3 ];
M
r83  
Mr.doob 已提交
1450 1451 1452

				}

M
r93  
Mr.doob 已提交
1453 1454 1455
				var imageData = texture.image.data !== undefined
					? texture.image
					: createImageData( texture.image );
M
r83  
Mr.doob 已提交
1456

M
r93  
Mr.doob 已提交
1457
				var group = geometry.groups[ groupIndex ];
M
r74  
Mr.doob 已提交
1458

M
r93  
Mr.doob 已提交
1459 1460 1461 1462
				if ( detectImageTransparency(
					imageData,
					geometry.attributes.uv.array,
					geometry.index.array.slice( group.start, group.start + group.count ) ) ) {
M
r74  
Mr.doob 已提交
1463

M
r93  
Mr.doob 已提交
1464
					map.transparent = true;
M
r74  
Mr.doob 已提交
1465

M
r93  
Mr.doob 已提交
1466
				}
M
r74  
Mr.doob 已提交
1467

M
r93  
Mr.doob 已提交
1468
			} );
M
r74  
Mr.doob 已提交
1469 1470 1471

		}

M
r93  
Mr.doob 已提交
1472 1473 1474
	};

	//
M
r74  
Mr.doob 已提交
1475

M
r93  
Mr.doob 已提交
1476
	function AnimationBuilder() {
M
r74  
Mr.doob 已提交
1477

M
r93  
Mr.doob 已提交
1478
	}
M
r74  
Mr.doob 已提交
1479

M
r93  
Mr.doob 已提交
1480
	AnimationBuilder.prototype = {
M
r74  
Mr.doob 已提交
1481

M
r93  
Mr.doob 已提交
1482
		constructor: AnimationBuilder,
M
r83  
Mr.doob 已提交
1483

M
r93  
Mr.doob 已提交
1484 1485 1486 1487 1488 1489
		/**
		 * @param {Object} vmd - parsed VMD data
		 * @param {THREE.SkinnedMesh} mesh - tracks will be fitting to mesh
		 * @return {THREE.AnimationClip}
		 */
		build: function ( vmd, mesh ) {
M
r83  
Mr.doob 已提交
1490

M
r93  
Mr.doob 已提交
1491
			// combine skeletal and morph animations
M
r83  
Mr.doob 已提交
1492

M
r93  
Mr.doob 已提交
1493 1494
			var tracks = this.buildSkeletalAnimation( vmd, mesh ).tracks;
			var tracks2 = this.buildMorphAnimation( vmd, mesh ).tracks;
M
r83  
Mr.doob 已提交
1495

M
r93  
Mr.doob 已提交
1496
			for ( var i = 0, il = tracks2.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1497

M
r93  
Mr.doob 已提交
1498
				tracks.push( tracks2[ i ] );
M
r74  
Mr.doob 已提交
1499

M
r93  
Mr.doob 已提交
1500
			}
M
r74  
Mr.doob 已提交
1501

M
r93  
Mr.doob 已提交
1502
			return new THREE.AnimationClip( '', - 1, tracks );
M
r74  
Mr.doob 已提交
1503

M
r93  
Mr.doob 已提交
1504
		},
M
r74  
Mr.doob 已提交
1505

M
r93  
Mr.doob 已提交
1506 1507 1508 1509 1510 1511
		/**
		 * @param {Object} vmd - parsed VMD data
		 * @param {THREE.SkinnedMesh} mesh - tracks will be fitting to mesh
		 * @return {THREE.AnimationClip}
		 */
		buildSkeletalAnimation: function ( vmd, mesh ) {
M
r74  
Mr.doob 已提交
1512

M
r93  
Mr.doob 已提交
1513
			function pushInterpolation( array, interpolation, index ) {
M
r74  
Mr.doob 已提交
1514

M
r93  
Mr.doob 已提交
1515 1516 1517 1518
				array.push( interpolation[ index + 0 ] / 127 ); // x1
				array.push( interpolation[ index + 8 ] / 127 ); // x2
				array.push( interpolation[ index + 4 ] / 127 ); // y1
				array.push( interpolation[ index + 12 ] / 127 ); // y2
M
r76  
Mr.doob 已提交
1519

M
r96  
Mr.doob 已提交
1520
			}
M
r76  
Mr.doob 已提交
1521

M
r93  
Mr.doob 已提交
1522
			var tracks = [];
M
r76  
Mr.doob 已提交
1523

M
r93  
Mr.doob 已提交
1524 1525 1526
			var motions = {};
			var bones = mesh.skeleton.bones;
			var boneNameDictionary = {};
M
r76  
Mr.doob 已提交
1527

M
r93  
Mr.doob 已提交
1528
			for ( var i = 0, il = bones.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1529

M
r93  
Mr.doob 已提交
1530
				boneNameDictionary[ bones[ i ].name ] = true;
M
Mr.doob 已提交
1531 1532

			}
M
r74  
Mr.doob 已提交
1533

M
r93  
Mr.doob 已提交
1534
			for ( var i = 0; i < vmd.metadata.motionCount; i ++ ) {
M
r74  
Mr.doob 已提交
1535

M
r93  
Mr.doob 已提交
1536 1537
				var motion = vmd.motions[ i ];
				var boneName = motion.boneName;
M
r74  
Mr.doob 已提交
1538

M
r93  
Mr.doob 已提交
1539
				if ( boneNameDictionary[ boneName ] === undefined ) continue;
M
r74  
Mr.doob 已提交
1540

M
r93  
Mr.doob 已提交
1541 1542
				motions[ boneName ] = motions[ boneName ] || [];
				motions[ boneName ].push( motion );
M
r74  
Mr.doob 已提交
1543 1544 1545

			}

M
r93  
Mr.doob 已提交
1546
			for ( var key in motions ) {
M
r74  
Mr.doob 已提交
1547

M
r93  
Mr.doob 已提交
1548
				var array = motions[ key ];
M
r74  
Mr.doob 已提交
1549

M
r93  
Mr.doob 已提交
1550
				array.sort( function ( a, b ) {
M
r74  
Mr.doob 已提交
1551

M
r93  
Mr.doob 已提交
1552
					return a.frameNum - b.frameNum;
M
r74  
Mr.doob 已提交
1553

M
r93  
Mr.doob 已提交
1554
				} );
M
r74  
Mr.doob 已提交
1555

M
r93  
Mr.doob 已提交
1556 1557 1558 1559 1560
				var times = [];
				var positions = [];
				var rotations = [];
				var pInterpolations = [];
				var rInterpolations = [];
M
r74  
Mr.doob 已提交
1561

M
r93  
Mr.doob 已提交
1562
				var basePosition = mesh.skeleton.getBoneByName( key ).position.toArray();
M
r74  
Mr.doob 已提交
1563

M
r93  
Mr.doob 已提交
1564
				for ( var i = 0, il = array.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1565

M
r93  
Mr.doob 已提交
1566 1567 1568 1569
					var time = array[ i ].frameNum / 30;
					var position = array[ i ].position;
					var rotation = array[ i ].rotation;
					var interpolation = array[ i ].interpolation;
M
r74  
Mr.doob 已提交
1570

M
r93  
Mr.doob 已提交
1571
					times.push( time );
M
r74  
Mr.doob 已提交
1572

M
r93  
Mr.doob 已提交
1573 1574 1575
					for ( var j = 0; j < 3; j ++ ) positions.push( basePosition[ j ] + position[ j ] );
					for ( var j = 0; j < 4; j ++ ) rotations.push( rotation[ j ] );
					for ( var j = 0; j < 3; j ++ ) pushInterpolation( pInterpolations, interpolation, j );
M
r74  
Mr.doob 已提交
1576

M
r93  
Mr.doob 已提交
1577
					pushInterpolation( rInterpolations, interpolation, 3 );
M
r74  
Mr.doob 已提交
1578

M
r93  
Mr.doob 已提交
1579
				}
M
r74  
Mr.doob 已提交
1580

M
r93  
Mr.doob 已提交
1581
				var targetName = '.bones[' + key + ']';
M
r74  
Mr.doob 已提交
1582

M
r93  
Mr.doob 已提交
1583 1584
				tracks.push( this._createTrack( targetName + '.position', THREE.VectorKeyframeTrack, times, positions, pInterpolations ) );
				tracks.push( this._createTrack( targetName + '.quaternion', THREE.QuaternionKeyframeTrack, times, rotations, rInterpolations ) );
M
r74  
Mr.doob 已提交
1585 1586 1587

			}

M
r93  
Mr.doob 已提交
1588
			return new THREE.AnimationClip( '', - 1, tracks );
M
r74  
Mr.doob 已提交
1589

M
r93  
Mr.doob 已提交
1590
		},
M
r74  
Mr.doob 已提交
1591

M
r93  
Mr.doob 已提交
1592 1593 1594 1595 1596 1597
		/**
		 * @param {Object} vmd - parsed VMD data
		 * @param {THREE.SkinnedMesh} mesh - tracks will be fitting to mesh
		 * @return {THREE.AnimationClip}
		 */
		buildMorphAnimation: function ( vmd, mesh ) {
M
r74  
Mr.doob 已提交
1598

M
r93  
Mr.doob 已提交
1599
			var tracks = [];
M
r74  
Mr.doob 已提交
1600

M
r93  
Mr.doob 已提交
1601 1602
			var morphs = {};
			var morphTargetDictionary = mesh.morphTargetDictionary;
M
r74  
Mr.doob 已提交
1603

M
r93  
Mr.doob 已提交
1604
			for ( var i = 0; i < vmd.metadata.morphCount; i ++ ) {
M
r74  
Mr.doob 已提交
1605

M
r93  
Mr.doob 已提交
1606 1607
				var morph = vmd.morphs[ i ];
				var morphName = morph.morphName;
M
r74  
Mr.doob 已提交
1608

M
r93  
Mr.doob 已提交
1609
				if ( morphTargetDictionary[ morphName ] === undefined ) continue;
M
r74  
Mr.doob 已提交
1610

M
r93  
Mr.doob 已提交
1611 1612
				morphs[ morphName ] = morphs[ morphName ] || [];
				morphs[ morphName ].push( morph );
M
r74  
Mr.doob 已提交
1613

M
r93  
Mr.doob 已提交
1614
			}
M
r74  
Mr.doob 已提交
1615

M
r93  
Mr.doob 已提交
1616
			for ( var key in morphs ) {
M
r74  
Mr.doob 已提交
1617

M
r93  
Mr.doob 已提交
1618
				var array = morphs[ key ];
M
r74  
Mr.doob 已提交
1619

M
r93  
Mr.doob 已提交
1620
				array.sort( function ( a, b ) {
M
r74  
Mr.doob 已提交
1621

M
r93  
Mr.doob 已提交
1622
					return a.frameNum - b.frameNum;
M
r74  
Mr.doob 已提交
1623

M
r93  
Mr.doob 已提交
1624
				} );
M
r74  
Mr.doob 已提交
1625

M
r93  
Mr.doob 已提交
1626 1627
				var times = [];
				var values = [];
M
r74  
Mr.doob 已提交
1628

M
r93  
Mr.doob 已提交
1629
				for ( var i = 0, il = array.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1630

M
r93  
Mr.doob 已提交
1631 1632
					times.push( array[ i ].frameNum / 30 );
					values.push( array[ i ].weight );
M
r74  
Mr.doob 已提交
1633

M
r93  
Mr.doob 已提交
1634
				}
M
r74  
Mr.doob 已提交
1635

M
r93  
Mr.doob 已提交
1636
				tracks.push( new THREE.NumberKeyframeTrack( '.morphTargetInfluences[' + morphTargetDictionary[ key ] + ']', times, values ) );
M
r74  
Mr.doob 已提交
1637 1638 1639

			}

M
r93  
Mr.doob 已提交
1640
			return new THREE.AnimationClip( '', - 1, tracks );
M
r74  
Mr.doob 已提交
1641

M
r93  
Mr.doob 已提交
1642
		},
M
r74  
Mr.doob 已提交
1643

M
r93  
Mr.doob 已提交
1644 1645 1646 1647 1648
		/**
		 * @param {Object} vmd - parsed VMD data
		 * @return {THREE.AnimationClip}
		 */
		buildCameraAnimation: function ( vmd ) {
M
r74  
Mr.doob 已提交
1649

M
r93  
Mr.doob 已提交
1650
			function pushVector3( array, vec ) {
M
r74  
Mr.doob 已提交
1651

M
r93  
Mr.doob 已提交
1652 1653 1654
				array.push( vec.x );
				array.push( vec.y );
				array.push( vec.z );
M
r74  
Mr.doob 已提交
1655 1656 1657

			}

M
r93  
Mr.doob 已提交
1658
			function pushQuaternion( array, q ) {
M
r74  
Mr.doob 已提交
1659

M
r93  
Mr.doob 已提交
1660 1661 1662 1663
				array.push( q.x );
				array.push( q.y );
				array.push( q.z );
				array.push( q.w );
M
r74  
Mr.doob 已提交
1664

M
r93  
Mr.doob 已提交
1665
			}
M
r74  
Mr.doob 已提交
1666

M
r93  
Mr.doob 已提交
1667
			function pushInterpolation( array, interpolation, index ) {
M
r74  
Mr.doob 已提交
1668

M
r93  
Mr.doob 已提交
1669 1670 1671 1672
				array.push( interpolation[ index * 4 + 0 ] / 127 ); // x1
				array.push( interpolation[ index * 4 + 1 ] / 127 ); // x2
				array.push( interpolation[ index * 4 + 2 ] / 127 ); // y1
				array.push( interpolation[ index * 4 + 3 ] / 127 ); // y2
M
r74  
Mr.doob 已提交
1673

M
r96  
Mr.doob 已提交
1674
			}
M
r74  
Mr.doob 已提交
1675

M
r93  
Mr.doob 已提交
1676
			var tracks = [];
M
r74  
Mr.doob 已提交
1677

M
r93  
Mr.doob 已提交
1678
			var cameras = vmd.cameras === undefined ? [] : vmd.cameras.slice();
M
r74  
Mr.doob 已提交
1679

M
r93  
Mr.doob 已提交
1680
			cameras.sort( function ( a, b ) {
M
r74  
Mr.doob 已提交
1681

M
r93  
Mr.doob 已提交
1682
				return a.frameNum - b.frameNum;
M
r74  
Mr.doob 已提交
1683

M
r93  
Mr.doob 已提交
1684
			} );
M
r74  
Mr.doob 已提交
1685

M
r93  
Mr.doob 已提交
1686 1687 1688 1689 1690
			var times = [];
			var centers = [];
			var quaternions = [];
			var positions = [];
			var fovs = [];
M
r74  
Mr.doob 已提交
1691

M
r93  
Mr.doob 已提交
1692 1693 1694 1695
			var cInterpolations = [];
			var qInterpolations = [];
			var pInterpolations = [];
			var fInterpolations = [];
M
r74  
Mr.doob 已提交
1696

M
r93  
Mr.doob 已提交
1697 1698 1699 1700
			var quaternion = new THREE.Quaternion();
			var euler = new THREE.Euler();
			var position = new THREE.Vector3();
			var center = new THREE.Vector3();
M
r74  
Mr.doob 已提交
1701

M
r93  
Mr.doob 已提交
1702
			for ( var i = 0, il = cameras.length; i < il; i ++ ) {
M
r74  
Mr.doob 已提交
1703

M
r93  
Mr.doob 已提交
1704
				var motion = cameras[ i ];
M
r83  
Mr.doob 已提交
1705

M
r93  
Mr.doob 已提交
1706 1707 1708 1709 1710 1711
				var time = motion.frameNum / 30;
				var pos = motion.position;
				var rot = motion.rotation;
				var distance = motion.distance;
				var fov = motion.fov;
				var interpolation = motion.interpolation;
M
r74  
Mr.doob 已提交
1712

M
r93  
Mr.doob 已提交
1713
				times.push( time );
M
r74  
Mr.doob 已提交
1714

M
r93  
Mr.doob 已提交
1715 1716
				position.set( 0, 0, - distance );
				center.set( pos[ 0 ], pos[ 1 ], pos[ 2 ] );
M
r74  
Mr.doob 已提交
1717

M
r93  
Mr.doob 已提交
1718 1719
				euler.set( - rot[ 0 ], - rot[ 1 ], - rot[ 2 ] );
				quaternion.setFromEuler( euler );
M
r74  
Mr.doob 已提交
1720

M
r93  
Mr.doob 已提交
1721 1722
				position.add( center );
				position.applyQuaternion( quaternion );
M
r74  
Mr.doob 已提交
1723

M
r93  
Mr.doob 已提交
1724 1725 1726
				pushVector3( centers, center );
				pushQuaternion( quaternions, quaternion );
				pushVector3( positions, position );
M
r82  
Mr.doob 已提交
1727

M
r93  
Mr.doob 已提交
1728
				fovs.push( fov );
M
r74  
Mr.doob 已提交
1729

M
r93  
Mr.doob 已提交
1730
				for ( var j = 0; j < 3; j ++ ) {
M
r74  
Mr.doob 已提交
1731

M
r93  
Mr.doob 已提交
1732
					pushInterpolation( cInterpolations, interpolation, j );
M
r74  
Mr.doob 已提交
1733

M
r93  
Mr.doob 已提交
1734
				}
M
r74  
Mr.doob 已提交
1735

M
r93  
Mr.doob 已提交
1736
				pushInterpolation( qInterpolations, interpolation, 3 );
M
r74  
Mr.doob 已提交
1737

M
r93  
Mr.doob 已提交
1738 1739
				// use the same parameter for x, y, z axis.
				for ( var j = 0; j < 3; j ++ ) {
M
r74  
Mr.doob 已提交
1740

M
r93  
Mr.doob 已提交
1741
					pushInterpolation( pInterpolations, interpolation, 4 );
M
r76  
Mr.doob 已提交
1742

M
r93  
Mr.doob 已提交
1743
				}
M
r76  
Mr.doob 已提交
1744

M
r93  
Mr.doob 已提交
1745
				pushInterpolation( fInterpolations, interpolation, 5 );
M
r76  
Mr.doob 已提交
1746

M
r93  
Mr.doob 已提交
1747
			}
M
r74  
Mr.doob 已提交
1748

M
r93  
Mr.doob 已提交
1749
			var tracks = [];
M
r74  
Mr.doob 已提交
1750

M
r93  
Mr.doob 已提交
1751 1752
			// I expect an object whose name 'target' exists under THREE.Camera
			tracks.push( this._createTrack( 'target.position', THREE.VectorKeyframeTrack, times, centers, cInterpolations ) );
M
r74  
Mr.doob 已提交
1753

M
r93  
Mr.doob 已提交
1754 1755 1756
			tracks.push( this._createTrack( '.quaternion', THREE.QuaternionKeyframeTrack, times, quaternions, qInterpolations ) );
			tracks.push( this._createTrack( '.position', THREE.VectorKeyframeTrack, times, positions, pInterpolations ) );
			tracks.push( this._createTrack( '.fov', THREE.NumberKeyframeTrack, times, fovs, fInterpolations ) );
M
r74  
Mr.doob 已提交
1757

M
r93  
Mr.doob 已提交
1758
			return new THREE.AnimationClip( '', - 1, tracks );
M
r74  
Mr.doob 已提交
1759

M
r93  
Mr.doob 已提交
1760
		},
M
r74  
Mr.doob 已提交
1761

M
r93  
Mr.doob 已提交
1762
		// private method
M
r74  
Mr.doob 已提交
1763

M
r93  
Mr.doob 已提交
1764
		_createTrack: function ( node, typedKeyframeTrack, times, values, interpolations ) {
M
r74  
Mr.doob 已提交
1765

M
r93  
Mr.doob 已提交
1766 1767 1768 1769 1770 1771
			/*
			 * optimizes here not to let KeyframeTrackPrototype optimize
			 * because KeyframeTrackPrototype optimizes times and values but
			 * doesn't optimize interpolations.
			 */
			if ( times.length > 2 ) {
M
r74  
Mr.doob 已提交
1772

M
r93  
Mr.doob 已提交
1773 1774 1775
				times = times.slice();
				values = values.slice();
				interpolations = interpolations.slice();
M
r80  
Mr.doob 已提交
1776

M
r93  
Mr.doob 已提交
1777 1778
				var stride = values.length / times.length;
				var interpolateStride = interpolations.length / times.length;
M
r80  
Mr.doob 已提交
1779

M
r93  
Mr.doob 已提交
1780
				var index = 1;
M
r80  
Mr.doob 已提交
1781

M
r93  
Mr.doob 已提交
1782
				for ( var aheadIndex = 2, endIndex = times.length; aheadIndex < endIndex; aheadIndex ++ ) {
M
r80  
Mr.doob 已提交
1783

M
r93  
Mr.doob 已提交
1784
					for ( var i = 0; i < stride; i ++ ) {
M
r80  
Mr.doob 已提交
1785

M
r93  
Mr.doob 已提交
1786 1787
						if ( values[ index * stride + i ] !== values[ ( index - 1 ) * stride + i ] ||
							values[ index * stride + i ] !== values[ aheadIndex * stride + i ] ) {
M
r80  
Mr.doob 已提交
1788

M
r93  
Mr.doob 已提交
1789 1790
							index ++;
							break;
M
r80  
Mr.doob 已提交
1791

M
r93  
Mr.doob 已提交
1792
						}
M
r80  
Mr.doob 已提交
1793

M
r93  
Mr.doob 已提交
1794
					}
M
r80  
Mr.doob 已提交
1795

M
r93  
Mr.doob 已提交
1796
					if ( aheadIndex > index ) {
M
r80  
Mr.doob 已提交
1797

M
r93  
Mr.doob 已提交
1798
						times[ index ] = times[ aheadIndex ];
M
r80  
Mr.doob 已提交
1799

M
r93  
Mr.doob 已提交
1800
						for ( var i = 0; i < stride; i ++ ) {
M
r80  
Mr.doob 已提交
1801

M
r93  
Mr.doob 已提交
1802
							values[ index * stride + i ] = values[ aheadIndex * stride + i ];
M
r76  
Mr.doob 已提交
1803

M
r93  
Mr.doob 已提交
1804
						}
M
r76  
Mr.doob 已提交
1805

M
r93  
Mr.doob 已提交
1806
						for ( var i = 0; i < interpolateStride; i ++ ) {
M
r76  
Mr.doob 已提交
1807

M
r93  
Mr.doob 已提交
1808
							interpolations[ index * interpolateStride + i ] = interpolations[ aheadIndex * interpolateStride + i ];
M
r76  
Mr.doob 已提交
1809

M
r93  
Mr.doob 已提交
1810
						}
M
r76  
Mr.doob 已提交
1811

M
r93  
Mr.doob 已提交
1812
					}
M
r74  
Mr.doob 已提交
1813

M
r93  
Mr.doob 已提交
1814
				}
M
r74  
Mr.doob 已提交
1815

M
r93  
Mr.doob 已提交
1816 1817 1818
				times.length = index + 1;
				values.length = ( index + 1 ) * stride;
				interpolations.length = ( index + 1 ) * interpolateStride;
M
r74  
Mr.doob 已提交
1819

M
r93  
Mr.doob 已提交
1820
			}
M
r74  
Mr.doob 已提交
1821

M
r93  
Mr.doob 已提交
1822
			var track = new typedKeyframeTrack( node, times, values );
M
r74  
Mr.doob 已提交
1823

M
r93  
Mr.doob 已提交
1824
			track.createInterpolant = function InterpolantFactoryMethodCubicBezier( result ) {
M
r74  
Mr.doob 已提交
1825

M
r93  
Mr.doob 已提交
1826
				return new CubicBezierInterpolation( this.times, this.values, this.getValueSize(), result, new Float32Array( interpolations ) );
M
r74  
Mr.doob 已提交
1827

M
r93  
Mr.doob 已提交
1828
			};
M
r74  
Mr.doob 已提交
1829

M
r93  
Mr.doob 已提交
1830
			return track;
M
r74  
Mr.doob 已提交
1831 1832 1833

		}

M
r93  
Mr.doob 已提交
1834
	};
M
r74  
Mr.doob 已提交
1835

M
r93  
Mr.doob 已提交
1836
	// interpolation
M
r74  
Mr.doob 已提交
1837

M
r93  
Mr.doob 已提交
1838
	function CubicBezierInterpolation( parameterPositions, sampleValues, sampleSize, resultBuffer, params ) {
M
r74  
Mr.doob 已提交
1839

M
r93  
Mr.doob 已提交
1840
		THREE.Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );
M
r74  
Mr.doob 已提交
1841

M
r93  
Mr.doob 已提交
1842
		this.interpolationParams = params;
M
r74  
Mr.doob 已提交
1843

M
r93  
Mr.doob 已提交
1844
	}
M
r74  
Mr.doob 已提交
1845

M
r93  
Mr.doob 已提交
1846
	CubicBezierInterpolation.prototype = Object.assign( Object.create( THREE.Interpolant.prototype ), {
M
r74  
Mr.doob 已提交
1847

M
r93  
Mr.doob 已提交
1848
		constructor: CubicBezierInterpolation,
M
r74  
Mr.doob 已提交
1849

M
r93  
Mr.doob 已提交
1850
		interpolate_: function ( i1, t0, t, t1 ) {
M
r74  
Mr.doob 已提交
1851

M
r93  
Mr.doob 已提交
1852 1853 1854 1855
			var result = this.resultBuffer;
			var values = this.sampleValues;
			var stride = this.valueSize;
			var params = this.interpolationParams;
M
r74  
Mr.doob 已提交
1856

M
r93  
Mr.doob 已提交
1857 1858
			var offset1 = i1 * stride;
			var offset0 = offset1 - stride;
M
r74  
Mr.doob 已提交
1859

M
r93  
Mr.doob 已提交
1860 1861 1862 1863
			// No interpolation if next key frame is in one frame in 30fps.
			// This is from MMD animation spec.
			// '1.5' is for precision loss. times are Float32 in Three.js Animation system.
			var weight1 = ( ( t1 - t0 ) < 1 / 30 * 1.5 ) ? 0.0 : ( t - t0 ) / ( t1 - t0 );
M
r74  
Mr.doob 已提交
1864

M
r93  
Mr.doob 已提交
1865
			if ( stride === 4 ) { // Quaternion
M
r74  
Mr.doob 已提交
1866

M
r93  
Mr.doob 已提交
1867 1868 1869 1870
				var x1 = params[ i1 * 4 + 0 ];
				var x2 = params[ i1 * 4 + 1 ];
				var y1 = params[ i1 * 4 + 2 ];
				var y2 = params[ i1 * 4 + 3 ];
M
r74  
Mr.doob 已提交
1871

M
r93  
Mr.doob 已提交
1872
				var ratio = this._calculate( x1, x2, y1, y2, weight1 );
M
r83  
Mr.doob 已提交
1873

M
r93  
Mr.doob 已提交
1874
				THREE.Quaternion.slerpFlat( result, 0, values, offset0, values, offset1, ratio );
M
r74  
Mr.doob 已提交
1875

M
r93  
Mr.doob 已提交
1876
			} else if ( stride === 3 ) { // Vector3
M
r74  
Mr.doob 已提交
1877

M
r93  
Mr.doob 已提交
1878
				for ( var i = 0; i !== stride; ++ i ) {
M
r74  
Mr.doob 已提交
1879

M
r93  
Mr.doob 已提交
1880 1881 1882 1883
					var x1 = params[ i1 * 12 + i * 4 + 0 ];
					var x2 = params[ i1 * 12 + i * 4 + 1 ];
					var y1 = params[ i1 * 12 + i * 4 + 2 ];
					var y2 = params[ i1 * 12 + i * 4 + 3 ];
M
r76  
Mr.doob 已提交
1884

M
r93  
Mr.doob 已提交
1885
					var ratio = this._calculate( x1, x2, y1, y2, weight1 );
M
r76  
Mr.doob 已提交
1886

M
r93  
Mr.doob 已提交
1887
					result[ i ] = values[ offset0 + i ] * ( 1 - ratio ) + values[ offset1 + i ] * ratio;
M
r74  
Mr.doob 已提交
1888

M
r93  
Mr.doob 已提交
1889
				}
M
r74  
Mr.doob 已提交
1890

M
r93  
Mr.doob 已提交
1891
			} else { // Number
M
r74  
Mr.doob 已提交
1892

M
r93  
Mr.doob 已提交
1893 1894 1895 1896
				var x1 = params[ i1 * 4 + 0 ];
				var x2 = params[ i1 * 4 + 1 ];
				var y1 = params[ i1 * 4 + 2 ];
				var y2 = params[ i1 * 4 + 3 ];
M
r74  
Mr.doob 已提交
1897

M
r93  
Mr.doob 已提交
1898
				var ratio = this._calculate( x1, x2, y1, y2, weight1 );
M
r74  
Mr.doob 已提交
1899

M
r93  
Mr.doob 已提交
1900
				result[ 0 ] = values[ offset0 ] * ( 1 - ratio ) + values[ offset1 ] * ratio;
M
r74  
Mr.doob 已提交
1901

M
r93  
Mr.doob 已提交
1902
			}
M
r74  
Mr.doob 已提交
1903

M
r93  
Mr.doob 已提交
1904
			return result;
M
r74  
Mr.doob 已提交
1905

M
r93  
Mr.doob 已提交
1906
		},
M
r74  
Mr.doob 已提交
1907

M
r93  
Mr.doob 已提交
1908
		_calculate: function ( x1, x2, y1, y2, x ) {
M
r74  
Mr.doob 已提交
1909

M
r93  
Mr.doob 已提交
1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
			/*
			 * Cubic Bezier curves
			 *   https://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
			 *
			 * B(t) = ( 1 - t ) ^ 3 * P0
			 *      + 3 * ( 1 - t ) ^ 2 * t * P1
			 *      + 3 * ( 1 - t ) * t^2 * P2
			 *      + t ^ 3 * P3
			 *      ( 0 <= t <= 1 )
			 *
			 * MMD uses Cubic Bezier curves for bone and camera animation interpolation.
			 *   http://d.hatena.ne.jp/edvakf/20111016/1318716097
			 *
			 *    x = ( 1 - t ) ^ 3 * x0
			 *      + 3 * ( 1 - t ) ^ 2 * t * x1
			 *      + 3 * ( 1 - t ) * t^2 * x2
			 *      + t ^ 3 * x3
			 *    y = ( 1 - t ) ^ 3 * y0
			 *      + 3 * ( 1 - t ) ^ 2 * t * y1
			 *      + 3 * ( 1 - t ) * t^2 * y2
			 *      + t ^ 3 * y3
			 *      ( x0 = 0, y0 = 0 )
			 *      ( x3 = 1, y3 = 1 )
			 *      ( 0 <= t, x1, x2, y1, y2 <= 1 )
			 *
			 * Here solves this equation with Bisection method,
			 *   https://en.wikipedia.org/wiki/Bisection_method
			 * gets t, and then calculate y.
			 *
			 * f(t) = 3 * ( 1 - t ) ^ 2 * t * x1
			 *      + 3 * ( 1 - t ) * t^2 * x2
			 *      + t ^ 3 - x = 0
			 *
			 * (Another option: Newton's method
			 *    https://en.wikipedia.org/wiki/Newton%27s_method)
			 */
M
r74  
Mr.doob 已提交
1946

M
r93  
Mr.doob 已提交
1947 1948 1949 1950 1951 1952
			var c = 0.5;
			var t = c;
			var s = 1.0 - t;
			var loop = 15;
			var eps = 1e-5;
			var math = Math;
M
r74  
Mr.doob 已提交
1953

M
r93  
Mr.doob 已提交
1954
			var sst3, stt3, ttt;
M
r74  
Mr.doob 已提交
1955

M
r93  
Mr.doob 已提交
1956
			for ( var i = 0; i < loop; i ++ ) {
M
r74  
Mr.doob 已提交
1957

M
r93  
Mr.doob 已提交
1958 1959 1960
				sst3 = 3.0 * s * s * t;
				stt3 = 3.0 * s * t * t;
				ttt = t * t * t;
M
r74  
Mr.doob 已提交
1961

M
r93  
Mr.doob 已提交
1962
				var ft = ( sst3 * x1 ) + ( stt3 * x2 ) + ( ttt ) - x;
M
r74  
Mr.doob 已提交
1963

M
r93  
Mr.doob 已提交
1964
				if ( math.abs( ft ) < eps ) break;
M
r74  
Mr.doob 已提交
1965

M
r93  
Mr.doob 已提交
1966
				c /= 2.0;
M
r74  
Mr.doob 已提交
1967

M
r93  
Mr.doob 已提交
1968 1969
				t += ( ft < 0 ) ? c : - c;
				s = 1.0 - t;
M
r74  
Mr.doob 已提交
1970

M
r93  
Mr.doob 已提交
1971
			}
M
r74  
Mr.doob 已提交
1972

M
r93  
Mr.doob 已提交
1973
			return ( sst3 * y1 ) + ( stt3 * y2 ) + ttt;
M
r74  
Mr.doob 已提交
1974 1975 1976

		}

M
r93  
Mr.doob 已提交
1977 1978 1979
	} );

	return MMDLoader;
M
r74  
Mr.doob 已提交
1980

M
r93  
Mr.doob 已提交
1981
} )();