1 | /**
|
---|
2 | * @author mrdoob / http://mrdoob.com/
|
---|
3 | * @author alteredq / http://alteredqualia.com/
|
---|
4 | */
|
---|
5 |
|
---|
6 | THREE.JSONLoader = function ( showStatus ) {
|
---|
7 |
|
---|
8 | THREE.Loader.call( this, showStatus );
|
---|
9 |
|
---|
10 | this.withCredentials = false;
|
---|
11 |
|
---|
12 | };
|
---|
13 |
|
---|
14 | THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype );
|
---|
15 |
|
---|
16 | THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
|
---|
17 |
|
---|
18 | var scope = this;
|
---|
19 |
|
---|
20 | // todo: unify load API to for easier SceneLoader use
|
---|
21 |
|
---|
22 | texturePath = texturePath && ( typeof texturePath === "string" ) ? texturePath : this.extractUrlBase( url );
|
---|
23 |
|
---|
24 | this.onLoadStart();
|
---|
25 | this.loadAjaxJSON( this, url, callback, texturePath );
|
---|
26 |
|
---|
27 | };
|
---|
28 |
|
---|
29 | THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, callbackProgress ) {
|
---|
30 |
|
---|
31 | var xhr = new XMLHttpRequest();
|
---|
32 |
|
---|
33 | var length = 0;
|
---|
34 |
|
---|
35 | xhr.onreadystatechange = function () {
|
---|
36 |
|
---|
37 | if ( xhr.readyState === xhr.DONE ) {
|
---|
38 |
|
---|
39 | if ( xhr.status === 200 || xhr.status === 0 ) {
|
---|
40 |
|
---|
41 | if ( xhr.responseText ) {
|
---|
42 |
|
---|
43 | var json = JSON.parse( xhr.responseText );
|
---|
44 | var result = context.parse( json, texturePath );
|
---|
45 | callback( result.geometry, result.materials );
|
---|
46 |
|
---|
47 | } else {
|
---|
48 |
|
---|
49 | console.warn( "THREE.JSONLoader: [" + url + "] seems to be unreachable or file there is empty" );
|
---|
50 |
|
---|
51 | }
|
---|
52 |
|
---|
53 | // in context of more complex asset initialization
|
---|
54 | // do not block on single failed file
|
---|
55 | // maybe should go even one more level up
|
---|
56 |
|
---|
57 | context.onLoadComplete();
|
---|
58 |
|
---|
59 | } else {
|
---|
60 |
|
---|
61 | console.error( "THREE.JSONLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
|
---|
62 |
|
---|
63 | }
|
---|
64 |
|
---|
65 | } else if ( xhr.readyState === xhr.LOADING ) {
|
---|
66 |
|
---|
67 | if ( callbackProgress ) {
|
---|
68 |
|
---|
69 | if ( length === 0 ) {
|
---|
70 |
|
---|
71 | length = xhr.getResponseHeader( "Content-Length" );
|
---|
72 |
|
---|
73 | }
|
---|
74 |
|
---|
75 | callbackProgress( { total: length, loaded: xhr.responseText.length } );
|
---|
76 |
|
---|
77 | }
|
---|
78 |
|
---|
79 | } else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
|
---|
80 |
|
---|
81 | if ( callbackProgress !== undefined ) {
|
---|
82 |
|
---|
83 | length = xhr.getResponseHeader( "Content-Length" );
|
---|
84 |
|
---|
85 | }
|
---|
86 |
|
---|
87 | }
|
---|
88 |
|
---|
89 | };
|
---|
90 |
|
---|
91 | xhr.open( "GET", url, true );
|
---|
92 | xhr.withCredentials = this.withCredentials;
|
---|
93 | xhr.send( null );
|
---|
94 |
|
---|
95 | };
|
---|
96 |
|
---|
97 | THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
|
---|
98 |
|
---|
99 | var scope = this,
|
---|
100 | geometry = new THREE.Geometry(),
|
---|
101 | scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
|
---|
102 |
|
---|
103 | parseModel( scale );
|
---|
104 |
|
---|
105 | parseSkin();
|
---|
106 | parseMorphing( scale );
|
---|
107 |
|
---|
108 | geometry.computeCentroids();
|
---|
109 | geometry.computeFaceNormals();
|
---|
110 | geometry.computeBoundingSphere();
|
---|
111 |
|
---|
112 | function parseModel( scale ) {
|
---|
113 |
|
---|
114 | function isBitSet( value, position ) {
|
---|
115 |
|
---|
116 | return value & ( 1 << position );
|
---|
117 |
|
---|
118 | }
|
---|
119 |
|
---|
120 | var i, j, fi,
|
---|
121 |
|
---|
122 | offset, zLength,
|
---|
123 |
|
---|
124 | colorIndex, normalIndex, uvIndex, materialIndex,
|
---|
125 |
|
---|
126 | type,
|
---|
127 | isQuad,
|
---|
128 | hasMaterial,
|
---|
129 | hasFaceVertexUv,
|
---|
130 | hasFaceNormal, hasFaceVertexNormal,
|
---|
131 | hasFaceColor, hasFaceVertexColor,
|
---|
132 |
|
---|
133 | vertex, face, faceA, faceB, color, hex, normal,
|
---|
134 |
|
---|
135 | uvLayer, uv, u, v,
|
---|
136 |
|
---|
137 | faces = json.faces,
|
---|
138 | vertices = json.vertices,
|
---|
139 | normals = json.normals,
|
---|
140 | colors = json.colors,
|
---|
141 |
|
---|
142 | nUvLayers = 0;
|
---|
143 |
|
---|
144 | if ( json.uvs !== undefined ) {
|
---|
145 |
|
---|
146 | // disregard empty arrays
|
---|
147 |
|
---|
148 | for ( i = 0; i < json.uvs.length; i++ ) {
|
---|
149 |
|
---|
150 | if ( json.uvs[ i ].length ) nUvLayers ++;
|
---|
151 |
|
---|
152 | }
|
---|
153 |
|
---|
154 | for ( i = 0; i < nUvLayers; i++ ) {
|
---|
155 |
|
---|
156 | geometry.faceVertexUvs[ i ] = [];
|
---|
157 |
|
---|
158 | }
|
---|
159 |
|
---|
160 | }
|
---|
161 |
|
---|
162 | offset = 0;
|
---|
163 | zLength = vertices.length;
|
---|
164 |
|
---|
165 | while ( offset < zLength ) {
|
---|
166 |
|
---|
167 | vertex = new THREE.Vector3();
|
---|
168 |
|
---|
169 | vertex.x = vertices[ offset ++ ] * scale;
|
---|
170 | vertex.y = vertices[ offset ++ ] * scale;
|
---|
171 | vertex.z = vertices[ offset ++ ] * scale;
|
---|
172 |
|
---|
173 | geometry.vertices.push( vertex );
|
---|
174 |
|
---|
175 | }
|
---|
176 |
|
---|
177 | offset = 0;
|
---|
178 | zLength = faces.length;
|
---|
179 |
|
---|
180 | while ( offset < zLength ) {
|
---|
181 |
|
---|
182 | type = faces[ offset ++ ];
|
---|
183 |
|
---|
184 |
|
---|
185 | isQuad = isBitSet( type, 0 );
|
---|
186 | hasMaterial = isBitSet( type, 1 );
|
---|
187 | hasFaceVertexUv = isBitSet( type, 3 );
|
---|
188 | hasFaceNormal = isBitSet( type, 4 );
|
---|
189 | hasFaceVertexNormal = isBitSet( type, 5 );
|
---|
190 | hasFaceColor = isBitSet( type, 6 );
|
---|
191 | hasFaceVertexColor = isBitSet( type, 7 );
|
---|
192 |
|
---|
193 | // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
|
---|
194 |
|
---|
195 | if ( isQuad ) {
|
---|
196 |
|
---|
197 | faceA = new THREE.Face3();
|
---|
198 | faceA.a = faces[ offset ];
|
---|
199 | faceA.b = faces[ offset + 1 ];
|
---|
200 | faceA.c = faces[ offset + 3 ];
|
---|
201 |
|
---|
202 | faceB = new THREE.Face3();
|
---|
203 | faceB.a = faces[ offset + 1 ];
|
---|
204 | faceB.b = faces[ offset + 2 ];
|
---|
205 | faceB.c = faces[ offset + 3 ];
|
---|
206 |
|
---|
207 | offset += 4;
|
---|
208 |
|
---|
209 | if ( hasMaterial ) {
|
---|
210 |
|
---|
211 | materialIndex = faces[ offset ++ ];
|
---|
212 | faceA.materialIndex = materialIndex;
|
---|
213 | faceB.materialIndex = materialIndex;
|
---|
214 |
|
---|
215 | }
|
---|
216 |
|
---|
217 | // to get face <=> uv index correspondence
|
---|
218 |
|
---|
219 | fi = geometry.faces.length;
|
---|
220 |
|
---|
221 | if ( hasFaceVertexUv ) {
|
---|
222 |
|
---|
223 | for ( i = 0; i < nUvLayers; i++ ) {
|
---|
224 |
|
---|
225 | uvLayer = json.uvs[ i ];
|
---|
226 |
|
---|
227 | geometry.faceVertexUvs[ i ][ fi ] = [];
|
---|
228 | geometry.faceVertexUvs[ i ][ fi + 1 ] = []
|
---|
229 |
|
---|
230 | for ( j = 0; j < 4; j ++ ) {
|
---|
231 |
|
---|
232 | uvIndex = faces[ offset ++ ];
|
---|
233 |
|
---|
234 | u = uvLayer[ uvIndex * 2 ];
|
---|
235 | v = uvLayer[ uvIndex * 2 + 1 ];
|
---|
236 |
|
---|
237 | uv = new THREE.Vector2( u, v );
|
---|
238 |
|
---|
239 | if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
---|
240 | if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
|
---|
241 |
|
---|
242 | }
|
---|
243 |
|
---|
244 | }
|
---|
245 |
|
---|
246 | }
|
---|
247 |
|
---|
248 | if ( hasFaceNormal ) {
|
---|
249 |
|
---|
250 | normalIndex = faces[ offset ++ ] * 3;
|
---|
251 |
|
---|
252 | faceA.normal.set(
|
---|
253 | normals[ normalIndex ++ ],
|
---|
254 | normals[ normalIndex ++ ],
|
---|
255 | normals[ normalIndex ]
|
---|
256 | );
|
---|
257 |
|
---|
258 | faceB.normal.copy( faceA.normal );
|
---|
259 |
|
---|
260 | }
|
---|
261 |
|
---|
262 | if ( hasFaceVertexNormal ) {
|
---|
263 |
|
---|
264 | for ( i = 0; i < 4; i++ ) {
|
---|
265 |
|
---|
266 | normalIndex = faces[ offset ++ ] * 3;
|
---|
267 |
|
---|
268 | normal = new THREE.Vector3(
|
---|
269 | normals[ normalIndex ++ ],
|
---|
270 | normals[ normalIndex ++ ],
|
---|
271 | normals[ normalIndex ]
|
---|
272 | );
|
---|
273 |
|
---|
274 |
|
---|
275 | if ( i !== 2 ) faceA.vertexNormals.push( normal );
|
---|
276 | if ( i !== 0 ) faceB.vertexNormals.push( normal );
|
---|
277 |
|
---|
278 | }
|
---|
279 |
|
---|
280 | }
|
---|
281 |
|
---|
282 |
|
---|
283 | if ( hasFaceColor ) {
|
---|
284 |
|
---|
285 | colorIndex = faces[ offset ++ ];
|
---|
286 | hex = colors[ colorIndex ];
|
---|
287 |
|
---|
288 | faceA.color.setHex( hex );
|
---|
289 | faceB.color.setHex( hex );
|
---|
290 |
|
---|
291 | }
|
---|
292 |
|
---|
293 |
|
---|
294 | if ( hasFaceVertexColor ) {
|
---|
295 |
|
---|
296 | for ( i = 0; i < 4; i++ ) {
|
---|
297 |
|
---|
298 | colorIndex = faces[ offset ++ ];
|
---|
299 | hex = colors[ colorIndex ];
|
---|
300 |
|
---|
301 | if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
|
---|
302 | if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
|
---|
303 |
|
---|
304 | }
|
---|
305 |
|
---|
306 | }
|
---|
307 |
|
---|
308 | geometry.faces.push( faceA );
|
---|
309 | geometry.faces.push( faceB );
|
---|
310 |
|
---|
311 | } else {
|
---|
312 |
|
---|
313 | face = new THREE.Face3();
|
---|
314 | face.a = faces[ offset ++ ];
|
---|
315 | face.b = faces[ offset ++ ];
|
---|
316 | face.c = faces[ offset ++ ];
|
---|
317 |
|
---|
318 | if ( hasMaterial ) {
|
---|
319 |
|
---|
320 | materialIndex = faces[ offset ++ ];
|
---|
321 | face.materialIndex = materialIndex;
|
---|
322 |
|
---|
323 | }
|
---|
324 |
|
---|
325 | // to get face <=> uv index correspondence
|
---|
326 |
|
---|
327 | fi = geometry.faces.length;
|
---|
328 |
|
---|
329 | if ( hasFaceVertexUv ) {
|
---|
330 |
|
---|
331 | for ( i = 0; i < nUvLayers; i++ ) {
|
---|
332 |
|
---|
333 | uvLayer = json.uvs[ i ];
|
---|
334 |
|
---|
335 | geometry.faceVertexUvs[ i ][ fi ] = [];
|
---|
336 |
|
---|
337 | for ( j = 0; j < 3; j ++ ) {
|
---|
338 |
|
---|
339 | uvIndex = faces[ offset ++ ];
|
---|
340 |
|
---|
341 | u = uvLayer[ uvIndex * 2 ];
|
---|
342 | v = uvLayer[ uvIndex * 2 + 1 ];
|
---|
343 |
|
---|
344 | uv = new THREE.Vector2( u, v );
|
---|
345 |
|
---|
346 | geometry.faceVertexUvs[ i ][ fi ].push( uv );
|
---|
347 |
|
---|
348 | }
|
---|
349 |
|
---|
350 | }
|
---|
351 |
|
---|
352 | }
|
---|
353 |
|
---|
354 | if ( hasFaceNormal ) {
|
---|
355 |
|
---|
356 | normalIndex = faces[ offset ++ ] * 3;
|
---|
357 |
|
---|
358 | face.normal.set(
|
---|
359 | normals[ normalIndex ++ ],
|
---|
360 | normals[ normalIndex ++ ],
|
---|
361 | normals[ normalIndex ]
|
---|
362 | );
|
---|
363 |
|
---|
364 | }
|
---|
365 |
|
---|
366 | if ( hasFaceVertexNormal ) {
|
---|
367 |
|
---|
368 | for ( i = 0; i < 3; i++ ) {
|
---|
369 |
|
---|
370 | normalIndex = faces[ offset ++ ] * 3;
|
---|
371 |
|
---|
372 | normal = new THREE.Vector3(
|
---|
373 | normals[ normalIndex ++ ],
|
---|
374 | normals[ normalIndex ++ ],
|
---|
375 | normals[ normalIndex ]
|
---|
376 | );
|
---|
377 |
|
---|
378 | face.vertexNormals.push( normal );
|
---|
379 |
|
---|
380 | }
|
---|
381 |
|
---|
382 | }
|
---|
383 |
|
---|
384 |
|
---|
385 | if ( hasFaceColor ) {
|
---|
386 |
|
---|
387 | colorIndex = faces[ offset ++ ];
|
---|
388 | face.color.setHex( colors[ colorIndex ] );
|
---|
389 |
|
---|
390 | }
|
---|
391 |
|
---|
392 |
|
---|
393 | if ( hasFaceVertexColor ) {
|
---|
394 |
|
---|
395 | for ( i = 0; i < 3; i++ ) {
|
---|
396 |
|
---|
397 | colorIndex = faces[ offset ++ ];
|
---|
398 | face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
|
---|
399 |
|
---|
400 | }
|
---|
401 |
|
---|
402 | }
|
---|
403 |
|
---|
404 | geometry.faces.push( face );
|
---|
405 |
|
---|
406 | }
|
---|
407 |
|
---|
408 | }
|
---|
409 |
|
---|
410 | };
|
---|
411 |
|
---|
412 | function parseSkin() {
|
---|
413 |
|
---|
414 | var i, l, x, y, z, w, a, b, c, d;
|
---|
415 |
|
---|
416 | if ( json.skinWeights ) {
|
---|
417 |
|
---|
418 | for ( i = 0, l = json.skinWeights.length; i < l; i += 2 ) {
|
---|
419 |
|
---|
420 | x = json.skinWeights[ i ];
|
---|
421 | y = json.skinWeights[ i + 1 ];
|
---|
422 | z = 0;
|
---|
423 | w = 0;
|
---|
424 |
|
---|
425 | geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
|
---|
426 |
|
---|
427 | }
|
---|
428 |
|
---|
429 | }
|
---|
430 |
|
---|
431 | if ( json.skinIndices ) {
|
---|
432 |
|
---|
433 | for ( i = 0, l = json.skinIndices.length; i < l; i += 2 ) {
|
---|
434 |
|
---|
435 | a = json.skinIndices[ i ];
|
---|
436 | b = json.skinIndices[ i + 1 ];
|
---|
437 | c = 0;
|
---|
438 | d = 0;
|
---|
439 |
|
---|
440 | geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
|
---|
441 |
|
---|
442 | }
|
---|
443 |
|
---|
444 | }
|
---|
445 |
|
---|
446 | geometry.bones = json.bones;
|
---|
447 | // could change this to json.animations[0] or remove completely
|
---|
448 | geometry.animation = json.animation;
|
---|
449 | geometry.animations = json.animations;
|
---|
450 | };
|
---|
451 |
|
---|
452 | function parseMorphing( scale ) {
|
---|
453 |
|
---|
454 | if ( json.morphTargets !== undefined ) {
|
---|
455 |
|
---|
456 | var i, l, v, vl, dstVertices, srcVertices;
|
---|
457 |
|
---|
458 | for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
|
---|
459 |
|
---|
460 | geometry.morphTargets[ i ] = {};
|
---|
461 | geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
|
---|
462 | geometry.morphTargets[ i ].vertices = [];
|
---|
463 |
|
---|
464 | dstVertices = geometry.morphTargets[ i ].vertices;
|
---|
465 | srcVertices = json.morphTargets [ i ].vertices;
|
---|
466 |
|
---|
467 | for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
|
---|
468 |
|
---|
469 | var vertex = new THREE.Vector3();
|
---|
470 | vertex.x = srcVertices[ v ] * scale;
|
---|
471 | vertex.y = srcVertices[ v + 1 ] * scale;
|
---|
472 | vertex.z = srcVertices[ v + 2 ] * scale;
|
---|
473 |
|
---|
474 | dstVertices.push( vertex );
|
---|
475 |
|
---|
476 | }
|
---|
477 |
|
---|
478 | }
|
---|
479 |
|
---|
480 | }
|
---|
481 |
|
---|
482 | if ( json.morphColors !== undefined ) {
|
---|
483 |
|
---|
484 | var i, l, c, cl, dstColors, srcColors, color;
|
---|
485 |
|
---|
486 | for ( i = 0, l = json.morphColors.length; i < l; i++ ) {
|
---|
487 |
|
---|
488 | geometry.morphColors[ i ] = {};
|
---|
489 | geometry.morphColors[ i ].name = json.morphColors[ i ].name;
|
---|
490 | geometry.morphColors[ i ].colors = [];
|
---|
491 |
|
---|
492 | dstColors = geometry.morphColors[ i ].colors;
|
---|
493 | srcColors = json.morphColors [ i ].colors;
|
---|
494 |
|
---|
495 | for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) {
|
---|
496 |
|
---|
497 | color = new THREE.Color( 0xffaa00 );
|
---|
498 | color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
|
---|
499 | dstColors.push( color );
|
---|
500 |
|
---|
501 | }
|
---|
502 |
|
---|
503 | }
|
---|
504 |
|
---|
505 | }
|
---|
506 |
|
---|
507 | };
|
---|
508 |
|
---|
509 | if ( json.materials === undefined ) {
|
---|
510 |
|
---|
511 | return { geometry: geometry };
|
---|
512 |
|
---|
513 | } else {
|
---|
514 |
|
---|
515 | var materials = this.initMaterials( json.materials, texturePath );
|
---|
516 |
|
---|
517 | if ( this.needsTangents( materials ) ) {
|
---|
518 |
|
---|
519 | geometry.computeTangents();
|
---|
520 |
|
---|
521 | }
|
---|
522 |
|
---|
523 | return { geometry: geometry, materials: materials };
|
---|
524 |
|
---|
525 | }
|
---|
526 |
|
---|
527 | };
|
---|