1 | /**
|
---|
2 | * @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com
|
---|
3 | * @author Tony Parisi / http://www.tonyparisi.com/
|
---|
4 | */
|
---|
5 |
|
---|
6 | THREE.ColladaLoader = function () {
|
---|
7 |
|
---|
8 | var COLLADA = null;
|
---|
9 | var scene = null;
|
---|
10 | var visualScene;
|
---|
11 | var kinematicsModel;
|
---|
12 |
|
---|
13 | var readyCallbackFunc = null;
|
---|
14 |
|
---|
15 | var sources = {};
|
---|
16 | var images = {};
|
---|
17 | var animations = {};
|
---|
18 | var controllers = {};
|
---|
19 | var geometries = {};
|
---|
20 | var materials = {};
|
---|
21 | var effects = {};
|
---|
22 | var cameras = {};
|
---|
23 | var lights = {};
|
---|
24 |
|
---|
25 | var animData;
|
---|
26 | var kinematics;
|
---|
27 | var visualScenes;
|
---|
28 | var kinematicsModel;
|
---|
29 | var baseUrl;
|
---|
30 | var morphs;
|
---|
31 | var skins;
|
---|
32 |
|
---|
33 | var flip_uv = true;
|
---|
34 | var preferredShading = THREE.SmoothShading;
|
---|
35 |
|
---|
36 | var options = {
|
---|
37 | // Force Geometry to always be centered at the local origin of the
|
---|
38 | // containing Mesh.
|
---|
39 | centerGeometry: false,
|
---|
40 |
|
---|
41 | // Axis conversion is done for geometries, animations, and controllers.
|
---|
42 | // If we ever pull cameras or lights out of the COLLADA file, they'll
|
---|
43 | // need extra work.
|
---|
44 | convertUpAxis: false,
|
---|
45 |
|
---|
46 | subdivideFaces: true,
|
---|
47 |
|
---|
48 | upAxis: 'Y',
|
---|
49 |
|
---|
50 | // For reflective or refractive materials we'll use this cubemap
|
---|
51 | defaultEnvMap: null
|
---|
52 |
|
---|
53 | };
|
---|
54 |
|
---|
55 | var colladaUnit = 1.0;
|
---|
56 | var colladaUp = 'Y';
|
---|
57 | var upConversion = null;
|
---|
58 |
|
---|
59 | function load ( url, readyCallback, progressCallback ) {
|
---|
60 |
|
---|
61 | var length = 0;
|
---|
62 |
|
---|
63 | if ( document.implementation && document.implementation.createDocument ) {
|
---|
64 |
|
---|
65 | var request = new XMLHttpRequest();
|
---|
66 |
|
---|
67 | request.onreadystatechange = function() {
|
---|
68 |
|
---|
69 | if( request.readyState === 4 ) {
|
---|
70 |
|
---|
71 | if( request.status === 0 || request.status === 200 ) {
|
---|
72 |
|
---|
73 |
|
---|
74 | if ( request.responseXML ) {
|
---|
75 |
|
---|
76 | readyCallbackFunc = readyCallback;
|
---|
77 | parse( request.responseXML, undefined, url );
|
---|
78 |
|
---|
79 | } else if ( request.responseText ) {
|
---|
80 |
|
---|
81 | readyCallbackFunc = readyCallback;
|
---|
82 | var xmlParser = new DOMParser();
|
---|
83 | var responseXML = xmlParser.parseFromString( request.responseText, "application/xml" );
|
---|
84 | parse( responseXML, undefined, url );
|
---|
85 |
|
---|
86 | } else {
|
---|
87 |
|
---|
88 | console.error( "ColladaLoader: Empty or non-existing file (" + url + ")" );
|
---|
89 |
|
---|
90 | }
|
---|
91 |
|
---|
92 | }
|
---|
93 |
|
---|
94 | } else if ( request.readyState === 3 ) {
|
---|
95 |
|
---|
96 | if ( progressCallback ) {
|
---|
97 |
|
---|
98 | if ( length === 0 ) {
|
---|
99 |
|
---|
100 | length = request.getResponseHeader( "Content-Length" );
|
---|
101 |
|
---|
102 | }
|
---|
103 |
|
---|
104 | progressCallback( { total: length, loaded: request.responseText.length } );
|
---|
105 |
|
---|
106 | }
|
---|
107 |
|
---|
108 | }
|
---|
109 |
|
---|
110 | }
|
---|
111 |
|
---|
112 | request.open( "GET", url, true );
|
---|
113 | request.send( null );
|
---|
114 |
|
---|
115 | } else {
|
---|
116 |
|
---|
117 | alert( "Don't know how to parse XML!" );
|
---|
118 |
|
---|
119 | }
|
---|
120 |
|
---|
121 | }
|
---|
122 |
|
---|
123 | function parse( doc, callBack, url ) {
|
---|
124 |
|
---|
125 | COLLADA = doc;
|
---|
126 | callBack = callBack || readyCallbackFunc;
|
---|
127 |
|
---|
128 | if ( url !== undefined ) {
|
---|
129 |
|
---|
130 | var parts = url.split( '/' );
|
---|
131 | parts.pop();
|
---|
132 | baseUrl = ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
|
---|
133 |
|
---|
134 | }
|
---|
135 |
|
---|
136 | parseAsset();
|
---|
137 | setUpConversion();
|
---|
138 | images = parseLib( "library_images image", _Image, "image" );
|
---|
139 | materials = parseLib( "library_materials material", Material, "material" );
|
---|
140 | effects = parseLib( "library_effects effect", Effect, "effect" );
|
---|
141 | geometries = parseLib( "library_geometries geometry", Geometry, "geometry" );
|
---|
142 | cameras = parseLib( "library_cameras camera", Camera, "camera" );
|
---|
143 | lights = parseLib( "library_lights light", Light, "light" );
|
---|
144 | controllers = parseLib( "library_controllers controller", Controller, "controller" );
|
---|
145 | animations = parseLib( "library_animations animation", Animation, "animation" );
|
---|
146 | visualScenes = parseLib( "library_visual_scenes visual_scene", VisualScene, "visual_scene" );
|
---|
147 | kinematicsModels = parseLib( "library_kinematics_models kinematics_model", KinematicsModel, "kinematics_model" );
|
---|
148 |
|
---|
149 | morphs = [];
|
---|
150 | skins = [];
|
---|
151 |
|
---|
152 | visualScene = parseScene();
|
---|
153 | scene = new THREE.Scene();
|
---|
154 |
|
---|
155 | for ( var i = 0; i < visualScene.nodes.length; i ++ ) {
|
---|
156 |
|
---|
157 | scene.add( createSceneGraph( visualScene.nodes[ i ] ) );
|
---|
158 |
|
---|
159 | }
|
---|
160 |
|
---|
161 | // unit conversion
|
---|
162 | scene.scale.multiplyScalar( colladaUnit );
|
---|
163 |
|
---|
164 | createAnimations();
|
---|
165 |
|
---|
166 | kinematicsModel = parseKinematicsModel();
|
---|
167 | createKinematics();
|
---|
168 |
|
---|
169 | var result = {
|
---|
170 |
|
---|
171 | scene: scene,
|
---|
172 | morphs: morphs,
|
---|
173 | skins: skins,
|
---|
174 | animations: animData,
|
---|
175 | kinematics: kinematics,
|
---|
176 | dae: {
|
---|
177 | images: images,
|
---|
178 | materials: materials,
|
---|
179 | cameras: cameras,
|
---|
180 | lights: lights,
|
---|
181 | effects: effects,
|
---|
182 | geometries: geometries,
|
---|
183 | controllers: controllers,
|
---|
184 | animations: animations,
|
---|
185 | visualScenes: visualScenes,
|
---|
186 | visualScene: visualScene,
|
---|
187 | scene: visualScene,
|
---|
188 | kinematicsModels: kinematicsModels,
|
---|
189 | kinematicsModel: kinematicsModel
|
---|
190 | }
|
---|
191 |
|
---|
192 | };
|
---|
193 |
|
---|
194 | if ( callBack ) {
|
---|
195 |
|
---|
196 | callBack( result );
|
---|
197 |
|
---|
198 | }
|
---|
199 |
|
---|
200 | return result;
|
---|
201 |
|
---|
202 | }
|
---|
203 |
|
---|
204 | function setPreferredShading ( shading ) {
|
---|
205 |
|
---|
206 | preferredShading = shading;
|
---|
207 |
|
---|
208 | }
|
---|
209 |
|
---|
210 | function parseAsset () {
|
---|
211 |
|
---|
212 | var elements = COLLADA.querySelectorAll('asset');
|
---|
213 |
|
---|
214 | var element = elements[0];
|
---|
215 |
|
---|
216 | if ( element && element.childNodes ) {
|
---|
217 |
|
---|
218 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
219 |
|
---|
220 | var child = element.childNodes[ i ];
|
---|
221 |
|
---|
222 | switch ( child.nodeName ) {
|
---|
223 |
|
---|
224 | case 'unit':
|
---|
225 |
|
---|
226 | var meter = child.getAttribute( 'meter' );
|
---|
227 |
|
---|
228 | if ( meter ) {
|
---|
229 |
|
---|
230 | colladaUnit = parseFloat( meter );
|
---|
231 |
|
---|
232 | }
|
---|
233 |
|
---|
234 | break;
|
---|
235 |
|
---|
236 | case 'up_axis':
|
---|
237 |
|
---|
238 | colladaUp = child.textContent.charAt(0);
|
---|
239 | break;
|
---|
240 |
|
---|
241 | }
|
---|
242 |
|
---|
243 | }
|
---|
244 |
|
---|
245 | }
|
---|
246 |
|
---|
247 | }
|
---|
248 |
|
---|
249 | function parseLib ( q, classSpec, prefix ) {
|
---|
250 |
|
---|
251 | var elements = COLLADA.querySelectorAll(q);
|
---|
252 |
|
---|
253 | var lib = {};
|
---|
254 |
|
---|
255 | var i = 0;
|
---|
256 |
|
---|
257 | var elementsLength = elements.length;
|
---|
258 |
|
---|
259 | for ( var j = 0; j < elementsLength; j ++ ) {
|
---|
260 |
|
---|
261 | var element = elements[j];
|
---|
262 | var daeElement = ( new classSpec() ).parse( element );
|
---|
263 |
|
---|
264 | if ( !daeElement.id || daeElement.id.length === 0 ) daeElement.id = prefix + ( i ++ );
|
---|
265 | lib[ daeElement.id ] = daeElement;
|
---|
266 |
|
---|
267 | }
|
---|
268 |
|
---|
269 | return lib;
|
---|
270 |
|
---|
271 | }
|
---|
272 |
|
---|
273 | function parseScene() {
|
---|
274 |
|
---|
275 | var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0];
|
---|
276 |
|
---|
277 | if ( sceneElement ) {
|
---|
278 |
|
---|
279 | var url = sceneElement.getAttribute( 'url' ).replace( /^#/, '' );
|
---|
280 | return visualScenes[ url.length > 0 ? url : 'visual_scene0' ];
|
---|
281 |
|
---|
282 | } else {
|
---|
283 |
|
---|
284 | return null;
|
---|
285 |
|
---|
286 | }
|
---|
287 |
|
---|
288 | }
|
---|
289 |
|
---|
290 | function parseKinematicsModel() {
|
---|
291 |
|
---|
292 | var kinematicsModelElement = COLLADA.querySelectorAll('instance_kinematics_model')[0];
|
---|
293 |
|
---|
294 | if ( kinematicsModelElement ) {
|
---|
295 |
|
---|
296 | var url = kinematicsModelElement.getAttribute( 'url' ).replace(/^#/, '');
|
---|
297 | return kinematicsModels[ url.length > 0 ? url : 'kinematics_model0' ];
|
---|
298 |
|
---|
299 | } else {
|
---|
300 |
|
---|
301 | return null;
|
---|
302 |
|
---|
303 | }
|
---|
304 |
|
---|
305 | }
|
---|
306 |
|
---|
307 | function createAnimations() {
|
---|
308 |
|
---|
309 | animData = [];
|
---|
310 |
|
---|
311 | // fill in the keys
|
---|
312 | recurseHierarchy( scene );
|
---|
313 |
|
---|
314 | }
|
---|
315 |
|
---|
316 | function recurseHierarchy( node ) {
|
---|
317 |
|
---|
318 | var n = visualScene.getChildById( node.colladaId, true ),
|
---|
319 | newData = null;
|
---|
320 |
|
---|
321 | if ( n && n.keys ) {
|
---|
322 |
|
---|
323 | newData = {
|
---|
324 | fps: 60,
|
---|
325 | hierarchy: [ {
|
---|
326 | node: n,
|
---|
327 | keys: n.keys,
|
---|
328 | sids: n.sids
|
---|
329 | } ],
|
---|
330 | node: node,
|
---|
331 | name: 'animation_' + node.name,
|
---|
332 | length: 0
|
---|
333 | };
|
---|
334 |
|
---|
335 | animData.push(newData);
|
---|
336 |
|
---|
337 | for ( var i = 0, il = n.keys.length; i < il; i++ ) {
|
---|
338 |
|
---|
339 | newData.length = Math.max( newData.length, n.keys[i].time );
|
---|
340 |
|
---|
341 | }
|
---|
342 |
|
---|
343 | } else {
|
---|
344 |
|
---|
345 | newData = {
|
---|
346 | hierarchy: [ {
|
---|
347 | keys: [],
|
---|
348 | sids: []
|
---|
349 | } ]
|
---|
350 | }
|
---|
351 |
|
---|
352 | }
|
---|
353 |
|
---|
354 | for ( var i = 0, il = node.children.length; i < il; i++ ) {
|
---|
355 |
|
---|
356 | var d = recurseHierarchy( node.children[i] );
|
---|
357 |
|
---|
358 | for ( var j = 0, jl = d.hierarchy.length; j < jl; j ++ ) {
|
---|
359 |
|
---|
360 | newData.hierarchy.push( {
|
---|
361 | keys: [],
|
---|
362 | sids: []
|
---|
363 | } );
|
---|
364 |
|
---|
365 | }
|
---|
366 |
|
---|
367 | }
|
---|
368 |
|
---|
369 | return newData;
|
---|
370 |
|
---|
371 | }
|
---|
372 |
|
---|
373 | function calcAnimationBounds () {
|
---|
374 |
|
---|
375 | var start = 1000000;
|
---|
376 | var end = -start;
|
---|
377 | var frames = 0;
|
---|
378 | var ID;
|
---|
379 | for ( var id in animations ) {
|
---|
380 |
|
---|
381 | var animation = animations[ id ];
|
---|
382 | ID = ID || animation.id;
|
---|
383 | for ( var i = 0; i < animation.sampler.length; i ++ ) {
|
---|
384 |
|
---|
385 | var sampler = animation.sampler[ i ];
|
---|
386 |
|
---|
387 | sampler.create();
|
---|
388 |
|
---|
389 | start = Math.min( start, sampler.startTime );
|
---|
390 | end = Math.max( end, sampler.endTime );
|
---|
391 | frames = Math.max( frames, sampler.input.length );
|
---|
392 |
|
---|
393 | }
|
---|
394 |
|
---|
395 | }
|
---|
396 |
|
---|
397 | return { start:start, end:end, frames:frames,ID:ID };
|
---|
398 |
|
---|
399 | }
|
---|
400 |
|
---|
401 | function createMorph ( geometry, ctrl ) {
|
---|
402 |
|
---|
403 | var morphCtrl = ctrl instanceof InstanceController ? controllers[ ctrl.url ] : ctrl;
|
---|
404 |
|
---|
405 | if ( !morphCtrl || !morphCtrl.morph ) {
|
---|
406 |
|
---|
407 | console.log("could not find morph controller!");
|
---|
408 | return;
|
---|
409 |
|
---|
410 | }
|
---|
411 |
|
---|
412 | var morph = morphCtrl.morph;
|
---|
413 |
|
---|
414 | for ( var i = 0; i < morph.targets.length; i ++ ) {
|
---|
415 |
|
---|
416 | var target_id = morph.targets[ i ];
|
---|
417 | var daeGeometry = geometries[ target_id ];
|
---|
418 |
|
---|
419 | if ( !daeGeometry.mesh ||
|
---|
420 | !daeGeometry.mesh.primitives ||
|
---|
421 | !daeGeometry.mesh.primitives.length ) {
|
---|
422 | continue;
|
---|
423 | }
|
---|
424 |
|
---|
425 | var target = daeGeometry.mesh.primitives[ 0 ].geometry;
|
---|
426 |
|
---|
427 | if ( target.vertices.length === geometry.vertices.length ) {
|
---|
428 |
|
---|
429 | geometry.morphTargets.push( { name: "target_1", vertices: target.vertices } );
|
---|
430 |
|
---|
431 | }
|
---|
432 |
|
---|
433 | }
|
---|
434 |
|
---|
435 | geometry.morphTargets.push( { name: "target_Z", vertices: geometry.vertices } );
|
---|
436 |
|
---|
437 | };
|
---|
438 |
|
---|
439 | function createSkin ( geometry, ctrl, applyBindShape ) {
|
---|
440 |
|
---|
441 | var skinCtrl = controllers[ ctrl.url ];
|
---|
442 |
|
---|
443 | if ( !skinCtrl || !skinCtrl.skin ) {
|
---|
444 |
|
---|
445 | console.log( "could not find skin controller!" );
|
---|
446 | return;
|
---|
447 |
|
---|
448 | }
|
---|
449 |
|
---|
450 | if ( !ctrl.skeleton || !ctrl.skeleton.length ) {
|
---|
451 |
|
---|
452 | console.log( "could not find the skeleton for the skin!" );
|
---|
453 | return;
|
---|
454 |
|
---|
455 | }
|
---|
456 |
|
---|
457 | var skin = skinCtrl.skin;
|
---|
458 | var skeleton = visualScene.getChildById( ctrl.skeleton[ 0 ] );
|
---|
459 | var hierarchy = [];
|
---|
460 |
|
---|
461 | applyBindShape = applyBindShape !== undefined ? applyBindShape : true;
|
---|
462 |
|
---|
463 | var bones = [];
|
---|
464 | geometry.skinWeights = [];
|
---|
465 | geometry.skinIndices = [];
|
---|
466 |
|
---|
467 | //createBones( geometry.bones, skin, hierarchy, skeleton, null, -1 );
|
---|
468 | //createWeights( skin, geometry.bones, geometry.skinIndices, geometry.skinWeights );
|
---|
469 |
|
---|
470 | /*
|
---|
471 | geometry.animation = {
|
---|
472 | name: 'take_001',
|
---|
473 | fps: 30,
|
---|
474 | length: 2,
|
---|
475 | JIT: true,
|
---|
476 | hierarchy: hierarchy
|
---|
477 | };
|
---|
478 | */
|
---|
479 |
|
---|
480 | if ( applyBindShape ) {
|
---|
481 |
|
---|
482 | for ( var i = 0; i < geometry.vertices.length; i ++ ) {
|
---|
483 |
|
---|
484 | geometry.vertices[ i ].applyMatrix4( skin.bindShapeMatrix );
|
---|
485 |
|
---|
486 | }
|
---|
487 |
|
---|
488 | }
|
---|
489 |
|
---|
490 | }
|
---|
491 |
|
---|
492 | function setupSkeleton ( node, bones, frame, parent ) {
|
---|
493 |
|
---|
494 | node.world = node.world || new THREE.Matrix4();
|
---|
495 | node.localworld = node.localworld || new THREE.Matrix4();
|
---|
496 | node.world.copy( node.matrix );
|
---|
497 | node.localworld.copy( node.matrix );
|
---|
498 |
|
---|
499 | if ( node.channels && node.channels.length ) {
|
---|
500 |
|
---|
501 | var channel = node.channels[ 0 ];
|
---|
502 | var m = channel.sampler.output[ frame ];
|
---|
503 |
|
---|
504 | if ( m instanceof THREE.Matrix4 ) {
|
---|
505 |
|
---|
506 | node.world.copy( m );
|
---|
507 | node.localworld.copy(m);
|
---|
508 | if(frame === 0)
|
---|
509 | node.matrix.copy(m);
|
---|
510 | }
|
---|
511 |
|
---|
512 | }
|
---|
513 |
|
---|
514 | if ( parent ) {
|
---|
515 |
|
---|
516 | node.world.multiplyMatrices( parent, node.world );
|
---|
517 |
|
---|
518 | }
|
---|
519 |
|
---|
520 | bones.push( node );
|
---|
521 |
|
---|
522 | for ( var i = 0; i < node.nodes.length; i ++ ) {
|
---|
523 |
|
---|
524 | setupSkeleton( node.nodes[ i ], bones, frame, node.world );
|
---|
525 |
|
---|
526 | }
|
---|
527 |
|
---|
528 | }
|
---|
529 |
|
---|
530 | function setupSkinningMatrices ( bones, skin ) {
|
---|
531 |
|
---|
532 | // FIXME: this is dumb...
|
---|
533 |
|
---|
534 | for ( var i = 0; i < bones.length; i ++ ) {
|
---|
535 |
|
---|
536 | var bone = bones[ i ];
|
---|
537 | var found = -1;
|
---|
538 |
|
---|
539 | if ( bone.type != 'JOINT' ) continue;
|
---|
540 |
|
---|
541 | for ( var j = 0; j < skin.joints.length; j ++ ) {
|
---|
542 |
|
---|
543 | if ( bone.sid === skin.joints[ j ] ) {
|
---|
544 |
|
---|
545 | found = j;
|
---|
546 | break;
|
---|
547 |
|
---|
548 | }
|
---|
549 |
|
---|
550 | }
|
---|
551 |
|
---|
552 | if ( found >= 0 ) {
|
---|
553 |
|
---|
554 | var inv = skin.invBindMatrices[ found ];
|
---|
555 |
|
---|
556 | bone.invBindMatrix = inv;
|
---|
557 | bone.skinningMatrix = new THREE.Matrix4();
|
---|
558 | bone.skinningMatrix.multiplyMatrices(bone.world, inv); // (IBMi * JMi)
|
---|
559 | bone.animatrix = new THREE.Matrix4();
|
---|
560 |
|
---|
561 | bone.animatrix.copy(bone.localworld);
|
---|
562 | bone.weights = [];
|
---|
563 |
|
---|
564 | for ( var j = 0; j < skin.weights.length; j ++ ) {
|
---|
565 |
|
---|
566 | for (var k = 0; k < skin.weights[ j ].length; k ++ ) {
|
---|
567 |
|
---|
568 | var w = skin.weights[ j ][ k ];
|
---|
569 |
|
---|
570 | if ( w.joint === found ) {
|
---|
571 |
|
---|
572 | bone.weights.push( w );
|
---|
573 |
|
---|
574 | }
|
---|
575 |
|
---|
576 | }
|
---|
577 |
|
---|
578 | }
|
---|
579 |
|
---|
580 | } else {
|
---|
581 |
|
---|
582 | console.warn( "ColladaLoader: Could not find joint '" + bone.sid + "'." );
|
---|
583 |
|
---|
584 | bone.skinningMatrix = new THREE.Matrix4();
|
---|
585 | bone.weights = [];
|
---|
586 |
|
---|
587 | }
|
---|
588 | }
|
---|
589 |
|
---|
590 | }
|
---|
591 |
|
---|
592 | //Walk the Collada tree and flatten the bones into a list, extract the position, quat and scale from the matrix
|
---|
593 | function flattenSkeleton(skeleton) {
|
---|
594 |
|
---|
595 | var list = [];
|
---|
596 | var walk = function(parentid, node, list) {
|
---|
597 |
|
---|
598 | var bone = {};
|
---|
599 | bone.name = node.sid;
|
---|
600 | bone.parent = parentid;
|
---|
601 | bone.matrix = node.matrix;
|
---|
602 | var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
|
---|
603 | bone.matrix.decompose(data[0],data[1],data[2]);
|
---|
604 |
|
---|
605 | bone.pos = [data[0].x,data[0].y,data[0].z];
|
---|
606 |
|
---|
607 | bone.scl = [data[2].x,data[2].y,data[2].z];
|
---|
608 | bone.rotq = [data[1].x,data[1].y,data[1].z,data[1].w];
|
---|
609 | list.push(bone);
|
---|
610 |
|
---|
611 | for(var i in node.nodes) {
|
---|
612 |
|
---|
613 | walk(node.sid,node.nodes[i],list);
|
---|
614 |
|
---|
615 | }
|
---|
616 |
|
---|
617 | };
|
---|
618 |
|
---|
619 | walk(-1,skeleton,list);
|
---|
620 | return list;
|
---|
621 |
|
---|
622 | }
|
---|
623 |
|
---|
624 | //Move the vertices into the pose that is proper for the start of the animation
|
---|
625 | function skinToBindPose(geometry,skeleton,skinController) {
|
---|
626 |
|
---|
627 | var bones = [];
|
---|
628 | setupSkeleton( skeleton, bones, -1 );
|
---|
629 | setupSkinningMatrices( bones, skinController.skin );
|
---|
630 | v = new THREE.Vector3();
|
---|
631 | var skinned = [];
|
---|
632 |
|
---|
633 | for(var i =0; i < geometry.vertices.length; i++) {
|
---|
634 |
|
---|
635 | skinned.push(new THREE.Vector3());
|
---|
636 |
|
---|
637 | }
|
---|
638 |
|
---|
639 | for ( i = 0; i < bones.length; i ++ ) {
|
---|
640 |
|
---|
641 | if ( bones[ i ].type != 'JOINT' ) continue;
|
---|
642 |
|
---|
643 | for ( j = 0; j < bones[ i ].weights.length; j ++ ) {
|
---|
644 |
|
---|
645 | w = bones[ i ].weights[ j ];
|
---|
646 | vidx = w.index;
|
---|
647 | weight = w.weight;
|
---|
648 |
|
---|
649 | o = geometry.vertices[vidx];
|
---|
650 | s = skinned[vidx];
|
---|
651 |
|
---|
652 | v.x = o.x;
|
---|
653 | v.y = o.y;
|
---|
654 | v.z = o.z;
|
---|
655 |
|
---|
656 | v.applyMatrix4( bones[i].skinningMatrix );
|
---|
657 |
|
---|
658 | s.x += (v.x * weight);
|
---|
659 | s.y += (v.y * weight);
|
---|
660 | s.z += (v.z * weight);
|
---|
661 | }
|
---|
662 |
|
---|
663 | }
|
---|
664 |
|
---|
665 | for(var i =0; i < geometry.vertices.length; i++) {
|
---|
666 |
|
---|
667 | geometry.vertices[i] = skinned[i];
|
---|
668 |
|
---|
669 | }
|
---|
670 |
|
---|
671 | }
|
---|
672 |
|
---|
673 | function applySkin ( geometry, instanceCtrl, frame ) {
|
---|
674 |
|
---|
675 | var skinController = controllers[ instanceCtrl.url ];
|
---|
676 |
|
---|
677 | frame = frame !== undefined ? frame : 40;
|
---|
678 |
|
---|
679 | if ( !skinController || !skinController.skin ) {
|
---|
680 |
|
---|
681 | console.log( 'ColladaLoader: Could not find skin controller.' );
|
---|
682 | return;
|
---|
683 |
|
---|
684 | }
|
---|
685 |
|
---|
686 | if ( !instanceCtrl.skeleton || !instanceCtrl.skeleton.length ) {
|
---|
687 |
|
---|
688 | console.log( 'ColladaLoader: Could not find the skeleton for the skin. ' );
|
---|
689 | return;
|
---|
690 |
|
---|
691 | }
|
---|
692 |
|
---|
693 | var animationBounds = calcAnimationBounds();
|
---|
694 | var skeleton = visualScene.getChildById( instanceCtrl.skeleton[0], true ) ||
|
---|
695 | visualScene.getChildBySid( instanceCtrl.skeleton[0], true );
|
---|
696 |
|
---|
697 | //flatten the skeleton into a list of bones
|
---|
698 | var bonelist = flattenSkeleton(skeleton);
|
---|
699 | var joints = skinController.skin.joints;
|
---|
700 |
|
---|
701 | //sort that list so that the order reflects the order in the joint list
|
---|
702 | var sortedbones = [];
|
---|
703 | for(var i = 0; i < joints.length; i++) {
|
---|
704 |
|
---|
705 | for(var j =0; j < bonelist.length; j++) {
|
---|
706 |
|
---|
707 | if(bonelist[j].name === joints[i]) {
|
---|
708 |
|
---|
709 | sortedbones[i] = bonelist[j];
|
---|
710 |
|
---|
711 | }
|
---|
712 |
|
---|
713 | }
|
---|
714 |
|
---|
715 | }
|
---|
716 |
|
---|
717 | //hook up the parents by index instead of name
|
---|
718 | for(var i = 0; i < sortedbones.length; i++) {
|
---|
719 |
|
---|
720 | for(var j =0; j < sortedbones.length; j++) {
|
---|
721 |
|
---|
722 | if(sortedbones[i].parent === sortedbones[j].name) {
|
---|
723 |
|
---|
724 | sortedbones[i].parent = j;
|
---|
725 |
|
---|
726 | }
|
---|
727 |
|
---|
728 | }
|
---|
729 |
|
---|
730 | }
|
---|
731 |
|
---|
732 |
|
---|
733 | var i, j, w, vidx, weight;
|
---|
734 | var v = new THREE.Vector3(), o, s;
|
---|
735 |
|
---|
736 | // move vertices to bind shape
|
---|
737 | for ( i = 0; i < geometry.vertices.length; i ++ ) {
|
---|
738 | geometry.vertices[i].applyMatrix4( skinController.skin.bindShapeMatrix );
|
---|
739 | }
|
---|
740 |
|
---|
741 | var skinIndices = [];
|
---|
742 | var skinWeights = [];
|
---|
743 | var weights = skinController.skin.weights;
|
---|
744 |
|
---|
745 | //hook up the skin weights
|
---|
746 | // TODO - this might be a good place to choose greatest 4 weights
|
---|
747 | for(var i =0; i < weights.length; i++) {
|
---|
748 |
|
---|
749 | var indicies = new THREE.Vector4(weights[i][0]?weights[i][0].joint:0,weights[i][1]?weights[i][1].joint:0,weights[i][2]?weights[i][2].joint:0,weights[i][3]?weights[i][3].joint:0);
|
---|
750 | var weight = new THREE.Vector4(weights[i][0]?weights[i][0].weight:0,weights[i][1]?weights[i][1].weight:0,weights[i][2]?weights[i][2].weight:0,weights[i][3]?weights[i][3].weight:0);
|
---|
751 |
|
---|
752 | skinIndices.push(indicies);
|
---|
753 | skinWeights.push(weight);
|
---|
754 |
|
---|
755 | }
|
---|
756 |
|
---|
757 | geometry.skinIndices = skinIndices;
|
---|
758 | geometry.skinWeights = skinWeights;
|
---|
759 | geometry.bones = sortedbones;
|
---|
760 | // process animation, or simply pose the rig if no animation
|
---|
761 |
|
---|
762 | //create an animation for the animated bones
|
---|
763 | //NOTE: this has no effect when using morphtargets
|
---|
764 | var animationdata = {"name":animationBounds.ID,"fps":30,"length":animationBounds.frames/30,"hierarchy":[]};
|
---|
765 |
|
---|
766 | for(var j =0; j < sortedbones.length; j++) {
|
---|
767 |
|
---|
768 | animationdata.hierarchy.push({parent:sortedbones[j].parent, name:sortedbones[j].name, keys:[]});
|
---|
769 |
|
---|
770 | }
|
---|
771 |
|
---|
772 | console.log( 'ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.' );
|
---|
773 |
|
---|
774 |
|
---|
775 |
|
---|
776 | skinToBindPose(geometry,skeleton,skinController);
|
---|
777 |
|
---|
778 |
|
---|
779 | for ( frame = 0; frame < animationBounds.frames; frame ++ ) {
|
---|
780 |
|
---|
781 | var bones = [];
|
---|
782 | var skinned = [];
|
---|
783 | // process the frame and setup the rig with a fresh
|
---|
784 | // transform, possibly from the bone's animation channel(s)
|
---|
785 |
|
---|
786 | setupSkeleton( skeleton, bones, frame );
|
---|
787 | setupSkinningMatrices( bones, skinController.skin );
|
---|
788 |
|
---|
789 | for(var i = 0; i < bones.length; i ++) {
|
---|
790 |
|
---|
791 | for(var j = 0; j < animationdata.hierarchy.length; j ++) {
|
---|
792 |
|
---|
793 | if(animationdata.hierarchy[j].name === bones[i].sid) {
|
---|
794 |
|
---|
795 | var key = {};
|
---|
796 | key.time = (frame/30);
|
---|
797 | key.matrix = bones[i].animatrix;
|
---|
798 |
|
---|
799 | if(frame === 0)
|
---|
800 | bones[i].matrix = key.matrix;
|
---|
801 |
|
---|
802 | var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
|
---|
803 | key.matrix.decompose(data[0],data[1],data[2]);
|
---|
804 |
|
---|
805 | key.pos = [data[0].x,data[0].y,data[0].z];
|
---|
806 |
|
---|
807 | key.scl = [data[2].x,data[2].y,data[2].z];
|
---|
808 | key.rot = data[1];
|
---|
809 |
|
---|
810 | animationdata.hierarchy[j].keys.push(key);
|
---|
811 |
|
---|
812 | }
|
---|
813 |
|
---|
814 | }
|
---|
815 |
|
---|
816 | }
|
---|
817 |
|
---|
818 | geometry.animation = animationdata;
|
---|
819 |
|
---|
820 | }
|
---|
821 |
|
---|
822 | };
|
---|
823 |
|
---|
824 | function createKinematics() {
|
---|
825 |
|
---|
826 | if ( kinematicsModel && kinematicsModel.joints.length === 0 ) {
|
---|
827 | kinematics = undefined;
|
---|
828 | return;
|
---|
829 | }
|
---|
830 |
|
---|
831 | var jointMap = {};
|
---|
832 |
|
---|
833 | var _addToMap = function( jointIndex, parentVisualElement ) {
|
---|
834 |
|
---|
835 | var parentVisualElementId = parentVisualElement.getAttribute( 'id' );
|
---|
836 | var colladaNode = visualScene.getChildById( parentVisualElementId, true );
|
---|
837 | var joint = kinematicsModel.joints[ jointIndex ];
|
---|
838 |
|
---|
839 | scene.traverse(function( node ) {
|
---|
840 |
|
---|
841 | if ( node.colladaId == parentVisualElementId ) {
|
---|
842 |
|
---|
843 | jointMap[ jointIndex ] = {
|
---|
844 | node: node,
|
---|
845 | transforms: colladaNode.transforms,
|
---|
846 | joint: joint,
|
---|
847 | position: joint.zeroPosition
|
---|
848 | };
|
---|
849 |
|
---|
850 | }
|
---|
851 |
|
---|
852 | });
|
---|
853 |
|
---|
854 | };
|
---|
855 |
|
---|
856 | kinematics = {
|
---|
857 |
|
---|
858 | joints: kinematicsModel && kinematicsModel.joints,
|
---|
859 |
|
---|
860 | getJointValue: function( jointIndex ) {
|
---|
861 |
|
---|
862 | var jointData = jointMap[ jointIndex ];
|
---|
863 |
|
---|
864 | if ( jointData ) {
|
---|
865 |
|
---|
866 | return jointData.position;
|
---|
867 |
|
---|
868 | } else {
|
---|
869 |
|
---|
870 | console.log( 'getJointValue: joint ' + jointIndex + ' doesn\'t exist' );
|
---|
871 |
|
---|
872 | }
|
---|
873 |
|
---|
874 | },
|
---|
875 |
|
---|
876 | setJointValue: function( jointIndex, value ) {
|
---|
877 |
|
---|
878 | var jointData = jointMap[ jointIndex ];
|
---|
879 |
|
---|
880 | if ( jointData ) {
|
---|
881 |
|
---|
882 | var joint = jointData.joint;
|
---|
883 |
|
---|
884 | if ( value > joint.limits.max || value < joint.limits.min ) {
|
---|
885 |
|
---|
886 | console.log( 'setJointValue: joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ')' );
|
---|
887 |
|
---|
888 | } else if ( joint.static ) {
|
---|
889 |
|
---|
890 | console.log( 'setJointValue: joint ' + jointIndex + ' is static' );
|
---|
891 |
|
---|
892 | } else {
|
---|
893 |
|
---|
894 | var threejsNode = jointData.node;
|
---|
895 | var axis = joint.axis;
|
---|
896 | var transforms = jointData.transforms;
|
---|
897 |
|
---|
898 | var matrix = new THREE.Matrix4();
|
---|
899 |
|
---|
900 | for (i = 0; i < transforms.length; i++ ) {
|
---|
901 |
|
---|
902 | var transform = transforms[ i ];
|
---|
903 |
|
---|
904 | // kinda ghetto joint detection
|
---|
905 | if ( transform.sid && transform.sid.indexOf( 'joint' + jointIndex ) !== -1 ) {
|
---|
906 |
|
---|
907 | // apply actual joint value here
|
---|
908 | switch ( joint.type ) {
|
---|
909 |
|
---|
910 | case 'revolute':
|
---|
911 |
|
---|
912 | matrix.multiply( m1.makeRotationAxis( axis, THREE.Math.degToRad(value) ) );
|
---|
913 | break;
|
---|
914 |
|
---|
915 | case 'prismatic':
|
---|
916 |
|
---|
917 | matrix.multiply( m1.makeTranslation(axis.x * value, axis.y * value, axis.z * value ) );
|
---|
918 | break;
|
---|
919 |
|
---|
920 | default:
|
---|
921 |
|
---|
922 | console.warn( 'setJointValue: unknown joint type: ' + joint.type );
|
---|
923 | break;
|
---|
924 |
|
---|
925 | }
|
---|
926 |
|
---|
927 | } else {
|
---|
928 |
|
---|
929 | var m1 = new THREE.Matrix4();
|
---|
930 |
|
---|
931 | switch ( transform.type ) {
|
---|
932 |
|
---|
933 | case 'matrix':
|
---|
934 |
|
---|
935 | matrix.multiply( transform.obj );
|
---|
936 |
|
---|
937 | break;
|
---|
938 |
|
---|
939 | case 'translate':
|
---|
940 |
|
---|
941 | matrix.multiply( m1.makeTranslation( transform.obj.x, transform.obj.y, transform.obj.z ) );
|
---|
942 |
|
---|
943 | break;
|
---|
944 |
|
---|
945 | case 'rotate':
|
---|
946 |
|
---|
947 | matrix.multiply( m1.makeRotationAxis( transform.obj, transform.angle ) );
|
---|
948 |
|
---|
949 | break;
|
---|
950 |
|
---|
951 | }
|
---|
952 | }
|
---|
953 | }
|
---|
954 |
|
---|
955 | // apply the matrix to the threejs node
|
---|
956 | var elementsFloat32Arr = matrix.elements;
|
---|
957 | var elements = Array.prototype.slice.call( elementsFloat32Arr );
|
---|
958 |
|
---|
959 | var elementsRowMajor = [
|
---|
960 | elements[ 0 ],
|
---|
961 | elements[ 4 ],
|
---|
962 | elements[ 8 ],
|
---|
963 | elements[ 12 ],
|
---|
964 | elements[ 1 ],
|
---|
965 | elements[ 5 ],
|
---|
966 | elements[ 9 ],
|
---|
967 | elements[ 13 ],
|
---|
968 | elements[ 2 ],
|
---|
969 | elements[ 6 ],
|
---|
970 | elements[ 10 ],
|
---|
971 | elements[ 14 ],
|
---|
972 | elements[ 3 ],
|
---|
973 | elements[ 7 ],
|
---|
974 | elements[ 11 ],
|
---|
975 | elements[ 15 ]
|
---|
976 | ];
|
---|
977 |
|
---|
978 | threejsNode.matrix.set.apply( threejsNode.matrix, elementsRowMajor );
|
---|
979 | threejsNode.matrix.decompose( threejsNode.position, threejsNode.quaternion, threejsNode.scale );
|
---|
980 | }
|
---|
981 |
|
---|
982 | } else {
|
---|
983 |
|
---|
984 | console.log( 'setJointValue: joint ' + jointIndex + ' doesn\'t exist' );
|
---|
985 |
|
---|
986 | }
|
---|
987 |
|
---|
988 | }
|
---|
989 |
|
---|
990 | };
|
---|
991 |
|
---|
992 | var element = COLLADA.querySelector('scene instance_kinematics_scene');
|
---|
993 |
|
---|
994 | if ( element ) {
|
---|
995 |
|
---|
996 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
997 |
|
---|
998 | var child = element.childNodes[ i ];
|
---|
999 |
|
---|
1000 | if ( child.nodeType != 1 ) continue;
|
---|
1001 |
|
---|
1002 | switch ( child.nodeName ) {
|
---|
1003 |
|
---|
1004 | case 'bind_joint_axis':
|
---|
1005 |
|
---|
1006 | var visualTarget = child.getAttribute( 'target' ).split( '/' ).pop();
|
---|
1007 | var axis = child.querySelector('axis param').textContent;
|
---|
1008 | var jointIndex = parseInt( axis.split( 'joint' ).pop().split( '.' )[0] );
|
---|
1009 | var visualTargetElement = COLLADA.querySelector( '[sid="' + visualTarget + '"]' );
|
---|
1010 |
|
---|
1011 | if ( visualTargetElement ) {
|
---|
1012 | var parentVisualElement = visualTargetElement.parentElement;
|
---|
1013 | _addToMap(jointIndex, parentVisualElement);
|
---|
1014 | }
|
---|
1015 |
|
---|
1016 | break;
|
---|
1017 |
|
---|
1018 | default:
|
---|
1019 |
|
---|
1020 | break;
|
---|
1021 |
|
---|
1022 | }
|
---|
1023 |
|
---|
1024 | }
|
---|
1025 | }
|
---|
1026 |
|
---|
1027 | };
|
---|
1028 |
|
---|
1029 | function createSceneGraph ( node, parent ) {
|
---|
1030 |
|
---|
1031 | var obj = new THREE.Object3D();
|
---|
1032 | var skinned = false;
|
---|
1033 | var skinController;
|
---|
1034 | var morphController;
|
---|
1035 | var i, j;
|
---|
1036 |
|
---|
1037 | // FIXME: controllers
|
---|
1038 |
|
---|
1039 | for ( i = 0; i < node.controllers.length; i ++ ) {
|
---|
1040 |
|
---|
1041 | var controller = controllers[ node.controllers[ i ].url ];
|
---|
1042 |
|
---|
1043 | switch ( controller.type ) {
|
---|
1044 |
|
---|
1045 | case 'skin':
|
---|
1046 |
|
---|
1047 | if ( geometries[ controller.skin.source ] ) {
|
---|
1048 |
|
---|
1049 | var inst_geom = new InstanceGeometry();
|
---|
1050 |
|
---|
1051 | inst_geom.url = controller.skin.source;
|
---|
1052 | inst_geom.instance_material = node.controllers[ i ].instance_material;
|
---|
1053 |
|
---|
1054 | node.geometries.push( inst_geom );
|
---|
1055 | skinned = true;
|
---|
1056 | skinController = node.controllers[ i ];
|
---|
1057 |
|
---|
1058 | } else if ( controllers[ controller.skin.source ] ) {
|
---|
1059 |
|
---|
1060 | // urgh: controller can be chained
|
---|
1061 | // handle the most basic case...
|
---|
1062 |
|
---|
1063 | var second = controllers[ controller.skin.source ];
|
---|
1064 | morphController = second;
|
---|
1065 | // skinController = node.controllers[i];
|
---|
1066 |
|
---|
1067 | if ( second.morph && geometries[ second.morph.source ] ) {
|
---|
1068 |
|
---|
1069 | var inst_geom = new InstanceGeometry();
|
---|
1070 |
|
---|
1071 | inst_geom.url = second.morph.source;
|
---|
1072 | inst_geom.instance_material = node.controllers[ i ].instance_material;
|
---|
1073 |
|
---|
1074 | node.geometries.push( inst_geom );
|
---|
1075 |
|
---|
1076 | }
|
---|
1077 |
|
---|
1078 | }
|
---|
1079 |
|
---|
1080 | break;
|
---|
1081 |
|
---|
1082 | case 'morph':
|
---|
1083 |
|
---|
1084 | if ( geometries[ controller.morph.source ] ) {
|
---|
1085 |
|
---|
1086 | var inst_geom = new InstanceGeometry();
|
---|
1087 |
|
---|
1088 | inst_geom.url = controller.morph.source;
|
---|
1089 | inst_geom.instance_material = node.controllers[ i ].instance_material;
|
---|
1090 |
|
---|
1091 | node.geometries.push( inst_geom );
|
---|
1092 | morphController = node.controllers[ i ];
|
---|
1093 |
|
---|
1094 | }
|
---|
1095 |
|
---|
1096 | console.log( 'ColladaLoader: Morph-controller partially supported.' );
|
---|
1097 |
|
---|
1098 | default:
|
---|
1099 | break;
|
---|
1100 |
|
---|
1101 | }
|
---|
1102 |
|
---|
1103 | }
|
---|
1104 |
|
---|
1105 | // geometries
|
---|
1106 |
|
---|
1107 | var double_sided_materials = {};
|
---|
1108 |
|
---|
1109 | for ( i = 0; i < node.geometries.length; i ++ ) {
|
---|
1110 |
|
---|
1111 | var instance_geometry = node.geometries[i];
|
---|
1112 | var instance_materials = instance_geometry.instance_material;
|
---|
1113 | var geometry = geometries[ instance_geometry.url ];
|
---|
1114 | var used_materials = {};
|
---|
1115 | var used_materials_array = [];
|
---|
1116 | var num_materials = 0;
|
---|
1117 | var first_material;
|
---|
1118 |
|
---|
1119 | if ( geometry ) {
|
---|
1120 |
|
---|
1121 | if ( !geometry.mesh || !geometry.mesh.primitives )
|
---|
1122 | continue;
|
---|
1123 |
|
---|
1124 | if ( obj.name.length === 0 ) {
|
---|
1125 |
|
---|
1126 | obj.name = geometry.id;
|
---|
1127 |
|
---|
1128 | }
|
---|
1129 |
|
---|
1130 | // collect used fx for this geometry-instance
|
---|
1131 |
|
---|
1132 | if ( instance_materials ) {
|
---|
1133 |
|
---|
1134 | for ( j = 0; j < instance_materials.length; j ++ ) {
|
---|
1135 |
|
---|
1136 | var instance_material = instance_materials[ j ];
|
---|
1137 | var mat = materials[ instance_material.target ];
|
---|
1138 | var effect_id = mat.instance_effect.url;
|
---|
1139 | var shader = effects[ effect_id ].shader;
|
---|
1140 | var material3js = shader.material;
|
---|
1141 |
|
---|
1142 | if ( geometry.doubleSided ) {
|
---|
1143 |
|
---|
1144 | if ( !( instance_material.symbol in double_sided_materials ) ) {
|
---|
1145 |
|
---|
1146 | var _copied_material = material3js.clone();
|
---|
1147 | _copied_material.side = THREE.DoubleSide;
|
---|
1148 | double_sided_materials[ instance_material.symbol ] = _copied_material;
|
---|
1149 |
|
---|
1150 | }
|
---|
1151 |
|
---|
1152 | material3js = double_sided_materials[ instance_material.symbol ];
|
---|
1153 |
|
---|
1154 | }
|
---|
1155 |
|
---|
1156 | material3js.opacity = !material3js.opacity ? 1 : material3js.opacity;
|
---|
1157 | used_materials[ instance_material.symbol ] = num_materials;
|
---|
1158 | used_materials_array.push( material3js );
|
---|
1159 | first_material = material3js;
|
---|
1160 | first_material.name = mat.name === null || mat.name === '' ? mat.id : mat.name;
|
---|
1161 | num_materials ++;
|
---|
1162 |
|
---|
1163 | }
|
---|
1164 |
|
---|
1165 | }
|
---|
1166 |
|
---|
1167 | var mesh;
|
---|
1168 | var material = first_material || new THREE.MeshLambertMaterial( { color: 0xdddddd, side: geometry.doubleSided ? THREE.DoubleSide : THREE.FrontSide } );
|
---|
1169 | var geom = geometry.mesh.geometry3js;
|
---|
1170 |
|
---|
1171 | if ( num_materials > 1 ) {
|
---|
1172 |
|
---|
1173 | material = new THREE.MeshFaceMaterial( used_materials_array );
|
---|
1174 |
|
---|
1175 | for ( j = 0; j < geom.faces.length; j ++ ) {
|
---|
1176 |
|
---|
1177 | var face = geom.faces[ j ];
|
---|
1178 | face.materialIndex = used_materials[ face.daeMaterial ]
|
---|
1179 |
|
---|
1180 | }
|
---|
1181 |
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | if ( skinController !== undefined ) {
|
---|
1185 |
|
---|
1186 |
|
---|
1187 | applySkin( geom, skinController );
|
---|
1188 |
|
---|
1189 | if ( geom.morphTargets.length > 0 ) {
|
---|
1190 |
|
---|
1191 | material.morphTargets = true;
|
---|
1192 | material.skinning = false;
|
---|
1193 |
|
---|
1194 | } else {
|
---|
1195 |
|
---|
1196 | material.morphTargets = false;
|
---|
1197 | material.skinning = true;
|
---|
1198 |
|
---|
1199 | }
|
---|
1200 |
|
---|
1201 |
|
---|
1202 | mesh = new THREE.SkinnedMesh( geom, material, false );
|
---|
1203 |
|
---|
1204 |
|
---|
1205 | //mesh.skeleton = skinController.skeleton;
|
---|
1206 | //mesh.skinController = controllers[ skinController.url ];
|
---|
1207 | //mesh.skinInstanceController = skinController;
|
---|
1208 | mesh.name = 'skin_' + skins.length;
|
---|
1209 |
|
---|
1210 |
|
---|
1211 |
|
---|
1212 | //mesh.animationHandle.setKey(0);
|
---|
1213 | skins.push( mesh );
|
---|
1214 |
|
---|
1215 | } else if ( morphController !== undefined ) {
|
---|
1216 |
|
---|
1217 | createMorph( geom, morphController );
|
---|
1218 |
|
---|
1219 | material.morphTargets = true;
|
---|
1220 |
|
---|
1221 | mesh = new THREE.Mesh( geom, material );
|
---|
1222 | mesh.name = 'morph_' + morphs.length;
|
---|
1223 |
|
---|
1224 | morphs.push( mesh );
|
---|
1225 |
|
---|
1226 | } else {
|
---|
1227 |
|
---|
1228 | if ( geom.isLineStrip === true ) {
|
---|
1229 |
|
---|
1230 | mesh = new THREE.Line( geom );
|
---|
1231 |
|
---|
1232 | } else {
|
---|
1233 |
|
---|
1234 | mesh = new THREE.Mesh( geom, material );
|
---|
1235 |
|
---|
1236 | }
|
---|
1237 |
|
---|
1238 | }
|
---|
1239 |
|
---|
1240 | obj.add(mesh);
|
---|
1241 |
|
---|
1242 | }
|
---|
1243 |
|
---|
1244 | }
|
---|
1245 |
|
---|
1246 | for ( i = 0; i < node.cameras.length; i ++ ) {
|
---|
1247 |
|
---|
1248 | var instance_camera = node.cameras[i];
|
---|
1249 | var cparams = cameras[instance_camera.url];
|
---|
1250 |
|
---|
1251 | var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio),
|
---|
1252 | parseFloat(cparams.znear), parseFloat(cparams.zfar));
|
---|
1253 |
|
---|
1254 | obj.add(cam);
|
---|
1255 | }
|
---|
1256 |
|
---|
1257 | for ( i = 0; i < node.lights.length; i ++ ) {
|
---|
1258 |
|
---|
1259 | var light = null;
|
---|
1260 | var instance_light = node.lights[i];
|
---|
1261 | var lparams = lights[instance_light.url];
|
---|
1262 |
|
---|
1263 | if ( lparams && lparams.technique ) {
|
---|
1264 |
|
---|
1265 | var color = lparams.color.getHex();
|
---|
1266 | var intensity = lparams.intensity;
|
---|
1267 | var distance = lparams.distance;
|
---|
1268 | var angle = lparams.falloff_angle;
|
---|
1269 | var exponent; // Intentionally undefined, don't know what this is yet
|
---|
1270 |
|
---|
1271 | switch ( lparams.technique ) {
|
---|
1272 |
|
---|
1273 | case 'directional':
|
---|
1274 |
|
---|
1275 | light = new THREE.DirectionalLight( color, intensity, distance );
|
---|
1276 | light.position.set(0, 0, 1);
|
---|
1277 | break;
|
---|
1278 |
|
---|
1279 | case 'point':
|
---|
1280 |
|
---|
1281 | light = new THREE.PointLight( color, intensity, distance );
|
---|
1282 | break;
|
---|
1283 |
|
---|
1284 | case 'spot':
|
---|
1285 |
|
---|
1286 | light = new THREE.SpotLight( color, intensity, distance, angle, exponent );
|
---|
1287 | light.position.set(0, 0, 1);
|
---|
1288 | break;
|
---|
1289 |
|
---|
1290 | case 'ambient':
|
---|
1291 |
|
---|
1292 | light = new THREE.AmbientLight( color );
|
---|
1293 | break;
|
---|
1294 |
|
---|
1295 | }
|
---|
1296 |
|
---|
1297 | }
|
---|
1298 |
|
---|
1299 | if (light) {
|
---|
1300 | obj.add(light);
|
---|
1301 | }
|
---|
1302 | }
|
---|
1303 |
|
---|
1304 | obj.name = node.name || node.id || "";
|
---|
1305 | obj.colladaId = node.id || "";
|
---|
1306 | obj.layer = node.layer || "";
|
---|
1307 | obj.matrix = node.matrix;
|
---|
1308 | obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
|
---|
1309 |
|
---|
1310 | if ( options.centerGeometry && obj.geometry ) {
|
---|
1311 |
|
---|
1312 | var delta = obj.geometry.center();
|
---|
1313 | delta.multiply( obj.scale );
|
---|
1314 | delta.applyQuaternion( obj.quaternion );
|
---|
1315 |
|
---|
1316 | obj.position.sub( delta );
|
---|
1317 |
|
---|
1318 | }
|
---|
1319 |
|
---|
1320 | for ( i = 0; i < node.nodes.length; i ++ ) {
|
---|
1321 |
|
---|
1322 | obj.add( createSceneGraph( node.nodes[i], node ) );
|
---|
1323 |
|
---|
1324 | }
|
---|
1325 |
|
---|
1326 | return obj;
|
---|
1327 |
|
---|
1328 | };
|
---|
1329 |
|
---|
1330 | function getJointId( skin, id ) {
|
---|
1331 |
|
---|
1332 | for ( var i = 0; i < skin.joints.length; i ++ ) {
|
---|
1333 |
|
---|
1334 | if ( skin.joints[ i ] === id ) {
|
---|
1335 |
|
---|
1336 | return i;
|
---|
1337 |
|
---|
1338 | }
|
---|
1339 |
|
---|
1340 | }
|
---|
1341 |
|
---|
1342 | };
|
---|
1343 |
|
---|
1344 | function getLibraryNode( id ) {
|
---|
1345 |
|
---|
1346 | var nodes = COLLADA.querySelectorAll('library_nodes node');
|
---|
1347 |
|
---|
1348 | for ( var i = 0; i < nodes.length; i++ ) {
|
---|
1349 |
|
---|
1350 | var attObj = nodes[i].attributes.getNamedItem('id');
|
---|
1351 | if ( attObj && attObj.value === id ) {
|
---|
1352 | return nodes[i];
|
---|
1353 | }
|
---|
1354 | }
|
---|
1355 |
|
---|
1356 | return undefined;
|
---|
1357 |
|
---|
1358 | };
|
---|
1359 |
|
---|
1360 | function getChannelsForNode ( node ) {
|
---|
1361 |
|
---|
1362 | var channels = [];
|
---|
1363 | var startTime = 1000000;
|
---|
1364 | var endTime = -1000000;
|
---|
1365 |
|
---|
1366 | for ( var id in animations ) {
|
---|
1367 |
|
---|
1368 | var animation = animations[id];
|
---|
1369 |
|
---|
1370 | for ( var i = 0; i < animation.channel.length; i ++ ) {
|
---|
1371 |
|
---|
1372 | var channel = animation.channel[i];
|
---|
1373 | var sampler = animation.sampler[i];
|
---|
1374 | var id = channel.target.split('/')[0];
|
---|
1375 |
|
---|
1376 | if ( id == node.id ) {
|
---|
1377 |
|
---|
1378 | sampler.create();
|
---|
1379 | channel.sampler = sampler;
|
---|
1380 | startTime = Math.min(startTime, sampler.startTime);
|
---|
1381 | endTime = Math.max(endTime, sampler.endTime);
|
---|
1382 | channels.push(channel);
|
---|
1383 |
|
---|
1384 | }
|
---|
1385 |
|
---|
1386 | }
|
---|
1387 |
|
---|
1388 | }
|
---|
1389 |
|
---|
1390 | if ( channels.length ) {
|
---|
1391 |
|
---|
1392 | node.startTime = startTime;
|
---|
1393 | node.endTime = endTime;
|
---|
1394 |
|
---|
1395 | }
|
---|
1396 |
|
---|
1397 | return channels;
|
---|
1398 |
|
---|
1399 | };
|
---|
1400 |
|
---|
1401 | function calcFrameDuration( node ) {
|
---|
1402 |
|
---|
1403 | var minT = 10000000;
|
---|
1404 |
|
---|
1405 | for ( var i = 0; i < node.channels.length; i ++ ) {
|
---|
1406 |
|
---|
1407 | var sampler = node.channels[i].sampler;
|
---|
1408 |
|
---|
1409 | for ( var j = 0; j < sampler.input.length - 1; j ++ ) {
|
---|
1410 |
|
---|
1411 | var t0 = sampler.input[ j ];
|
---|
1412 | var t1 = sampler.input[ j + 1 ];
|
---|
1413 | minT = Math.min( minT, t1 - t0 );
|
---|
1414 |
|
---|
1415 | }
|
---|
1416 | }
|
---|
1417 |
|
---|
1418 | return minT;
|
---|
1419 |
|
---|
1420 | };
|
---|
1421 |
|
---|
1422 | function calcMatrixAt( node, t ) {
|
---|
1423 |
|
---|
1424 | var animated = {};
|
---|
1425 |
|
---|
1426 | var i, j;
|
---|
1427 |
|
---|
1428 | for ( i = 0; i < node.channels.length; i ++ ) {
|
---|
1429 |
|
---|
1430 | var channel = node.channels[ i ];
|
---|
1431 | animated[ channel.sid ] = channel;
|
---|
1432 |
|
---|
1433 | }
|
---|
1434 |
|
---|
1435 | var matrix = new THREE.Matrix4();
|
---|
1436 |
|
---|
1437 | for ( i = 0; i < node.transforms.length; i ++ ) {
|
---|
1438 |
|
---|
1439 | var transform = node.transforms[ i ];
|
---|
1440 | var channel = animated[ transform.sid ];
|
---|
1441 |
|
---|
1442 | if ( channel !== undefined ) {
|
---|
1443 |
|
---|
1444 | var sampler = channel.sampler;
|
---|
1445 | var value;
|
---|
1446 |
|
---|
1447 | for ( j = 0; j < sampler.input.length - 1; j ++ ) {
|
---|
1448 |
|
---|
1449 | if ( sampler.input[ j + 1 ] > t ) {
|
---|
1450 |
|
---|
1451 | value = sampler.output[ j ];
|
---|
1452 | //console.log(value.flatten)
|
---|
1453 | break;
|
---|
1454 |
|
---|
1455 | }
|
---|
1456 |
|
---|
1457 | }
|
---|
1458 |
|
---|
1459 | if ( value !== undefined ) {
|
---|
1460 |
|
---|
1461 | if ( value instanceof THREE.Matrix4 ) {
|
---|
1462 |
|
---|
1463 | matrix.multiplyMatrices( matrix, value );
|
---|
1464 |
|
---|
1465 | } else {
|
---|
1466 |
|
---|
1467 | // FIXME: handle other types
|
---|
1468 |
|
---|
1469 | matrix.multiplyMatrices( matrix, transform.matrix );
|
---|
1470 |
|
---|
1471 | }
|
---|
1472 |
|
---|
1473 | } else {
|
---|
1474 |
|
---|
1475 | matrix.multiplyMatrices( matrix, transform.matrix );
|
---|
1476 |
|
---|
1477 | }
|
---|
1478 |
|
---|
1479 | } else {
|
---|
1480 |
|
---|
1481 | matrix.multiplyMatrices( matrix, transform.matrix );
|
---|
1482 |
|
---|
1483 | }
|
---|
1484 |
|
---|
1485 | }
|
---|
1486 |
|
---|
1487 | return matrix;
|
---|
1488 |
|
---|
1489 | };
|
---|
1490 |
|
---|
1491 | function bakeAnimations ( node ) {
|
---|
1492 |
|
---|
1493 | if ( node.channels && node.channels.length ) {
|
---|
1494 |
|
---|
1495 | var keys = [],
|
---|
1496 | sids = [];
|
---|
1497 |
|
---|
1498 | for ( var i = 0, il = node.channels.length; i < il; i++ ) {
|
---|
1499 |
|
---|
1500 | var channel = node.channels[i],
|
---|
1501 | fullSid = channel.fullSid,
|
---|
1502 | sampler = channel.sampler,
|
---|
1503 | input = sampler.input,
|
---|
1504 | transform = node.getTransformBySid( channel.sid ),
|
---|
1505 | member;
|
---|
1506 |
|
---|
1507 | if ( channel.arrIndices ) {
|
---|
1508 |
|
---|
1509 | member = [];
|
---|
1510 |
|
---|
1511 | for ( var j = 0, jl = channel.arrIndices.length; j < jl; j++ ) {
|
---|
1512 |
|
---|
1513 | member[ j ] = getConvertedIndex( channel.arrIndices[ j ] );
|
---|
1514 |
|
---|
1515 | }
|
---|
1516 |
|
---|
1517 | } else {
|
---|
1518 |
|
---|
1519 | member = getConvertedMember( channel.member );
|
---|
1520 |
|
---|
1521 | }
|
---|
1522 |
|
---|
1523 | if ( transform ) {
|
---|
1524 |
|
---|
1525 | if ( sids.indexOf( fullSid ) === -1 ) {
|
---|
1526 |
|
---|
1527 | sids.push( fullSid );
|
---|
1528 |
|
---|
1529 | }
|
---|
1530 |
|
---|
1531 | for ( var j = 0, jl = input.length; j < jl; j++ ) {
|
---|
1532 |
|
---|
1533 | var time = input[j],
|
---|
1534 | data = sampler.getData( transform.type, j, member ),
|
---|
1535 | key = findKey( keys, time );
|
---|
1536 |
|
---|
1537 | if ( !key ) {
|
---|
1538 |
|
---|
1539 | key = new Key( time );
|
---|
1540 | var timeNdx = findTimeNdx( keys, time );
|
---|
1541 | keys.splice( timeNdx === -1 ? keys.length : timeNdx, 0, key );
|
---|
1542 |
|
---|
1543 | }
|
---|
1544 |
|
---|
1545 | key.addTarget( fullSid, transform, member, data );
|
---|
1546 |
|
---|
1547 | }
|
---|
1548 |
|
---|
1549 | } else {
|
---|
1550 |
|
---|
1551 | console.log( 'Could not find transform "' + channel.sid + '" in node ' + node.id );
|
---|
1552 |
|
---|
1553 | }
|
---|
1554 |
|
---|
1555 | }
|
---|
1556 |
|
---|
1557 | // post process
|
---|
1558 | for ( var i = 0; i < sids.length; i++ ) {
|
---|
1559 |
|
---|
1560 | var sid = sids[ i ];
|
---|
1561 |
|
---|
1562 | for ( var j = 0; j < keys.length; j++ ) {
|
---|
1563 |
|
---|
1564 | var key = keys[ j ];
|
---|
1565 |
|
---|
1566 | if ( !key.hasTarget( sid ) ) {
|
---|
1567 |
|
---|
1568 | interpolateKeys( keys, key, j, sid );
|
---|
1569 |
|
---|
1570 | }
|
---|
1571 |
|
---|
1572 | }
|
---|
1573 |
|
---|
1574 | }
|
---|
1575 |
|
---|
1576 | node.keys = keys;
|
---|
1577 | node.sids = sids;
|
---|
1578 |
|
---|
1579 | }
|
---|
1580 |
|
---|
1581 | };
|
---|
1582 |
|
---|
1583 | function findKey ( keys, time) {
|
---|
1584 |
|
---|
1585 | var retVal = null;
|
---|
1586 |
|
---|
1587 | for ( var i = 0, il = keys.length; i < il && retVal === null; i++ ) {
|
---|
1588 |
|
---|
1589 | var key = keys[i];
|
---|
1590 |
|
---|
1591 | if ( key.time === time ) {
|
---|
1592 |
|
---|
1593 | retVal = key;
|
---|
1594 |
|
---|
1595 | } else if ( key.time > time ) {
|
---|
1596 |
|
---|
1597 | break;
|
---|
1598 |
|
---|
1599 | }
|
---|
1600 |
|
---|
1601 | }
|
---|
1602 |
|
---|
1603 | return retVal;
|
---|
1604 |
|
---|
1605 | };
|
---|
1606 |
|
---|
1607 | function findTimeNdx ( keys, time) {
|
---|
1608 |
|
---|
1609 | var ndx = -1;
|
---|
1610 |
|
---|
1611 | for ( var i = 0, il = keys.length; i < il && ndx === -1; i++ ) {
|
---|
1612 |
|
---|
1613 | var key = keys[i];
|
---|
1614 |
|
---|
1615 | if ( key.time >= time ) {
|
---|
1616 |
|
---|
1617 | ndx = i;
|
---|
1618 |
|
---|
1619 | }
|
---|
1620 |
|
---|
1621 | }
|
---|
1622 |
|
---|
1623 | return ndx;
|
---|
1624 |
|
---|
1625 | };
|
---|
1626 |
|
---|
1627 | function interpolateKeys ( keys, key, ndx, fullSid ) {
|
---|
1628 |
|
---|
1629 | var prevKey = getPrevKeyWith( keys, fullSid, ndx ? ndx-1 : 0 ),
|
---|
1630 | nextKey = getNextKeyWith( keys, fullSid, ndx+1 );
|
---|
1631 |
|
---|
1632 | if ( prevKey && nextKey ) {
|
---|
1633 |
|
---|
1634 | var scale = (key.time - prevKey.time) / (nextKey.time - prevKey.time),
|
---|
1635 | prevTarget = prevKey.getTarget( fullSid ),
|
---|
1636 | nextData = nextKey.getTarget( fullSid ).data,
|
---|
1637 | prevData = prevTarget.data,
|
---|
1638 | data;
|
---|
1639 |
|
---|
1640 | if ( prevTarget.type === 'matrix' ) {
|
---|
1641 |
|
---|
1642 | data = prevData;
|
---|
1643 |
|
---|
1644 | } else if ( prevData.length ) {
|
---|
1645 |
|
---|
1646 | data = [];
|
---|
1647 |
|
---|
1648 | for ( var i = 0; i < prevData.length; ++i ) {
|
---|
1649 |
|
---|
1650 | data[ i ] = prevData[ i ] + ( nextData[ i ] - prevData[ i ] ) * scale;
|
---|
1651 |
|
---|
1652 | }
|
---|
1653 |
|
---|
1654 | } else {
|
---|
1655 |
|
---|
1656 | data = prevData + ( nextData - prevData ) * scale;
|
---|
1657 |
|
---|
1658 | }
|
---|
1659 |
|
---|
1660 | key.addTarget( fullSid, prevTarget.transform, prevTarget.member, data );
|
---|
1661 |
|
---|
1662 | }
|
---|
1663 |
|
---|
1664 | };
|
---|
1665 |
|
---|
1666 | // Get next key with given sid
|
---|
1667 |
|
---|
1668 | function getNextKeyWith( keys, fullSid, ndx ) {
|
---|
1669 |
|
---|
1670 | for ( ; ndx < keys.length; ndx++ ) {
|
---|
1671 |
|
---|
1672 | var key = keys[ ndx ];
|
---|
1673 |
|
---|
1674 | if ( key.hasTarget( fullSid ) ) {
|
---|
1675 |
|
---|
1676 | return key;
|
---|
1677 |
|
---|
1678 | }
|
---|
1679 |
|
---|
1680 | }
|
---|
1681 |
|
---|
1682 | return null;
|
---|
1683 |
|
---|
1684 | };
|
---|
1685 |
|
---|
1686 | // Get previous key with given sid
|
---|
1687 |
|
---|
1688 | function getPrevKeyWith( keys, fullSid, ndx ) {
|
---|
1689 |
|
---|
1690 | ndx = ndx >= 0 ? ndx : ndx + keys.length;
|
---|
1691 |
|
---|
1692 | for ( ; ndx >= 0; ndx-- ) {
|
---|
1693 |
|
---|
1694 | var key = keys[ ndx ];
|
---|
1695 |
|
---|
1696 | if ( key.hasTarget( fullSid ) ) {
|
---|
1697 |
|
---|
1698 | return key;
|
---|
1699 |
|
---|
1700 | }
|
---|
1701 |
|
---|
1702 | }
|
---|
1703 |
|
---|
1704 | return null;
|
---|
1705 |
|
---|
1706 | };
|
---|
1707 |
|
---|
1708 | function _Image() {
|
---|
1709 |
|
---|
1710 | this.id = "";
|
---|
1711 | this.init_from = "";
|
---|
1712 |
|
---|
1713 | };
|
---|
1714 |
|
---|
1715 | _Image.prototype.parse = function(element) {
|
---|
1716 |
|
---|
1717 | this.id = element.getAttribute('id');
|
---|
1718 |
|
---|
1719 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1720 |
|
---|
1721 | var child = element.childNodes[ i ];
|
---|
1722 |
|
---|
1723 | if ( child.nodeName === 'init_from' ) {
|
---|
1724 |
|
---|
1725 | this.init_from = child.textContent;
|
---|
1726 |
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 | }
|
---|
1730 |
|
---|
1731 | return this;
|
---|
1732 |
|
---|
1733 | };
|
---|
1734 |
|
---|
1735 | function Controller() {
|
---|
1736 |
|
---|
1737 | this.id = "";
|
---|
1738 | this.name = "";
|
---|
1739 | this.type = "";
|
---|
1740 | this.skin = null;
|
---|
1741 | this.morph = null;
|
---|
1742 |
|
---|
1743 | };
|
---|
1744 |
|
---|
1745 | Controller.prototype.parse = function( element ) {
|
---|
1746 |
|
---|
1747 | this.id = element.getAttribute('id');
|
---|
1748 | this.name = element.getAttribute('name');
|
---|
1749 | this.type = "none";
|
---|
1750 |
|
---|
1751 | for ( var i = 0; i < element.childNodes.length; i++ ) {
|
---|
1752 |
|
---|
1753 | var child = element.childNodes[ i ];
|
---|
1754 |
|
---|
1755 | switch ( child.nodeName ) {
|
---|
1756 |
|
---|
1757 | case 'skin':
|
---|
1758 |
|
---|
1759 | this.skin = (new Skin()).parse(child);
|
---|
1760 | this.type = child.nodeName;
|
---|
1761 | break;
|
---|
1762 |
|
---|
1763 | case 'morph':
|
---|
1764 |
|
---|
1765 | this.morph = (new Morph()).parse(child);
|
---|
1766 | this.type = child.nodeName;
|
---|
1767 | break;
|
---|
1768 |
|
---|
1769 | default:
|
---|
1770 | break;
|
---|
1771 |
|
---|
1772 | }
|
---|
1773 | }
|
---|
1774 |
|
---|
1775 | return this;
|
---|
1776 |
|
---|
1777 | };
|
---|
1778 |
|
---|
1779 | function Morph() {
|
---|
1780 |
|
---|
1781 | this.method = null;
|
---|
1782 | this.source = null;
|
---|
1783 | this.targets = null;
|
---|
1784 | this.weights = null;
|
---|
1785 |
|
---|
1786 | };
|
---|
1787 |
|
---|
1788 | Morph.prototype.parse = function( element ) {
|
---|
1789 |
|
---|
1790 | var sources = {};
|
---|
1791 | var inputs = [];
|
---|
1792 | var i;
|
---|
1793 |
|
---|
1794 | this.method = element.getAttribute( 'method' );
|
---|
1795 | this.source = element.getAttribute( 'source' ).replace( /^#/, '' );
|
---|
1796 |
|
---|
1797 | for ( i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1798 |
|
---|
1799 | var child = element.childNodes[ i ];
|
---|
1800 | if ( child.nodeType != 1 ) continue;
|
---|
1801 |
|
---|
1802 | switch ( child.nodeName ) {
|
---|
1803 |
|
---|
1804 | case 'source':
|
---|
1805 |
|
---|
1806 | var source = ( new Source() ).parse( child );
|
---|
1807 | sources[ source.id ] = source;
|
---|
1808 | break;
|
---|
1809 |
|
---|
1810 | case 'targets':
|
---|
1811 |
|
---|
1812 | inputs = this.parseInputs( child );
|
---|
1813 | break;
|
---|
1814 |
|
---|
1815 | default:
|
---|
1816 |
|
---|
1817 | console.log( child.nodeName );
|
---|
1818 | break;
|
---|
1819 |
|
---|
1820 | }
|
---|
1821 |
|
---|
1822 | }
|
---|
1823 |
|
---|
1824 | for ( i = 0; i < inputs.length; i ++ ) {
|
---|
1825 |
|
---|
1826 | var input = inputs[ i ];
|
---|
1827 | var source = sources[ input.source ];
|
---|
1828 |
|
---|
1829 | switch ( input.semantic ) {
|
---|
1830 |
|
---|
1831 | case 'MORPH_TARGET':
|
---|
1832 |
|
---|
1833 | this.targets = source.read();
|
---|
1834 | break;
|
---|
1835 |
|
---|
1836 | case 'MORPH_WEIGHT':
|
---|
1837 |
|
---|
1838 | this.weights = source.read();
|
---|
1839 | break;
|
---|
1840 |
|
---|
1841 | default:
|
---|
1842 | break;
|
---|
1843 |
|
---|
1844 | }
|
---|
1845 | }
|
---|
1846 |
|
---|
1847 | return this;
|
---|
1848 |
|
---|
1849 | };
|
---|
1850 |
|
---|
1851 | Morph.prototype.parseInputs = function(element) {
|
---|
1852 |
|
---|
1853 | var inputs = [];
|
---|
1854 |
|
---|
1855 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1856 |
|
---|
1857 | var child = element.childNodes[i];
|
---|
1858 | if ( child.nodeType != 1) continue;
|
---|
1859 |
|
---|
1860 | switch ( child.nodeName ) {
|
---|
1861 |
|
---|
1862 | case 'input':
|
---|
1863 |
|
---|
1864 | inputs.push( (new Input()).parse(child) );
|
---|
1865 | break;
|
---|
1866 |
|
---|
1867 | default:
|
---|
1868 | break;
|
---|
1869 | }
|
---|
1870 | }
|
---|
1871 |
|
---|
1872 | return inputs;
|
---|
1873 |
|
---|
1874 | };
|
---|
1875 |
|
---|
1876 | function Skin() {
|
---|
1877 |
|
---|
1878 | this.source = "";
|
---|
1879 | this.bindShapeMatrix = null;
|
---|
1880 | this.invBindMatrices = [];
|
---|
1881 | this.joints = [];
|
---|
1882 | this.weights = [];
|
---|
1883 |
|
---|
1884 | };
|
---|
1885 |
|
---|
1886 | Skin.prototype.parse = function( element ) {
|
---|
1887 |
|
---|
1888 | var sources = {};
|
---|
1889 | var joints, weights;
|
---|
1890 |
|
---|
1891 | this.source = element.getAttribute( 'source' ).replace( /^#/, '' );
|
---|
1892 | this.invBindMatrices = [];
|
---|
1893 | this.joints = [];
|
---|
1894 | this.weights = [];
|
---|
1895 |
|
---|
1896 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1897 |
|
---|
1898 | var child = element.childNodes[i];
|
---|
1899 | if ( child.nodeType != 1 ) continue;
|
---|
1900 |
|
---|
1901 | switch ( child.nodeName ) {
|
---|
1902 |
|
---|
1903 | case 'bind_shape_matrix':
|
---|
1904 |
|
---|
1905 | var f = _floats(child.textContent);
|
---|
1906 | this.bindShapeMatrix = getConvertedMat4( f );
|
---|
1907 | break;
|
---|
1908 |
|
---|
1909 | case 'source':
|
---|
1910 |
|
---|
1911 | var src = new Source().parse(child);
|
---|
1912 | sources[ src.id ] = src;
|
---|
1913 | break;
|
---|
1914 |
|
---|
1915 | case 'joints':
|
---|
1916 |
|
---|
1917 | joints = child;
|
---|
1918 | break;
|
---|
1919 |
|
---|
1920 | case 'vertex_weights':
|
---|
1921 |
|
---|
1922 | weights = child;
|
---|
1923 | break;
|
---|
1924 |
|
---|
1925 | default:
|
---|
1926 |
|
---|
1927 | console.log( child.nodeName );
|
---|
1928 | break;
|
---|
1929 |
|
---|
1930 | }
|
---|
1931 | }
|
---|
1932 |
|
---|
1933 | this.parseJoints( joints, sources );
|
---|
1934 | this.parseWeights( weights, sources );
|
---|
1935 |
|
---|
1936 | return this;
|
---|
1937 |
|
---|
1938 | };
|
---|
1939 |
|
---|
1940 | Skin.prototype.parseJoints = function ( element, sources ) {
|
---|
1941 |
|
---|
1942 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1943 |
|
---|
1944 | var child = element.childNodes[ i ];
|
---|
1945 | if ( child.nodeType != 1 ) continue;
|
---|
1946 |
|
---|
1947 | switch ( child.nodeName ) {
|
---|
1948 |
|
---|
1949 | case 'input':
|
---|
1950 |
|
---|
1951 | var input = ( new Input() ).parse( child );
|
---|
1952 | var source = sources[ input.source ];
|
---|
1953 |
|
---|
1954 | if ( input.semantic === 'JOINT' ) {
|
---|
1955 |
|
---|
1956 | this.joints = source.read();
|
---|
1957 |
|
---|
1958 | } else if ( input.semantic === 'INV_BIND_MATRIX' ) {
|
---|
1959 |
|
---|
1960 | this.invBindMatrices = source.read();
|
---|
1961 |
|
---|
1962 | }
|
---|
1963 |
|
---|
1964 | break;
|
---|
1965 |
|
---|
1966 | default:
|
---|
1967 | break;
|
---|
1968 | }
|
---|
1969 |
|
---|
1970 | }
|
---|
1971 |
|
---|
1972 | };
|
---|
1973 |
|
---|
1974 | Skin.prototype.parseWeights = function ( element, sources ) {
|
---|
1975 |
|
---|
1976 | var v, vcount, inputs = [];
|
---|
1977 |
|
---|
1978 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
1979 |
|
---|
1980 | var child = element.childNodes[ i ];
|
---|
1981 | if ( child.nodeType != 1 ) continue;
|
---|
1982 |
|
---|
1983 | switch ( child.nodeName ) {
|
---|
1984 |
|
---|
1985 | case 'input':
|
---|
1986 |
|
---|
1987 | inputs.push( ( new Input() ).parse( child ) );
|
---|
1988 | break;
|
---|
1989 |
|
---|
1990 | case 'v':
|
---|
1991 |
|
---|
1992 | v = _ints( child.textContent );
|
---|
1993 | break;
|
---|
1994 |
|
---|
1995 | case 'vcount':
|
---|
1996 |
|
---|
1997 | vcount = _ints( child.textContent );
|
---|
1998 | break;
|
---|
1999 |
|
---|
2000 | default:
|
---|
2001 | break;
|
---|
2002 |
|
---|
2003 | }
|
---|
2004 |
|
---|
2005 | }
|
---|
2006 |
|
---|
2007 | var index = 0;
|
---|
2008 |
|
---|
2009 | for ( var i = 0; i < vcount.length; i ++ ) {
|
---|
2010 |
|
---|
2011 | var numBones = vcount[i];
|
---|
2012 | var vertex_weights = [];
|
---|
2013 |
|
---|
2014 | for ( var j = 0; j < numBones; j++ ) {
|
---|
2015 |
|
---|
2016 | var influence = {};
|
---|
2017 |
|
---|
2018 | for ( var k = 0; k < inputs.length; k ++ ) {
|
---|
2019 |
|
---|
2020 | var input = inputs[ k ];
|
---|
2021 | var value = v[ index + input.offset ];
|
---|
2022 |
|
---|
2023 | switch ( input.semantic ) {
|
---|
2024 |
|
---|
2025 | case 'JOINT':
|
---|
2026 |
|
---|
2027 | influence.joint = value;//this.joints[value];
|
---|
2028 | break;
|
---|
2029 |
|
---|
2030 | case 'WEIGHT':
|
---|
2031 |
|
---|
2032 | influence.weight = sources[ input.source ].data[ value ];
|
---|
2033 | break;
|
---|
2034 |
|
---|
2035 | default:
|
---|
2036 | break;
|
---|
2037 |
|
---|
2038 | }
|
---|
2039 |
|
---|
2040 | }
|
---|
2041 |
|
---|
2042 | vertex_weights.push( influence );
|
---|
2043 | index += inputs.length;
|
---|
2044 | }
|
---|
2045 |
|
---|
2046 | for ( var j = 0; j < vertex_weights.length; j ++ ) {
|
---|
2047 |
|
---|
2048 | vertex_weights[ j ].index = i;
|
---|
2049 |
|
---|
2050 | }
|
---|
2051 |
|
---|
2052 | this.weights.push( vertex_weights );
|
---|
2053 |
|
---|
2054 | }
|
---|
2055 |
|
---|
2056 | };
|
---|
2057 |
|
---|
2058 | function VisualScene () {
|
---|
2059 |
|
---|
2060 | this.id = "";
|
---|
2061 | this.name = "";
|
---|
2062 | this.nodes = [];
|
---|
2063 | this.scene = new THREE.Scene();
|
---|
2064 |
|
---|
2065 | };
|
---|
2066 |
|
---|
2067 | VisualScene.prototype.getChildById = function( id, recursive ) {
|
---|
2068 |
|
---|
2069 | for ( var i = 0; i < this.nodes.length; i ++ ) {
|
---|
2070 |
|
---|
2071 | var node = this.nodes[ i ].getChildById( id, recursive );
|
---|
2072 |
|
---|
2073 | if ( node ) {
|
---|
2074 |
|
---|
2075 | return node;
|
---|
2076 |
|
---|
2077 | }
|
---|
2078 |
|
---|
2079 | }
|
---|
2080 |
|
---|
2081 | return null;
|
---|
2082 |
|
---|
2083 | };
|
---|
2084 |
|
---|
2085 | VisualScene.prototype.getChildBySid = function( sid, recursive ) {
|
---|
2086 |
|
---|
2087 | for ( var i = 0; i < this.nodes.length; i ++ ) {
|
---|
2088 |
|
---|
2089 | var node = this.nodes[ i ].getChildBySid( sid, recursive );
|
---|
2090 |
|
---|
2091 | if ( node ) {
|
---|
2092 |
|
---|
2093 | return node;
|
---|
2094 |
|
---|
2095 | }
|
---|
2096 |
|
---|
2097 | }
|
---|
2098 |
|
---|
2099 | return null;
|
---|
2100 |
|
---|
2101 | };
|
---|
2102 |
|
---|
2103 | VisualScene.prototype.parse = function( element ) {
|
---|
2104 |
|
---|
2105 | this.id = element.getAttribute( 'id' );
|
---|
2106 | this.name = element.getAttribute( 'name' );
|
---|
2107 | this.nodes = [];
|
---|
2108 |
|
---|
2109 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2110 |
|
---|
2111 | var child = element.childNodes[ i ];
|
---|
2112 | if ( child.nodeType != 1 ) continue;
|
---|
2113 |
|
---|
2114 | switch ( child.nodeName ) {
|
---|
2115 |
|
---|
2116 | case 'node':
|
---|
2117 |
|
---|
2118 | this.nodes.push( ( new Node() ).parse( child ) );
|
---|
2119 | break;
|
---|
2120 |
|
---|
2121 | default:
|
---|
2122 | break;
|
---|
2123 |
|
---|
2124 | }
|
---|
2125 |
|
---|
2126 | }
|
---|
2127 |
|
---|
2128 | return this;
|
---|
2129 |
|
---|
2130 | };
|
---|
2131 |
|
---|
2132 | function Node() {
|
---|
2133 |
|
---|
2134 | this.id = "";
|
---|
2135 | this.name = "";
|
---|
2136 | this.sid = "";
|
---|
2137 | this.nodes = [];
|
---|
2138 | this.controllers = [];
|
---|
2139 | this.transforms = [];
|
---|
2140 | this.geometries = [];
|
---|
2141 | this.channels = [];
|
---|
2142 | this.matrix = new THREE.Matrix4();
|
---|
2143 |
|
---|
2144 | };
|
---|
2145 |
|
---|
2146 | Node.prototype.getChannelForTransform = function( transformSid ) {
|
---|
2147 |
|
---|
2148 | for ( var i = 0; i < this.channels.length; i ++ ) {
|
---|
2149 |
|
---|
2150 | var channel = this.channels[i];
|
---|
2151 | var parts = channel.target.split('/');
|
---|
2152 | var id = parts.shift();
|
---|
2153 | var sid = parts.shift();
|
---|
2154 | var dotSyntax = (sid.indexOf(".") >= 0);
|
---|
2155 | var arrSyntax = (sid.indexOf("(") >= 0);
|
---|
2156 | var arrIndices;
|
---|
2157 | var member;
|
---|
2158 |
|
---|
2159 | if ( dotSyntax ) {
|
---|
2160 |
|
---|
2161 | parts = sid.split(".");
|
---|
2162 | sid = parts.shift();
|
---|
2163 | member = parts.shift();
|
---|
2164 |
|
---|
2165 | } else if ( arrSyntax ) {
|
---|
2166 |
|
---|
2167 | arrIndices = sid.split("(");
|
---|
2168 | sid = arrIndices.shift();
|
---|
2169 |
|
---|
2170 | for ( var j = 0; j < arrIndices.length; j ++ ) {
|
---|
2171 |
|
---|
2172 | arrIndices[ j ] = parseInt( arrIndices[ j ].replace( /\)/, '' ) );
|
---|
2173 |
|
---|
2174 | }
|
---|
2175 |
|
---|
2176 | }
|
---|
2177 |
|
---|
2178 | if ( sid === transformSid ) {
|
---|
2179 |
|
---|
2180 | channel.info = { sid: sid, dotSyntax: dotSyntax, arrSyntax: arrSyntax, arrIndices: arrIndices };
|
---|
2181 | return channel;
|
---|
2182 |
|
---|
2183 | }
|
---|
2184 |
|
---|
2185 | }
|
---|
2186 |
|
---|
2187 | return null;
|
---|
2188 |
|
---|
2189 | };
|
---|
2190 |
|
---|
2191 | Node.prototype.getChildById = function ( id, recursive ) {
|
---|
2192 |
|
---|
2193 | if ( this.id === id ) {
|
---|
2194 |
|
---|
2195 | return this;
|
---|
2196 |
|
---|
2197 | }
|
---|
2198 |
|
---|
2199 | if ( recursive ) {
|
---|
2200 |
|
---|
2201 | for ( var i = 0; i < this.nodes.length; i ++ ) {
|
---|
2202 |
|
---|
2203 | var n = this.nodes[ i ].getChildById( id, recursive );
|
---|
2204 |
|
---|
2205 | if ( n ) {
|
---|
2206 |
|
---|
2207 | return n;
|
---|
2208 |
|
---|
2209 | }
|
---|
2210 |
|
---|
2211 | }
|
---|
2212 |
|
---|
2213 | }
|
---|
2214 |
|
---|
2215 | return null;
|
---|
2216 |
|
---|
2217 | };
|
---|
2218 |
|
---|
2219 | Node.prototype.getChildBySid = function ( sid, recursive ) {
|
---|
2220 |
|
---|
2221 | if ( this.sid === sid ) {
|
---|
2222 |
|
---|
2223 | return this;
|
---|
2224 |
|
---|
2225 | }
|
---|
2226 |
|
---|
2227 | if ( recursive ) {
|
---|
2228 |
|
---|
2229 | for ( var i = 0; i < this.nodes.length; i ++ ) {
|
---|
2230 |
|
---|
2231 | var n = this.nodes[ i ].getChildBySid( sid, recursive );
|
---|
2232 |
|
---|
2233 | if ( n ) {
|
---|
2234 |
|
---|
2235 | return n;
|
---|
2236 |
|
---|
2237 | }
|
---|
2238 |
|
---|
2239 | }
|
---|
2240 | }
|
---|
2241 |
|
---|
2242 | return null;
|
---|
2243 |
|
---|
2244 | };
|
---|
2245 |
|
---|
2246 | Node.prototype.getTransformBySid = function ( sid ) {
|
---|
2247 |
|
---|
2248 | for ( var i = 0; i < this.transforms.length; i ++ ) {
|
---|
2249 |
|
---|
2250 | if ( this.transforms[ i ].sid === sid ) return this.transforms[ i ];
|
---|
2251 |
|
---|
2252 | }
|
---|
2253 |
|
---|
2254 | return null;
|
---|
2255 |
|
---|
2256 | };
|
---|
2257 |
|
---|
2258 | Node.prototype.parse = function( element ) {
|
---|
2259 |
|
---|
2260 | var url;
|
---|
2261 |
|
---|
2262 | this.id = element.getAttribute('id');
|
---|
2263 | this.sid = element.getAttribute('sid');
|
---|
2264 | this.name = element.getAttribute('name');
|
---|
2265 | this.type = element.getAttribute('type');
|
---|
2266 | this.layer = element.getAttribute('layer');
|
---|
2267 |
|
---|
2268 | this.type = this.type === 'JOINT' ? this.type : 'NODE';
|
---|
2269 |
|
---|
2270 | this.nodes = [];
|
---|
2271 | this.transforms = [];
|
---|
2272 | this.geometries = [];
|
---|
2273 | this.cameras = [];
|
---|
2274 | this.lights = [];
|
---|
2275 | this.controllers = [];
|
---|
2276 | this.matrix = new THREE.Matrix4();
|
---|
2277 |
|
---|
2278 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2279 |
|
---|
2280 | var child = element.childNodes[ i ];
|
---|
2281 | if ( child.nodeType != 1 ) continue;
|
---|
2282 |
|
---|
2283 | switch ( child.nodeName ) {
|
---|
2284 |
|
---|
2285 | case 'node':
|
---|
2286 |
|
---|
2287 | this.nodes.push( ( new Node() ).parse( child ) );
|
---|
2288 | break;
|
---|
2289 |
|
---|
2290 | case 'instance_camera':
|
---|
2291 |
|
---|
2292 | this.cameras.push( ( new InstanceCamera() ).parse( child ) );
|
---|
2293 | break;
|
---|
2294 |
|
---|
2295 | case 'instance_controller':
|
---|
2296 |
|
---|
2297 | this.controllers.push( ( new InstanceController() ).parse( child ) );
|
---|
2298 | break;
|
---|
2299 |
|
---|
2300 | case 'instance_geometry':
|
---|
2301 |
|
---|
2302 | this.geometries.push( ( new InstanceGeometry() ).parse( child ) );
|
---|
2303 | break;
|
---|
2304 |
|
---|
2305 | case 'instance_light':
|
---|
2306 |
|
---|
2307 | this.lights.push( ( new InstanceLight() ).parse( child ) );
|
---|
2308 | break;
|
---|
2309 |
|
---|
2310 | case 'instance_node':
|
---|
2311 |
|
---|
2312 | url = child.getAttribute( 'url' ).replace( /^#/, '' );
|
---|
2313 | var iNode = getLibraryNode( url );
|
---|
2314 |
|
---|
2315 | if ( iNode ) {
|
---|
2316 |
|
---|
2317 | this.nodes.push( ( new Node() ).parse( iNode )) ;
|
---|
2318 |
|
---|
2319 | }
|
---|
2320 |
|
---|
2321 | break;
|
---|
2322 |
|
---|
2323 | case 'rotate':
|
---|
2324 | case 'translate':
|
---|
2325 | case 'scale':
|
---|
2326 | case 'matrix':
|
---|
2327 | case 'lookat':
|
---|
2328 | case 'skew':
|
---|
2329 |
|
---|
2330 | this.transforms.push( ( new Transform() ).parse( child ) );
|
---|
2331 | break;
|
---|
2332 |
|
---|
2333 | case 'extra':
|
---|
2334 | break;
|
---|
2335 |
|
---|
2336 | default:
|
---|
2337 |
|
---|
2338 | console.log( child.nodeName );
|
---|
2339 | break;
|
---|
2340 |
|
---|
2341 | }
|
---|
2342 |
|
---|
2343 | }
|
---|
2344 |
|
---|
2345 | this.channels = getChannelsForNode( this );
|
---|
2346 | bakeAnimations( this );
|
---|
2347 |
|
---|
2348 | this.updateMatrix();
|
---|
2349 |
|
---|
2350 | return this;
|
---|
2351 |
|
---|
2352 | };
|
---|
2353 |
|
---|
2354 | Node.prototype.updateMatrix = function () {
|
---|
2355 |
|
---|
2356 | this.matrix.identity();
|
---|
2357 |
|
---|
2358 | for ( var i = 0; i < this.transforms.length; i ++ ) {
|
---|
2359 |
|
---|
2360 | this.transforms[ i ].apply( this.matrix );
|
---|
2361 |
|
---|
2362 | }
|
---|
2363 |
|
---|
2364 | };
|
---|
2365 |
|
---|
2366 | function Transform () {
|
---|
2367 |
|
---|
2368 | this.sid = "";
|
---|
2369 | this.type = "";
|
---|
2370 | this.data = [];
|
---|
2371 | this.obj = null;
|
---|
2372 |
|
---|
2373 | };
|
---|
2374 |
|
---|
2375 | Transform.prototype.parse = function ( element ) {
|
---|
2376 |
|
---|
2377 | this.sid = element.getAttribute( 'sid' );
|
---|
2378 | this.type = element.nodeName;
|
---|
2379 | this.data = _floats( element.textContent );
|
---|
2380 | this.convert();
|
---|
2381 |
|
---|
2382 | return this;
|
---|
2383 |
|
---|
2384 | };
|
---|
2385 |
|
---|
2386 | Transform.prototype.convert = function () {
|
---|
2387 |
|
---|
2388 | switch ( this.type ) {
|
---|
2389 |
|
---|
2390 | case 'matrix':
|
---|
2391 |
|
---|
2392 | this.obj = getConvertedMat4( this.data );
|
---|
2393 | break;
|
---|
2394 |
|
---|
2395 | case 'rotate':
|
---|
2396 |
|
---|
2397 | this.angle = THREE.Math.degToRad( this.data[3] );
|
---|
2398 |
|
---|
2399 | case 'translate':
|
---|
2400 |
|
---|
2401 | fixCoords( this.data, -1 );
|
---|
2402 | this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] );
|
---|
2403 | break;
|
---|
2404 |
|
---|
2405 | case 'scale':
|
---|
2406 |
|
---|
2407 | fixCoords( this.data, 1 );
|
---|
2408 | this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] );
|
---|
2409 | break;
|
---|
2410 |
|
---|
2411 | default:
|
---|
2412 | console.log( 'Can not convert Transform of type ' + this.type );
|
---|
2413 | break;
|
---|
2414 |
|
---|
2415 | }
|
---|
2416 |
|
---|
2417 | };
|
---|
2418 |
|
---|
2419 | Transform.prototype.apply = function () {
|
---|
2420 |
|
---|
2421 | var m1 = new THREE.Matrix4();
|
---|
2422 |
|
---|
2423 | return function ( matrix ) {
|
---|
2424 |
|
---|
2425 | switch ( this.type ) {
|
---|
2426 |
|
---|
2427 | case 'matrix':
|
---|
2428 |
|
---|
2429 | matrix.multiply( this.obj );
|
---|
2430 |
|
---|
2431 | break;
|
---|
2432 |
|
---|
2433 | case 'translate':
|
---|
2434 |
|
---|
2435 | matrix.multiply( m1.makeTranslation( this.obj.x, this.obj.y, this.obj.z ) );
|
---|
2436 |
|
---|
2437 | break;
|
---|
2438 |
|
---|
2439 | case 'rotate':
|
---|
2440 |
|
---|
2441 | matrix.multiply( m1.makeRotationAxis( this.obj, this.angle ) );
|
---|
2442 |
|
---|
2443 | break;
|
---|
2444 |
|
---|
2445 | case 'scale':
|
---|
2446 |
|
---|
2447 | matrix.scale( this.obj );
|
---|
2448 |
|
---|
2449 | break;
|
---|
2450 |
|
---|
2451 | }
|
---|
2452 |
|
---|
2453 | };
|
---|
2454 |
|
---|
2455 | }();
|
---|
2456 |
|
---|
2457 | Transform.prototype.update = function ( data, member ) {
|
---|
2458 |
|
---|
2459 | var members = [ 'X', 'Y', 'Z', 'ANGLE' ];
|
---|
2460 |
|
---|
2461 | switch ( this.type ) {
|
---|
2462 |
|
---|
2463 | case 'matrix':
|
---|
2464 |
|
---|
2465 | if ( ! member ) {
|
---|
2466 |
|
---|
2467 | this.obj.copy( data );
|
---|
2468 |
|
---|
2469 | } else if ( member.length === 1 ) {
|
---|
2470 |
|
---|
2471 | switch ( member[ 0 ] ) {
|
---|
2472 |
|
---|
2473 | case 0:
|
---|
2474 |
|
---|
2475 | this.obj.n11 = data[ 0 ];
|
---|
2476 | this.obj.n21 = data[ 1 ];
|
---|
2477 | this.obj.n31 = data[ 2 ];
|
---|
2478 | this.obj.n41 = data[ 3 ];
|
---|
2479 |
|
---|
2480 | break;
|
---|
2481 |
|
---|
2482 | case 1:
|
---|
2483 |
|
---|
2484 | this.obj.n12 = data[ 0 ];
|
---|
2485 | this.obj.n22 = data[ 1 ];
|
---|
2486 | this.obj.n32 = data[ 2 ];
|
---|
2487 | this.obj.n42 = data[ 3 ];
|
---|
2488 |
|
---|
2489 | break;
|
---|
2490 |
|
---|
2491 | case 2:
|
---|
2492 |
|
---|
2493 | this.obj.n13 = data[ 0 ];
|
---|
2494 | this.obj.n23 = data[ 1 ];
|
---|
2495 | this.obj.n33 = data[ 2 ];
|
---|
2496 | this.obj.n43 = data[ 3 ];
|
---|
2497 |
|
---|
2498 | break;
|
---|
2499 |
|
---|
2500 | case 3:
|
---|
2501 |
|
---|
2502 | this.obj.n14 = data[ 0 ];
|
---|
2503 | this.obj.n24 = data[ 1 ];
|
---|
2504 | this.obj.n34 = data[ 2 ];
|
---|
2505 | this.obj.n44 = data[ 3 ];
|
---|
2506 |
|
---|
2507 | break;
|
---|
2508 |
|
---|
2509 | }
|
---|
2510 |
|
---|
2511 | } else if ( member.length === 2 ) {
|
---|
2512 |
|
---|
2513 | var propName = 'n' + ( member[ 0 ] + 1 ) + ( member[ 1 ] + 1 );
|
---|
2514 | this.obj[ propName ] = data;
|
---|
2515 |
|
---|
2516 | } else {
|
---|
2517 |
|
---|
2518 | console.log('Incorrect addressing of matrix in transform.');
|
---|
2519 |
|
---|
2520 | }
|
---|
2521 |
|
---|
2522 | break;
|
---|
2523 |
|
---|
2524 | case 'translate':
|
---|
2525 | case 'scale':
|
---|
2526 |
|
---|
2527 | if ( Object.prototype.toString.call( member ) === '[object Array]' ) {
|
---|
2528 |
|
---|
2529 | member = members[ member[ 0 ] ];
|
---|
2530 |
|
---|
2531 | }
|
---|
2532 |
|
---|
2533 | switch ( member ) {
|
---|
2534 |
|
---|
2535 | case 'X':
|
---|
2536 |
|
---|
2537 | this.obj.x = data;
|
---|
2538 | break;
|
---|
2539 |
|
---|
2540 | case 'Y':
|
---|
2541 |
|
---|
2542 | this.obj.y = data;
|
---|
2543 | break;
|
---|
2544 |
|
---|
2545 | case 'Z':
|
---|
2546 |
|
---|
2547 | this.obj.z = data;
|
---|
2548 | break;
|
---|
2549 |
|
---|
2550 | default:
|
---|
2551 |
|
---|
2552 | this.obj.x = data[ 0 ];
|
---|
2553 | this.obj.y = data[ 1 ];
|
---|
2554 | this.obj.z = data[ 2 ];
|
---|
2555 | break;
|
---|
2556 |
|
---|
2557 | }
|
---|
2558 |
|
---|
2559 | break;
|
---|
2560 |
|
---|
2561 | case 'rotate':
|
---|
2562 |
|
---|
2563 | if ( Object.prototype.toString.call( member ) === '[object Array]' ) {
|
---|
2564 |
|
---|
2565 | member = members[ member[ 0 ] ];
|
---|
2566 |
|
---|
2567 | }
|
---|
2568 |
|
---|
2569 | switch ( member ) {
|
---|
2570 |
|
---|
2571 | case 'X':
|
---|
2572 |
|
---|
2573 | this.obj.x = data;
|
---|
2574 | break;
|
---|
2575 |
|
---|
2576 | case 'Y':
|
---|
2577 |
|
---|
2578 | this.obj.y = data;
|
---|
2579 | break;
|
---|
2580 |
|
---|
2581 | case 'Z':
|
---|
2582 |
|
---|
2583 | this.obj.z = data;
|
---|
2584 | break;
|
---|
2585 |
|
---|
2586 | case 'ANGLE':
|
---|
2587 |
|
---|
2588 | this.angle = THREE.Math.degToRad( data );
|
---|
2589 | break;
|
---|
2590 |
|
---|
2591 | default:
|
---|
2592 |
|
---|
2593 | this.obj.x = data[ 0 ];
|
---|
2594 | this.obj.y = data[ 1 ];
|
---|
2595 | this.obj.z = data[ 2 ];
|
---|
2596 | this.angle = THREE.Math.degToRad( data[ 3 ] );
|
---|
2597 | break;
|
---|
2598 |
|
---|
2599 | }
|
---|
2600 | break;
|
---|
2601 |
|
---|
2602 | }
|
---|
2603 |
|
---|
2604 | };
|
---|
2605 |
|
---|
2606 | function InstanceController() {
|
---|
2607 |
|
---|
2608 | this.url = "";
|
---|
2609 | this.skeleton = [];
|
---|
2610 | this.instance_material = [];
|
---|
2611 |
|
---|
2612 | };
|
---|
2613 |
|
---|
2614 | InstanceController.prototype.parse = function ( element ) {
|
---|
2615 |
|
---|
2616 | this.url = element.getAttribute('url').replace(/^#/, '');
|
---|
2617 | this.skeleton = [];
|
---|
2618 | this.instance_material = [];
|
---|
2619 |
|
---|
2620 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2621 |
|
---|
2622 | var child = element.childNodes[ i ];
|
---|
2623 | if ( child.nodeType !== 1 ) continue;
|
---|
2624 |
|
---|
2625 | switch ( child.nodeName ) {
|
---|
2626 |
|
---|
2627 | case 'skeleton':
|
---|
2628 |
|
---|
2629 | this.skeleton.push( child.textContent.replace(/^#/, '') );
|
---|
2630 | break;
|
---|
2631 |
|
---|
2632 | case 'bind_material':
|
---|
2633 |
|
---|
2634 | var instances = child.querySelectorAll('instance_material');
|
---|
2635 |
|
---|
2636 | for ( var j = 0; j < instances.length; j ++ ){
|
---|
2637 |
|
---|
2638 | var instance = instances[j];
|
---|
2639 | this.instance_material.push( (new InstanceMaterial()).parse(instance) );
|
---|
2640 |
|
---|
2641 | }
|
---|
2642 |
|
---|
2643 |
|
---|
2644 | break;
|
---|
2645 |
|
---|
2646 | case 'extra':
|
---|
2647 | break;
|
---|
2648 |
|
---|
2649 | default:
|
---|
2650 | break;
|
---|
2651 |
|
---|
2652 | }
|
---|
2653 | }
|
---|
2654 |
|
---|
2655 | return this;
|
---|
2656 |
|
---|
2657 | };
|
---|
2658 |
|
---|
2659 | function InstanceMaterial () {
|
---|
2660 |
|
---|
2661 | this.symbol = "";
|
---|
2662 | this.target = "";
|
---|
2663 |
|
---|
2664 | };
|
---|
2665 |
|
---|
2666 | InstanceMaterial.prototype.parse = function ( element ) {
|
---|
2667 |
|
---|
2668 | this.symbol = element.getAttribute('symbol');
|
---|
2669 | this.target = element.getAttribute('target').replace(/^#/, '');
|
---|
2670 | return this;
|
---|
2671 |
|
---|
2672 | };
|
---|
2673 |
|
---|
2674 | function InstanceGeometry() {
|
---|
2675 |
|
---|
2676 | this.url = "";
|
---|
2677 | this.instance_material = [];
|
---|
2678 |
|
---|
2679 | };
|
---|
2680 |
|
---|
2681 | InstanceGeometry.prototype.parse = function ( element ) {
|
---|
2682 |
|
---|
2683 | this.url = element.getAttribute('url').replace(/^#/, '');
|
---|
2684 | this.instance_material = [];
|
---|
2685 |
|
---|
2686 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2687 |
|
---|
2688 | var child = element.childNodes[i];
|
---|
2689 | if ( child.nodeType != 1 ) continue;
|
---|
2690 |
|
---|
2691 | if ( child.nodeName === 'bind_material' ) {
|
---|
2692 |
|
---|
2693 | var instances = child.querySelectorAll('instance_material');
|
---|
2694 |
|
---|
2695 | for ( var j = 0; j < instances.length; j ++ ) {
|
---|
2696 |
|
---|
2697 | var instance = instances[j];
|
---|
2698 | this.instance_material.push( (new InstanceMaterial()).parse(instance) );
|
---|
2699 |
|
---|
2700 | }
|
---|
2701 |
|
---|
2702 | break;
|
---|
2703 |
|
---|
2704 | }
|
---|
2705 |
|
---|
2706 | }
|
---|
2707 |
|
---|
2708 | return this;
|
---|
2709 |
|
---|
2710 | };
|
---|
2711 |
|
---|
2712 | function Geometry() {
|
---|
2713 |
|
---|
2714 | this.id = "";
|
---|
2715 | this.mesh = null;
|
---|
2716 |
|
---|
2717 | };
|
---|
2718 |
|
---|
2719 | Geometry.prototype.parse = function ( element ) {
|
---|
2720 |
|
---|
2721 | this.id = element.getAttribute('id');
|
---|
2722 |
|
---|
2723 | extractDoubleSided( this, element );
|
---|
2724 |
|
---|
2725 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2726 |
|
---|
2727 | var child = element.childNodes[i];
|
---|
2728 |
|
---|
2729 | switch ( child.nodeName ) {
|
---|
2730 |
|
---|
2731 | case 'mesh':
|
---|
2732 |
|
---|
2733 | this.mesh = (new Mesh(this)).parse(child);
|
---|
2734 | break;
|
---|
2735 |
|
---|
2736 | case 'extra':
|
---|
2737 |
|
---|
2738 | // console.log( child );
|
---|
2739 | break;
|
---|
2740 |
|
---|
2741 | default:
|
---|
2742 | break;
|
---|
2743 | }
|
---|
2744 | }
|
---|
2745 |
|
---|
2746 | return this;
|
---|
2747 |
|
---|
2748 | };
|
---|
2749 |
|
---|
2750 | function Mesh( geometry ) {
|
---|
2751 |
|
---|
2752 | this.geometry = geometry.id;
|
---|
2753 | this.primitives = [];
|
---|
2754 | this.vertices = null;
|
---|
2755 | this.geometry3js = null;
|
---|
2756 |
|
---|
2757 | };
|
---|
2758 |
|
---|
2759 | Mesh.prototype.parse = function ( element ) {
|
---|
2760 |
|
---|
2761 | this.primitives = [];
|
---|
2762 |
|
---|
2763 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
2764 |
|
---|
2765 | var child = element.childNodes[ i ];
|
---|
2766 |
|
---|
2767 | switch ( child.nodeName ) {
|
---|
2768 |
|
---|
2769 | case 'source':
|
---|
2770 |
|
---|
2771 | _source( child );
|
---|
2772 | break;
|
---|
2773 |
|
---|
2774 | case 'vertices':
|
---|
2775 |
|
---|
2776 | this.vertices = ( new Vertices() ).parse( child );
|
---|
2777 | break;
|
---|
2778 |
|
---|
2779 | case 'linestrips':
|
---|
2780 |
|
---|
2781 | this.primitives.push( ( new LineStrips().parse( child ) ) );
|
---|
2782 | break;
|
---|
2783 |
|
---|
2784 | case 'triangles':
|
---|
2785 |
|
---|
2786 | this.primitives.push( ( new Triangles().parse( child ) ) );
|
---|
2787 | break;
|
---|
2788 |
|
---|
2789 | case 'polygons':
|
---|
2790 |
|
---|
2791 | this.primitives.push( ( new Polygons().parse( child ) ) );
|
---|
2792 | break;
|
---|
2793 |
|
---|
2794 | case 'polylist':
|
---|
2795 |
|
---|
2796 | this.primitives.push( ( new Polylist().parse( child ) ) );
|
---|
2797 | break;
|
---|
2798 |
|
---|
2799 | default:
|
---|
2800 | break;
|
---|
2801 |
|
---|
2802 | }
|
---|
2803 |
|
---|
2804 | }
|
---|
2805 |
|
---|
2806 | this.geometry3js = new THREE.Geometry();
|
---|
2807 |
|
---|
2808 | var vertexData = sources[ this.vertices.input['POSITION'].source ].data;
|
---|
2809 |
|
---|
2810 | for ( var i = 0; i < vertexData.length; i += 3 ) {
|
---|
2811 |
|
---|
2812 | this.geometry3js.vertices.push( getConvertedVec3( vertexData, i ).clone() );
|
---|
2813 |
|
---|
2814 | }
|
---|
2815 |
|
---|
2816 | for ( var i = 0; i < this.primitives.length; i ++ ) {
|
---|
2817 |
|
---|
2818 | var primitive = this.primitives[ i ];
|
---|
2819 | primitive.setVertices( this.vertices );
|
---|
2820 | this.handlePrimitive( primitive, this.geometry3js );
|
---|
2821 |
|
---|
2822 | }
|
---|
2823 |
|
---|
2824 | if ( this.geometry3js.calcNormals ) {
|
---|
2825 |
|
---|
2826 | this.geometry3js.computeVertexNormals();
|
---|
2827 | delete this.geometry3js.calcNormals;
|
---|
2828 |
|
---|
2829 | }
|
---|
2830 |
|
---|
2831 | return this;
|
---|
2832 |
|
---|
2833 | };
|
---|
2834 |
|
---|
2835 | Mesh.prototype.handlePrimitive = function ( primitive, geom ) {
|
---|
2836 |
|
---|
2837 | if ( primitive instanceof LineStrips ) {
|
---|
2838 |
|
---|
2839 | // TODO: Handle indices. Maybe easier with BufferGeometry?
|
---|
2840 |
|
---|
2841 | geom.isLineStrip = true;
|
---|
2842 | return;
|
---|
2843 |
|
---|
2844 | }
|
---|
2845 |
|
---|
2846 | var j, k, pList = primitive.p, inputs = primitive.inputs;
|
---|
2847 | var input, index, idx32;
|
---|
2848 | var source, numParams;
|
---|
2849 | var vcIndex = 0, vcount = 3, maxOffset = 0;
|
---|
2850 | var texture_sets = [];
|
---|
2851 |
|
---|
2852 | for ( j = 0; j < inputs.length; j ++ ) {
|
---|
2853 |
|
---|
2854 | input = inputs[ j ];
|
---|
2855 |
|
---|
2856 | var offset = input.offset + 1;
|
---|
2857 | maxOffset = (maxOffset < offset)? offset : maxOffset;
|
---|
2858 |
|
---|
2859 | switch ( input.semantic ) {
|
---|
2860 |
|
---|
2861 | case 'TEXCOORD':
|
---|
2862 | texture_sets.push( input.set );
|
---|
2863 | break;
|
---|
2864 |
|
---|
2865 | }
|
---|
2866 |
|
---|
2867 | }
|
---|
2868 |
|
---|
2869 | for ( var pCount = 0; pCount < pList.length; ++pCount ) {
|
---|
2870 |
|
---|
2871 | var p = pList[ pCount ], i = 0;
|
---|
2872 |
|
---|
2873 | while ( i < p.length ) {
|
---|
2874 |
|
---|
2875 | var vs = [];
|
---|
2876 | var ns = [];
|
---|
2877 | var ts = null;
|
---|
2878 | var cs = [];
|
---|
2879 |
|
---|
2880 | if ( primitive.vcount ) {
|
---|
2881 |
|
---|
2882 | vcount = primitive.vcount.length ? primitive.vcount[ vcIndex ++ ] : primitive.vcount;
|
---|
2883 |
|
---|
2884 | } else {
|
---|
2885 |
|
---|
2886 | vcount = p.length / maxOffset;
|
---|
2887 |
|
---|
2888 | }
|
---|
2889 |
|
---|
2890 |
|
---|
2891 | for ( j = 0; j < vcount; j ++ ) {
|
---|
2892 |
|
---|
2893 | for ( k = 0; k < inputs.length; k ++ ) {
|
---|
2894 |
|
---|
2895 | input = inputs[ k ];
|
---|
2896 | source = sources[ input.source ];
|
---|
2897 |
|
---|
2898 | index = p[ i + ( j * maxOffset ) + input.offset ];
|
---|
2899 | numParams = source.accessor.params.length;
|
---|
2900 | idx32 = index * numParams;
|
---|
2901 |
|
---|
2902 | switch ( input.semantic ) {
|
---|
2903 |
|
---|
2904 | case 'VERTEX':
|
---|
2905 |
|
---|
2906 | vs.push( index );
|
---|
2907 |
|
---|
2908 | break;
|
---|
2909 |
|
---|
2910 | case 'NORMAL':
|
---|
2911 |
|
---|
2912 | ns.push( getConvertedVec3( source.data, idx32 ) );
|
---|
2913 |
|
---|
2914 | break;
|
---|
2915 |
|
---|
2916 | case 'TEXCOORD':
|
---|
2917 |
|
---|
2918 | ts = ts || { };
|
---|
2919 | if ( ts[ input.set ] === undefined ) ts[ input.set ] = [];
|
---|
2920 | // invert the V
|
---|
2921 | ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], source.data[ idx32 + 1 ] ) );
|
---|
2922 |
|
---|
2923 | break;
|
---|
2924 |
|
---|
2925 | case 'COLOR':
|
---|
2926 |
|
---|
2927 | cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) );
|
---|
2928 |
|
---|
2929 | break;
|
---|
2930 |
|
---|
2931 | default:
|
---|
2932 |
|
---|
2933 | break;
|
---|
2934 |
|
---|
2935 | }
|
---|
2936 |
|
---|
2937 | }
|
---|
2938 |
|
---|
2939 | }
|
---|
2940 |
|
---|
2941 | if ( ns.length === 0 ) {
|
---|
2942 |
|
---|
2943 | // check the vertices inputs
|
---|
2944 | input = this.vertices.input.NORMAL;
|
---|
2945 |
|
---|
2946 | if ( input ) {
|
---|
2947 |
|
---|
2948 | source = sources[ input.source ];
|
---|
2949 | numParams = source.accessor.params.length;
|
---|
2950 |
|
---|
2951 | for ( var ndx = 0, len = vs.length; ndx < len; ndx++ ) {
|
---|
2952 |
|
---|
2953 | ns.push( getConvertedVec3( source.data, vs[ ndx ] * numParams ) );
|
---|
2954 |
|
---|
2955 | }
|
---|
2956 |
|
---|
2957 | } else {
|
---|
2958 |
|
---|
2959 | geom.calcNormals = true;
|
---|
2960 |
|
---|
2961 | }
|
---|
2962 |
|
---|
2963 | }
|
---|
2964 |
|
---|
2965 | if ( !ts ) {
|
---|
2966 |
|
---|
2967 | ts = { };
|
---|
2968 | // check the vertices inputs
|
---|
2969 | input = this.vertices.input.TEXCOORD;
|
---|
2970 |
|
---|
2971 | if ( input ) {
|
---|
2972 |
|
---|
2973 | texture_sets.push( input.set );
|
---|
2974 | source = sources[ input.source ];
|
---|
2975 | numParams = source.accessor.params.length;
|
---|
2976 |
|
---|
2977 | for ( var ndx = 0, len = vs.length; ndx < len; ndx++ ) {
|
---|
2978 |
|
---|
2979 | idx32 = vs[ ndx ] * numParams;
|
---|
2980 | if ( ts[ input.set ] === undefined ) ts[ input.set ] = [ ];
|
---|
2981 | // invert the V
|
---|
2982 | ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], 1.0 - source.data[ idx32 + 1 ] ) );
|
---|
2983 |
|
---|
2984 | }
|
---|
2985 |
|
---|
2986 | }
|
---|
2987 |
|
---|
2988 | }
|
---|
2989 |
|
---|
2990 | if ( cs.length === 0 ) {
|
---|
2991 |
|
---|
2992 | // check the vertices inputs
|
---|
2993 | input = this.vertices.input.COLOR;
|
---|
2994 |
|
---|
2995 | if ( input ) {
|
---|
2996 |
|
---|
2997 | source = sources[ input.source ];
|
---|
2998 | numParams = source.accessor.params.length;
|
---|
2999 |
|
---|
3000 | for ( var ndx = 0, len = vs.length; ndx < len; ndx++ ) {
|
---|
3001 |
|
---|
3002 | idx32 = vs[ ndx ] * numParams;
|
---|
3003 | cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) );
|
---|
3004 |
|
---|
3005 | }
|
---|
3006 |
|
---|
3007 | }
|
---|
3008 |
|
---|
3009 | }
|
---|
3010 |
|
---|
3011 | var face = null, faces = [], uv, uvArr;
|
---|
3012 |
|
---|
3013 | if ( vcount === 3 ) {
|
---|
3014 |
|
---|
3015 | faces.push( new THREE.Face3( vs[0], vs[1], vs[2], ns, cs.length ? cs : new THREE.Color() ) );
|
---|
3016 |
|
---|
3017 | } else if ( vcount === 4 ) {
|
---|
3018 |
|
---|
3019 | faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ns[0], ns[1], ns[3]], cs.length ? [cs[0], cs[1], cs[3]] : new THREE.Color() ) );
|
---|
3020 |
|
---|
3021 | faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ns[1], ns[2], ns[3]], cs.length ? [cs[1], cs[2], cs[3]] : new THREE.Color() ) );
|
---|
3022 |
|
---|
3023 | } else if ( vcount > 4 && options.subdivideFaces ) {
|
---|
3024 |
|
---|
3025 | var clr = cs.length ? cs : new THREE.Color(),
|
---|
3026 | vec1, vec2, vec3, v1, v2, norm;
|
---|
3027 |
|
---|
3028 | // subdivide into multiple Face3s
|
---|
3029 |
|
---|
3030 | for ( k = 1; k < vcount - 1; ) {
|
---|
3031 |
|
---|
3032 | // FIXME: normals don't seem to be quite right
|
---|
3033 |
|
---|
3034 | faces.push( new THREE.Face3( vs[0], vs[k], vs[k+1], [ ns[0], ns[k++], ns[k] ], clr ) );
|
---|
3035 |
|
---|
3036 | }
|
---|
3037 |
|
---|
3038 | }
|
---|
3039 |
|
---|
3040 | if ( faces.length ) {
|
---|
3041 |
|
---|
3042 | for ( var ndx = 0, len = faces.length; ndx < len; ndx ++ ) {
|
---|
3043 |
|
---|
3044 | face = faces[ndx];
|
---|
3045 | face.daeMaterial = primitive.material;
|
---|
3046 | geom.faces.push( face );
|
---|
3047 |
|
---|
3048 | for ( k = 0; k < texture_sets.length; k++ ) {
|
---|
3049 |
|
---|
3050 | uv = ts[ texture_sets[k] ];
|
---|
3051 |
|
---|
3052 | if ( vcount > 4 ) {
|
---|
3053 |
|
---|
3054 | // Grab the right UVs for the vertices in this face
|
---|
3055 | uvArr = [ uv[0], uv[ndx+1], uv[ndx+2] ];
|
---|
3056 |
|
---|
3057 | } else if ( vcount === 4 ) {
|
---|
3058 |
|
---|
3059 | if ( ndx === 0 ) {
|
---|
3060 |
|
---|
3061 | uvArr = [ uv[0], uv[1], uv[3] ];
|
---|
3062 |
|
---|
3063 | } else {
|
---|
3064 |
|
---|
3065 | uvArr = [ uv[1].clone(), uv[2], uv[3].clone() ];
|
---|
3066 |
|
---|
3067 | }
|
---|
3068 |
|
---|
3069 | } else {
|
---|
3070 |
|
---|
3071 | uvArr = [ uv[0], uv[1], uv[2] ];
|
---|
3072 |
|
---|
3073 | }
|
---|
3074 |
|
---|
3075 | if ( geom.faceVertexUvs[k] === undefined ) {
|
---|
3076 |
|
---|
3077 | geom.faceVertexUvs[k] = [];
|
---|
3078 |
|
---|
3079 | }
|
---|
3080 |
|
---|
3081 | geom.faceVertexUvs[k].push( uvArr );
|
---|
3082 |
|
---|
3083 | }
|
---|
3084 |
|
---|
3085 | }
|
---|
3086 |
|
---|
3087 | } else {
|
---|
3088 |
|
---|
3089 | console.log( 'dropped face with vcount ' + vcount + ' for geometry with id: ' + geom.id );
|
---|
3090 |
|
---|
3091 | }
|
---|
3092 |
|
---|
3093 | i += maxOffset * vcount;
|
---|
3094 |
|
---|
3095 | }
|
---|
3096 |
|
---|
3097 | }
|
---|
3098 |
|
---|
3099 | };
|
---|
3100 |
|
---|
3101 | function Polygons () {
|
---|
3102 |
|
---|
3103 | this.material = "";
|
---|
3104 | this.count = 0;
|
---|
3105 | this.inputs = [];
|
---|
3106 | this.vcount = null;
|
---|
3107 | this.p = [];
|
---|
3108 | this.geometry = new THREE.Geometry();
|
---|
3109 |
|
---|
3110 | };
|
---|
3111 |
|
---|
3112 | Polygons.prototype.setVertices = function ( vertices ) {
|
---|
3113 |
|
---|
3114 | for ( var i = 0; i < this.inputs.length; i ++ ) {
|
---|
3115 |
|
---|
3116 | if ( this.inputs[ i ].source === vertices.id ) {
|
---|
3117 |
|
---|
3118 | this.inputs[ i ].source = vertices.input[ 'POSITION' ].source;
|
---|
3119 |
|
---|
3120 | }
|
---|
3121 |
|
---|
3122 | }
|
---|
3123 |
|
---|
3124 | };
|
---|
3125 |
|
---|
3126 | Polygons.prototype.parse = function ( element ) {
|
---|
3127 |
|
---|
3128 | this.material = element.getAttribute( 'material' );
|
---|
3129 | this.count = _attr_as_int( element, 'count', 0 );
|
---|
3130 |
|
---|
3131 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3132 |
|
---|
3133 | var child = element.childNodes[ i ];
|
---|
3134 |
|
---|
3135 | switch ( child.nodeName ) {
|
---|
3136 |
|
---|
3137 | case 'input':
|
---|
3138 |
|
---|
3139 | this.inputs.push( ( new Input() ).parse( element.childNodes[ i ] ) );
|
---|
3140 | break;
|
---|
3141 |
|
---|
3142 | case 'vcount':
|
---|
3143 |
|
---|
3144 | this.vcount = _ints( child.textContent );
|
---|
3145 | break;
|
---|
3146 |
|
---|
3147 | case 'p':
|
---|
3148 |
|
---|
3149 | this.p.push( _ints( child.textContent ) );
|
---|
3150 | break;
|
---|
3151 |
|
---|
3152 | case 'ph':
|
---|
3153 |
|
---|
3154 | console.warn( 'polygon holes not yet supported!' );
|
---|
3155 | break;
|
---|
3156 |
|
---|
3157 | default:
|
---|
3158 | break;
|
---|
3159 |
|
---|
3160 | }
|
---|
3161 |
|
---|
3162 | }
|
---|
3163 |
|
---|
3164 | return this;
|
---|
3165 |
|
---|
3166 | };
|
---|
3167 |
|
---|
3168 | function Polylist () {
|
---|
3169 |
|
---|
3170 | Polygons.call( this );
|
---|
3171 |
|
---|
3172 | this.vcount = [];
|
---|
3173 |
|
---|
3174 | };
|
---|
3175 |
|
---|
3176 | Polylist.prototype = Object.create( Polygons.prototype );
|
---|
3177 |
|
---|
3178 | function LineStrips() {
|
---|
3179 |
|
---|
3180 | Polygons.call( this );
|
---|
3181 |
|
---|
3182 | this.vcount = 1;
|
---|
3183 |
|
---|
3184 | };
|
---|
3185 |
|
---|
3186 | LineStrips.prototype = Object.create( Polygons.prototype );
|
---|
3187 |
|
---|
3188 | function Triangles () {
|
---|
3189 |
|
---|
3190 | Polygons.call( this );
|
---|
3191 |
|
---|
3192 | this.vcount = 3;
|
---|
3193 |
|
---|
3194 | };
|
---|
3195 |
|
---|
3196 | Triangles.prototype = Object.create( Polygons.prototype );
|
---|
3197 |
|
---|
3198 | function Accessor() {
|
---|
3199 |
|
---|
3200 | this.source = "";
|
---|
3201 | this.count = 0;
|
---|
3202 | this.stride = 0;
|
---|
3203 | this.params = [];
|
---|
3204 |
|
---|
3205 | };
|
---|
3206 |
|
---|
3207 | Accessor.prototype.parse = function ( element ) {
|
---|
3208 |
|
---|
3209 | this.params = [];
|
---|
3210 | this.source = element.getAttribute( 'source' );
|
---|
3211 | this.count = _attr_as_int( element, 'count', 0 );
|
---|
3212 | this.stride = _attr_as_int( element, 'stride', 0 );
|
---|
3213 |
|
---|
3214 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3215 |
|
---|
3216 | var child = element.childNodes[ i ];
|
---|
3217 |
|
---|
3218 | if ( child.nodeName === 'param' ) {
|
---|
3219 |
|
---|
3220 | var param = {};
|
---|
3221 | param[ 'name' ] = child.getAttribute( 'name' );
|
---|
3222 | param[ 'type' ] = child.getAttribute( 'type' );
|
---|
3223 | this.params.push( param );
|
---|
3224 |
|
---|
3225 | }
|
---|
3226 |
|
---|
3227 | }
|
---|
3228 |
|
---|
3229 | return this;
|
---|
3230 |
|
---|
3231 | };
|
---|
3232 |
|
---|
3233 | function Vertices() {
|
---|
3234 |
|
---|
3235 | this.input = {};
|
---|
3236 |
|
---|
3237 | };
|
---|
3238 |
|
---|
3239 | Vertices.prototype.parse = function ( element ) {
|
---|
3240 |
|
---|
3241 | this.id = element.getAttribute('id');
|
---|
3242 |
|
---|
3243 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3244 |
|
---|
3245 | if ( element.childNodes[i].nodeName === 'input' ) {
|
---|
3246 |
|
---|
3247 | var input = ( new Input() ).parse( element.childNodes[ i ] );
|
---|
3248 | this.input[ input.semantic ] = input;
|
---|
3249 |
|
---|
3250 | }
|
---|
3251 |
|
---|
3252 | }
|
---|
3253 |
|
---|
3254 | return this;
|
---|
3255 |
|
---|
3256 | };
|
---|
3257 |
|
---|
3258 | function Input () {
|
---|
3259 |
|
---|
3260 | this.semantic = "";
|
---|
3261 | this.offset = 0;
|
---|
3262 | this.source = "";
|
---|
3263 | this.set = 0;
|
---|
3264 |
|
---|
3265 | };
|
---|
3266 |
|
---|
3267 | Input.prototype.parse = function ( element ) {
|
---|
3268 |
|
---|
3269 | this.semantic = element.getAttribute('semantic');
|
---|
3270 | this.source = element.getAttribute('source').replace(/^#/, '');
|
---|
3271 | this.set = _attr_as_int(element, 'set', -1);
|
---|
3272 | this.offset = _attr_as_int(element, 'offset', 0);
|
---|
3273 |
|
---|
3274 | if ( this.semantic === 'TEXCOORD' && this.set < 0 ) {
|
---|
3275 |
|
---|
3276 | this.set = 0;
|
---|
3277 |
|
---|
3278 | }
|
---|
3279 |
|
---|
3280 | return this;
|
---|
3281 |
|
---|
3282 | };
|
---|
3283 |
|
---|
3284 | function Source ( id ) {
|
---|
3285 |
|
---|
3286 | this.id = id;
|
---|
3287 | this.type = null;
|
---|
3288 |
|
---|
3289 | };
|
---|
3290 |
|
---|
3291 | Source.prototype.parse = function ( element ) {
|
---|
3292 |
|
---|
3293 | this.id = element.getAttribute( 'id' );
|
---|
3294 |
|
---|
3295 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3296 |
|
---|
3297 | var child = element.childNodes[i];
|
---|
3298 |
|
---|
3299 | switch ( child.nodeName ) {
|
---|
3300 |
|
---|
3301 | case 'bool_array':
|
---|
3302 |
|
---|
3303 | this.data = _bools( child.textContent );
|
---|
3304 | this.type = child.nodeName;
|
---|
3305 | break;
|
---|
3306 |
|
---|
3307 | case 'float_array':
|
---|
3308 |
|
---|
3309 | this.data = _floats( child.textContent );
|
---|
3310 | this.type = child.nodeName;
|
---|
3311 | break;
|
---|
3312 |
|
---|
3313 | case 'int_array':
|
---|
3314 |
|
---|
3315 | this.data = _ints( child.textContent );
|
---|
3316 | this.type = child.nodeName;
|
---|
3317 | break;
|
---|
3318 |
|
---|
3319 | case 'IDREF_array':
|
---|
3320 | case 'Name_array':
|
---|
3321 |
|
---|
3322 | this.data = _strings( child.textContent );
|
---|
3323 | this.type = child.nodeName;
|
---|
3324 | break;
|
---|
3325 |
|
---|
3326 | case 'technique_common':
|
---|
3327 |
|
---|
3328 | for ( var j = 0; j < child.childNodes.length; j ++ ) {
|
---|
3329 |
|
---|
3330 | if ( child.childNodes[ j ].nodeName === 'accessor' ) {
|
---|
3331 |
|
---|
3332 | this.accessor = ( new Accessor() ).parse( child.childNodes[ j ] );
|
---|
3333 | break;
|
---|
3334 |
|
---|
3335 | }
|
---|
3336 | }
|
---|
3337 | break;
|
---|
3338 |
|
---|
3339 | default:
|
---|
3340 | // console.log(child.nodeName);
|
---|
3341 | break;
|
---|
3342 |
|
---|
3343 | }
|
---|
3344 |
|
---|
3345 | }
|
---|
3346 |
|
---|
3347 | return this;
|
---|
3348 |
|
---|
3349 | };
|
---|
3350 |
|
---|
3351 | Source.prototype.read = function () {
|
---|
3352 |
|
---|
3353 | var result = [];
|
---|
3354 |
|
---|
3355 | //for (var i = 0; i < this.accessor.params.length; i++) {
|
---|
3356 |
|
---|
3357 | var param = this.accessor.params[ 0 ];
|
---|
3358 |
|
---|
3359 | //console.log(param.name + " " + param.type);
|
---|
3360 |
|
---|
3361 | switch ( param.type ) {
|
---|
3362 |
|
---|
3363 | case 'IDREF':
|
---|
3364 | case 'Name': case 'name':
|
---|
3365 | case 'float':
|
---|
3366 |
|
---|
3367 | return this.data;
|
---|
3368 |
|
---|
3369 | case 'float4x4':
|
---|
3370 |
|
---|
3371 | for ( var j = 0; j < this.data.length; j += 16 ) {
|
---|
3372 |
|
---|
3373 | var s = this.data.slice( j, j + 16 );
|
---|
3374 | var m = getConvertedMat4( s );
|
---|
3375 | result.push( m );
|
---|
3376 | }
|
---|
3377 |
|
---|
3378 | break;
|
---|
3379 |
|
---|
3380 | default:
|
---|
3381 |
|
---|
3382 | console.log( 'ColladaLoader: Source: Read dont know how to read ' + param.type + '.' );
|
---|
3383 | break;
|
---|
3384 |
|
---|
3385 | }
|
---|
3386 |
|
---|
3387 | //}
|
---|
3388 |
|
---|
3389 | return result;
|
---|
3390 |
|
---|
3391 | };
|
---|
3392 |
|
---|
3393 | function Material () {
|
---|
3394 |
|
---|
3395 | this.id = "";
|
---|
3396 | this.name = "";
|
---|
3397 | this.instance_effect = null;
|
---|
3398 |
|
---|
3399 | };
|
---|
3400 |
|
---|
3401 | Material.prototype.parse = function ( element ) {
|
---|
3402 |
|
---|
3403 | this.id = element.getAttribute( 'id' );
|
---|
3404 | this.name = element.getAttribute( 'name' );
|
---|
3405 |
|
---|
3406 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3407 |
|
---|
3408 | if ( element.childNodes[ i ].nodeName === 'instance_effect' ) {
|
---|
3409 |
|
---|
3410 | this.instance_effect = ( new InstanceEffect() ).parse( element.childNodes[ i ] );
|
---|
3411 | break;
|
---|
3412 |
|
---|
3413 | }
|
---|
3414 |
|
---|
3415 | }
|
---|
3416 |
|
---|
3417 | return this;
|
---|
3418 |
|
---|
3419 | };
|
---|
3420 |
|
---|
3421 | function ColorOrTexture () {
|
---|
3422 |
|
---|
3423 | this.color = new THREE.Color();
|
---|
3424 | this.color.setRGB( Math.random(), Math.random(), Math.random() );
|
---|
3425 | this.color.a = 1.0;
|
---|
3426 |
|
---|
3427 | this.texture = null;
|
---|
3428 | this.texcoord = null;
|
---|
3429 | this.texOpts = null;
|
---|
3430 |
|
---|
3431 | };
|
---|
3432 |
|
---|
3433 | ColorOrTexture.prototype.isColor = function () {
|
---|
3434 |
|
---|
3435 | return ( this.texture === null );
|
---|
3436 |
|
---|
3437 | };
|
---|
3438 |
|
---|
3439 | ColorOrTexture.prototype.isTexture = function () {
|
---|
3440 |
|
---|
3441 | return ( this.texture != null );
|
---|
3442 |
|
---|
3443 | };
|
---|
3444 |
|
---|
3445 | ColorOrTexture.prototype.parse = function ( element ) {
|
---|
3446 |
|
---|
3447 | if (element.nodeName === 'transparent') {
|
---|
3448 |
|
---|
3449 | this.opaque = element.getAttribute('opaque');
|
---|
3450 |
|
---|
3451 | }
|
---|
3452 |
|
---|
3453 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3454 |
|
---|
3455 | var child = element.childNodes[ i ];
|
---|
3456 | if ( child.nodeType != 1 ) continue;
|
---|
3457 |
|
---|
3458 | switch ( child.nodeName ) {
|
---|
3459 |
|
---|
3460 | case 'color':
|
---|
3461 |
|
---|
3462 | var rgba = _floats( child.textContent );
|
---|
3463 | this.color = new THREE.Color();
|
---|
3464 | this.color.setRGB( rgba[0], rgba[1], rgba[2] );
|
---|
3465 | this.color.a = rgba[3];
|
---|
3466 | break;
|
---|
3467 |
|
---|
3468 | case 'texture':
|
---|
3469 |
|
---|
3470 | this.texture = child.getAttribute('texture');
|
---|
3471 | this.texcoord = child.getAttribute('texcoord');
|
---|
3472 | // Defaults from:
|
---|
3473 | // https://collada.org/mediawiki/index.php/Maya_texture_placement_MAYA_extension
|
---|
3474 | this.texOpts = {
|
---|
3475 | offsetU: 0,
|
---|
3476 | offsetV: 0,
|
---|
3477 | repeatU: 1,
|
---|
3478 | repeatV: 1,
|
---|
3479 | wrapU: 1,
|
---|
3480 | wrapV: 1
|
---|
3481 | };
|
---|
3482 | this.parseTexture( child );
|
---|
3483 | break;
|
---|
3484 |
|
---|
3485 | default:
|
---|
3486 | break;
|
---|
3487 |
|
---|
3488 | }
|
---|
3489 |
|
---|
3490 | }
|
---|
3491 |
|
---|
3492 | return this;
|
---|
3493 |
|
---|
3494 | };
|
---|
3495 |
|
---|
3496 | ColorOrTexture.prototype.parseTexture = function ( element ) {
|
---|
3497 |
|
---|
3498 | if ( ! element.childNodes ) return this;
|
---|
3499 |
|
---|
3500 | // This should be supported by Maya, 3dsMax, and MotionBuilder
|
---|
3501 |
|
---|
3502 | if ( element.childNodes[1] && element.childNodes[1].nodeName === 'extra' ) {
|
---|
3503 |
|
---|
3504 | element = element.childNodes[1];
|
---|
3505 |
|
---|
3506 | if ( element.childNodes[1] && element.childNodes[1].nodeName === 'technique' ) {
|
---|
3507 |
|
---|
3508 | element = element.childNodes[1];
|
---|
3509 |
|
---|
3510 | }
|
---|
3511 |
|
---|
3512 | }
|
---|
3513 |
|
---|
3514 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3515 |
|
---|
3516 | var child = element.childNodes[ i ];
|
---|
3517 |
|
---|
3518 | switch ( child.nodeName ) {
|
---|
3519 |
|
---|
3520 | case 'offsetU':
|
---|
3521 | case 'offsetV':
|
---|
3522 | case 'repeatU':
|
---|
3523 | case 'repeatV':
|
---|
3524 |
|
---|
3525 | this.texOpts[ child.nodeName ] = parseFloat( child.textContent );
|
---|
3526 |
|
---|
3527 | break;
|
---|
3528 |
|
---|
3529 | case 'wrapU':
|
---|
3530 | case 'wrapV':
|
---|
3531 |
|
---|
3532 | // some dae have a value of true which becomes NaN via parseInt
|
---|
3533 |
|
---|
3534 | if ( child.textContent.toUpperCase() === 'TRUE' ) {
|
---|
3535 |
|
---|
3536 | this.texOpts[ child.nodeName ] = 1;
|
---|
3537 |
|
---|
3538 | } else {
|
---|
3539 |
|
---|
3540 | this.texOpts[ child.nodeName ] = parseInt( child.textContent );
|
---|
3541 |
|
---|
3542 | }
|
---|
3543 | break;
|
---|
3544 |
|
---|
3545 | default:
|
---|
3546 |
|
---|
3547 | this.texOpts[ child.nodeName ] = child.textContent;
|
---|
3548 |
|
---|
3549 | break;
|
---|
3550 |
|
---|
3551 | }
|
---|
3552 |
|
---|
3553 | }
|
---|
3554 |
|
---|
3555 | return this;
|
---|
3556 |
|
---|
3557 | };
|
---|
3558 |
|
---|
3559 | function Shader ( type, effect ) {
|
---|
3560 |
|
---|
3561 | this.type = type;
|
---|
3562 | this.effect = effect;
|
---|
3563 | this.material = null;
|
---|
3564 |
|
---|
3565 | };
|
---|
3566 |
|
---|
3567 | Shader.prototype.parse = function ( element ) {
|
---|
3568 |
|
---|
3569 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3570 |
|
---|
3571 | var child = element.childNodes[ i ];
|
---|
3572 | if ( child.nodeType != 1 ) continue;
|
---|
3573 |
|
---|
3574 | switch ( child.nodeName ) {
|
---|
3575 |
|
---|
3576 | case 'ambient':
|
---|
3577 | case 'emission':
|
---|
3578 | case 'diffuse':
|
---|
3579 | case 'specular':
|
---|
3580 | case 'transparent':
|
---|
3581 |
|
---|
3582 | this[ child.nodeName ] = ( new ColorOrTexture() ).parse( child );
|
---|
3583 | break;
|
---|
3584 |
|
---|
3585 | case 'bump':
|
---|
3586 |
|
---|
3587 | // If 'bumptype' is 'heightfield', create a 'bump' property
|
---|
3588 | // Else if 'bumptype' is 'normalmap', create a 'normal' property
|
---|
3589 | // (Default to 'bump')
|
---|
3590 | var bumpType = child.getAttribute( 'bumptype' );
|
---|
3591 | if ( bumpType ) {
|
---|
3592 | if ( bumpType.toLowerCase() === "heightfield" ) {
|
---|
3593 | this[ 'bump' ] = ( new ColorOrTexture() ).parse( child );
|
---|
3594 | } else if ( bumpType.toLowerCase() === "normalmap" ) {
|
---|
3595 | this[ 'normal' ] = ( new ColorOrTexture() ).parse( child );
|
---|
3596 | } else {
|
---|
3597 | console.error( "Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType +
|
---|
3598 | ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'" );
|
---|
3599 | this[ 'bump' ] = ( new ColorOrTexture() ).parse( child );
|
---|
3600 | }
|
---|
3601 | } else {
|
---|
3602 | console.warn( "Shader.prototype.parse: Attribute 'bumptype' missing from bump node - defaulting to 'HEIGHTFIELD'" );
|
---|
3603 | this[ 'bump' ] = ( new ColorOrTexture() ).parse( child );
|
---|
3604 | }
|
---|
3605 |
|
---|
3606 | break;
|
---|
3607 |
|
---|
3608 | case 'shininess':
|
---|
3609 | case 'reflectivity':
|
---|
3610 | case 'index_of_refraction':
|
---|
3611 | case 'transparency':
|
---|
3612 |
|
---|
3613 | var f = child.querySelectorAll('float');
|
---|
3614 |
|
---|
3615 | if ( f.length > 0 )
|
---|
3616 | this[ child.nodeName ] = parseFloat( f[ 0 ].textContent );
|
---|
3617 |
|
---|
3618 | break;
|
---|
3619 |
|
---|
3620 | default:
|
---|
3621 | break;
|
---|
3622 |
|
---|
3623 | }
|
---|
3624 |
|
---|
3625 | }
|
---|
3626 |
|
---|
3627 | this.create();
|
---|
3628 | return this;
|
---|
3629 |
|
---|
3630 | };
|
---|
3631 |
|
---|
3632 | Shader.prototype.create = function() {
|
---|
3633 |
|
---|
3634 | var props = {};
|
---|
3635 |
|
---|
3636 | var transparent = false;
|
---|
3637 |
|
---|
3638 | if (this['transparency'] !== undefined && this['transparent'] !== undefined) {
|
---|
3639 | // convert transparent color RBG to average value
|
---|
3640 | var transparentColor = this['transparent'];
|
---|
3641 | var transparencyLevel = (this.transparent.color.r + this.transparent.color.g + this.transparent.color.b) / 3 * this.transparency;
|
---|
3642 |
|
---|
3643 | if (transparencyLevel > 0) {
|
---|
3644 | transparent = true;
|
---|
3645 | props[ 'transparent' ] = true;
|
---|
3646 | props[ 'opacity' ] = 1 - transparencyLevel;
|
---|
3647 |
|
---|
3648 | }
|
---|
3649 |
|
---|
3650 | }
|
---|
3651 |
|
---|
3652 | var keys = {
|
---|
3653 | 'diffuse':'map',
|
---|
3654 | 'ambient':'lightMap' ,
|
---|
3655 | 'specular':'specularMap',
|
---|
3656 | 'emission':'emissionMap',
|
---|
3657 | 'bump':'bumpMap',
|
---|
3658 | 'normal':'normalMap'
|
---|
3659 | };
|
---|
3660 |
|
---|
3661 | for ( var prop in this ) {
|
---|
3662 |
|
---|
3663 | switch ( prop ) {
|
---|
3664 |
|
---|
3665 | case 'ambient':
|
---|
3666 | case 'emission':
|
---|
3667 | case 'diffuse':
|
---|
3668 | case 'specular':
|
---|
3669 | case 'bump':
|
---|
3670 | case 'normal':
|
---|
3671 |
|
---|
3672 | var cot = this[ prop ];
|
---|
3673 |
|
---|
3674 | if ( cot instanceof ColorOrTexture ) {
|
---|
3675 |
|
---|
3676 | if ( cot.isTexture() ) {
|
---|
3677 |
|
---|
3678 | var samplerId = cot.texture;
|
---|
3679 | var surfaceId = this.effect.sampler[samplerId];
|
---|
3680 |
|
---|
3681 | if ( surfaceId !== undefined && surfaceId.source !== undefined ) {
|
---|
3682 |
|
---|
3683 | var surface = this.effect.surface[surfaceId.source];
|
---|
3684 |
|
---|
3685 | if ( surface !== undefined ) {
|
---|
3686 |
|
---|
3687 | var image = images[ surface.init_from ];
|
---|
3688 |
|
---|
3689 | if ( image ) {
|
---|
3690 |
|
---|
3691 | var url = baseUrl + image.init_from;
|
---|
3692 |
|
---|
3693 | var texture;
|
---|
3694 | var loader = THREE.Loader.Handlers.get( url );
|
---|
3695 |
|
---|
3696 | if ( loader !== null ) {
|
---|
3697 |
|
---|
3698 | texture = loader.load( url );
|
---|
3699 |
|
---|
3700 | } else {
|
---|
3701 |
|
---|
3702 | texture = new THREE.Texture();
|
---|
3703 |
|
---|
3704 | loadTextureImage( texture, url );
|
---|
3705 |
|
---|
3706 | }
|
---|
3707 |
|
---|
3708 | texture.wrapS = cot.texOpts.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
|
---|
3709 | texture.wrapT = cot.texOpts.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
|
---|
3710 | texture.offset.x = cot.texOpts.offsetU;
|
---|
3711 | texture.offset.y = cot.texOpts.offsetV;
|
---|
3712 | texture.repeat.x = cot.texOpts.repeatU;
|
---|
3713 | texture.repeat.y = cot.texOpts.repeatV;
|
---|
3714 | props[keys[prop]] = texture;
|
---|
3715 |
|
---|
3716 | // Texture with baked lighting?
|
---|
3717 | if (prop === 'emission') props['emissive'] = 0xffffff;
|
---|
3718 |
|
---|
3719 | }
|
---|
3720 |
|
---|
3721 | }
|
---|
3722 |
|
---|
3723 | }
|
---|
3724 |
|
---|
3725 | } else if ( prop === 'diffuse' || !transparent ) {
|
---|
3726 |
|
---|
3727 | if ( prop === 'emission' ) {
|
---|
3728 |
|
---|
3729 | props[ 'emissive' ] = cot.color.getHex();
|
---|
3730 |
|
---|
3731 | } else {
|
---|
3732 |
|
---|
3733 | props[ prop ] = cot.color.getHex();
|
---|
3734 |
|
---|
3735 | }
|
---|
3736 |
|
---|
3737 | }
|
---|
3738 |
|
---|
3739 | }
|
---|
3740 |
|
---|
3741 | break;
|
---|
3742 |
|
---|
3743 | case 'shininess':
|
---|
3744 |
|
---|
3745 | props[ prop ] = this[ prop ];
|
---|
3746 | break;
|
---|
3747 |
|
---|
3748 | case 'reflectivity':
|
---|
3749 |
|
---|
3750 | props[ prop ] = this[ prop ];
|
---|
3751 | if( props[ prop ] > 0.0 ) props['envMap'] = options.defaultEnvMap;
|
---|
3752 | props['combine'] = THREE.MixOperation; //mix regular shading with reflective component
|
---|
3753 | break;
|
---|
3754 |
|
---|
3755 | case 'index_of_refraction':
|
---|
3756 |
|
---|
3757 | props[ 'refractionRatio' ] = this[ prop ]; //TODO: "index_of_refraction" becomes "refractionRatio" in shader, but I'm not sure if the two are actually comparable
|
---|
3758 | if ( this[ prop ] !== 1.0 ) props['envMap'] = options.defaultEnvMap;
|
---|
3759 | break;
|
---|
3760 |
|
---|
3761 | case 'transparency':
|
---|
3762 | // gets figured out up top
|
---|
3763 | break;
|
---|
3764 |
|
---|
3765 | default:
|
---|
3766 | break;
|
---|
3767 |
|
---|
3768 | }
|
---|
3769 |
|
---|
3770 | }
|
---|
3771 |
|
---|
3772 | props[ 'shading' ] = preferredShading;
|
---|
3773 | props[ 'side' ] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide;
|
---|
3774 |
|
---|
3775 | switch ( this.type ) {
|
---|
3776 |
|
---|
3777 | case 'constant':
|
---|
3778 |
|
---|
3779 | if (props.emissive != undefined) props.color = props.emissive;
|
---|
3780 | this.material = new THREE.MeshBasicMaterial( props );
|
---|
3781 | break;
|
---|
3782 |
|
---|
3783 | case 'phong':
|
---|
3784 | case 'blinn':
|
---|
3785 |
|
---|
3786 | if (props.diffuse != undefined) props.color = props.diffuse;
|
---|
3787 | this.material = new THREE.MeshPhongMaterial( props );
|
---|
3788 | break;
|
---|
3789 |
|
---|
3790 | case 'lambert':
|
---|
3791 | default:
|
---|
3792 |
|
---|
3793 | if (props.diffuse != undefined) props.color = props.diffuse;
|
---|
3794 | this.material = new THREE.MeshLambertMaterial( props );
|
---|
3795 | break;
|
---|
3796 |
|
---|
3797 | }
|
---|
3798 |
|
---|
3799 | return this.material;
|
---|
3800 |
|
---|
3801 | };
|
---|
3802 |
|
---|
3803 | function Surface ( effect ) {
|
---|
3804 |
|
---|
3805 | this.effect = effect;
|
---|
3806 | this.init_from = null;
|
---|
3807 | this.format = null;
|
---|
3808 |
|
---|
3809 | };
|
---|
3810 |
|
---|
3811 | Surface.prototype.parse = function ( element ) {
|
---|
3812 |
|
---|
3813 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3814 |
|
---|
3815 | var child = element.childNodes[ i ];
|
---|
3816 | if ( child.nodeType != 1 ) continue;
|
---|
3817 |
|
---|
3818 | switch ( child.nodeName ) {
|
---|
3819 |
|
---|
3820 | case 'init_from':
|
---|
3821 |
|
---|
3822 | this.init_from = child.textContent;
|
---|
3823 | break;
|
---|
3824 |
|
---|
3825 | case 'format':
|
---|
3826 |
|
---|
3827 | this.format = child.textContent;
|
---|
3828 | break;
|
---|
3829 |
|
---|
3830 | default:
|
---|
3831 |
|
---|
3832 | console.log( "unhandled Surface prop: " + child.nodeName );
|
---|
3833 | break;
|
---|
3834 |
|
---|
3835 | }
|
---|
3836 |
|
---|
3837 | }
|
---|
3838 |
|
---|
3839 | return this;
|
---|
3840 |
|
---|
3841 | };
|
---|
3842 |
|
---|
3843 | function Sampler2D ( effect ) {
|
---|
3844 |
|
---|
3845 | this.effect = effect;
|
---|
3846 | this.source = null;
|
---|
3847 | this.wrap_s = null;
|
---|
3848 | this.wrap_t = null;
|
---|
3849 | this.minfilter = null;
|
---|
3850 | this.magfilter = null;
|
---|
3851 | this.mipfilter = null;
|
---|
3852 |
|
---|
3853 | };
|
---|
3854 |
|
---|
3855 | Sampler2D.prototype.parse = function ( element ) {
|
---|
3856 |
|
---|
3857 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3858 |
|
---|
3859 | var child = element.childNodes[ i ];
|
---|
3860 | if ( child.nodeType != 1 ) continue;
|
---|
3861 |
|
---|
3862 | switch ( child.nodeName ) {
|
---|
3863 |
|
---|
3864 | case 'source':
|
---|
3865 |
|
---|
3866 | this.source = child.textContent;
|
---|
3867 | break;
|
---|
3868 |
|
---|
3869 | case 'minfilter':
|
---|
3870 |
|
---|
3871 | this.minfilter = child.textContent;
|
---|
3872 | break;
|
---|
3873 |
|
---|
3874 | case 'magfilter':
|
---|
3875 |
|
---|
3876 | this.magfilter = child.textContent;
|
---|
3877 | break;
|
---|
3878 |
|
---|
3879 | case 'mipfilter':
|
---|
3880 |
|
---|
3881 | this.mipfilter = child.textContent;
|
---|
3882 | break;
|
---|
3883 |
|
---|
3884 | case 'wrap_s':
|
---|
3885 |
|
---|
3886 | this.wrap_s = child.textContent;
|
---|
3887 | break;
|
---|
3888 |
|
---|
3889 | case 'wrap_t':
|
---|
3890 |
|
---|
3891 | this.wrap_t = child.textContent;
|
---|
3892 | break;
|
---|
3893 |
|
---|
3894 | default:
|
---|
3895 |
|
---|
3896 | console.log( "unhandled Sampler2D prop: " + child.nodeName );
|
---|
3897 | break;
|
---|
3898 |
|
---|
3899 | }
|
---|
3900 |
|
---|
3901 | }
|
---|
3902 |
|
---|
3903 | return this;
|
---|
3904 |
|
---|
3905 | };
|
---|
3906 |
|
---|
3907 | function Effect () {
|
---|
3908 |
|
---|
3909 | this.id = "";
|
---|
3910 | this.name = "";
|
---|
3911 | this.shader = null;
|
---|
3912 | this.surface = {};
|
---|
3913 | this.sampler = {};
|
---|
3914 |
|
---|
3915 | };
|
---|
3916 |
|
---|
3917 | Effect.prototype.create = function () {
|
---|
3918 |
|
---|
3919 | if ( this.shader === null ) {
|
---|
3920 |
|
---|
3921 | return null;
|
---|
3922 |
|
---|
3923 | }
|
---|
3924 |
|
---|
3925 | };
|
---|
3926 |
|
---|
3927 | Effect.prototype.parse = function ( element ) {
|
---|
3928 |
|
---|
3929 | this.id = element.getAttribute( 'id' );
|
---|
3930 | this.name = element.getAttribute( 'name' );
|
---|
3931 |
|
---|
3932 | extractDoubleSided( this, element );
|
---|
3933 |
|
---|
3934 | this.shader = null;
|
---|
3935 |
|
---|
3936 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3937 |
|
---|
3938 | var child = element.childNodes[ i ];
|
---|
3939 | if ( child.nodeType != 1 ) continue;
|
---|
3940 |
|
---|
3941 | switch ( child.nodeName ) {
|
---|
3942 |
|
---|
3943 | case 'profile_COMMON':
|
---|
3944 |
|
---|
3945 | this.parseTechnique( this.parseProfileCOMMON( child ) );
|
---|
3946 | break;
|
---|
3947 |
|
---|
3948 | default:
|
---|
3949 | break;
|
---|
3950 |
|
---|
3951 | }
|
---|
3952 |
|
---|
3953 | }
|
---|
3954 |
|
---|
3955 | return this;
|
---|
3956 |
|
---|
3957 | };
|
---|
3958 |
|
---|
3959 | Effect.prototype.parseNewparam = function ( element ) {
|
---|
3960 |
|
---|
3961 | var sid = element.getAttribute( 'sid' );
|
---|
3962 |
|
---|
3963 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
3964 |
|
---|
3965 | var child = element.childNodes[ i ];
|
---|
3966 | if ( child.nodeType != 1 ) continue;
|
---|
3967 |
|
---|
3968 | switch ( child.nodeName ) {
|
---|
3969 |
|
---|
3970 | case 'surface':
|
---|
3971 |
|
---|
3972 | this.surface[sid] = ( new Surface( this ) ).parse( child );
|
---|
3973 | break;
|
---|
3974 |
|
---|
3975 | case 'sampler2D':
|
---|
3976 |
|
---|
3977 | this.sampler[sid] = ( new Sampler2D( this ) ).parse( child );
|
---|
3978 | break;
|
---|
3979 |
|
---|
3980 | case 'extra':
|
---|
3981 |
|
---|
3982 | break;
|
---|
3983 |
|
---|
3984 | default:
|
---|
3985 |
|
---|
3986 | console.log( child.nodeName );
|
---|
3987 | break;
|
---|
3988 |
|
---|
3989 | }
|
---|
3990 |
|
---|
3991 | }
|
---|
3992 |
|
---|
3993 | };
|
---|
3994 |
|
---|
3995 | Effect.prototype.parseProfileCOMMON = function ( element ) {
|
---|
3996 |
|
---|
3997 | var technique;
|
---|
3998 |
|
---|
3999 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4000 |
|
---|
4001 | var child = element.childNodes[ i ];
|
---|
4002 |
|
---|
4003 | if ( child.nodeType != 1 ) continue;
|
---|
4004 |
|
---|
4005 | switch ( child.nodeName ) {
|
---|
4006 |
|
---|
4007 | case 'profile_COMMON':
|
---|
4008 |
|
---|
4009 | this.parseProfileCOMMON( child );
|
---|
4010 | break;
|
---|
4011 |
|
---|
4012 | case 'technique':
|
---|
4013 |
|
---|
4014 | technique = child;
|
---|
4015 | break;
|
---|
4016 |
|
---|
4017 | case 'newparam':
|
---|
4018 |
|
---|
4019 | this.parseNewparam( child );
|
---|
4020 | break;
|
---|
4021 |
|
---|
4022 | case 'image':
|
---|
4023 |
|
---|
4024 | var _image = ( new _Image() ).parse( child );
|
---|
4025 | images[ _image.id ] = _image;
|
---|
4026 | break;
|
---|
4027 |
|
---|
4028 | case 'extra':
|
---|
4029 | break;
|
---|
4030 |
|
---|
4031 | default:
|
---|
4032 |
|
---|
4033 | console.log( child.nodeName );
|
---|
4034 | break;
|
---|
4035 |
|
---|
4036 | }
|
---|
4037 |
|
---|
4038 | }
|
---|
4039 |
|
---|
4040 | return technique;
|
---|
4041 |
|
---|
4042 | };
|
---|
4043 |
|
---|
4044 | Effect.prototype.parseTechnique= function ( element ) {
|
---|
4045 |
|
---|
4046 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4047 |
|
---|
4048 | var child = element.childNodes[i];
|
---|
4049 | if ( child.nodeType != 1 ) continue;
|
---|
4050 |
|
---|
4051 | switch ( child.nodeName ) {
|
---|
4052 |
|
---|
4053 | case 'constant':
|
---|
4054 | case 'lambert':
|
---|
4055 | case 'blinn':
|
---|
4056 | case 'phong':
|
---|
4057 |
|
---|
4058 | this.shader = ( new Shader( child.nodeName, this ) ).parse( child );
|
---|
4059 | break;
|
---|
4060 | case 'extra':
|
---|
4061 | this.parseExtra(child);
|
---|
4062 | break;
|
---|
4063 | default:
|
---|
4064 | break;
|
---|
4065 |
|
---|
4066 | }
|
---|
4067 |
|
---|
4068 | }
|
---|
4069 |
|
---|
4070 | };
|
---|
4071 |
|
---|
4072 | Effect.prototype.parseExtra = function ( element ) {
|
---|
4073 |
|
---|
4074 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4075 |
|
---|
4076 | var child = element.childNodes[i];
|
---|
4077 | if ( child.nodeType != 1 ) continue;
|
---|
4078 |
|
---|
4079 | switch ( child.nodeName ) {
|
---|
4080 |
|
---|
4081 | case 'technique':
|
---|
4082 | this.parseExtraTechnique( child );
|
---|
4083 | break;
|
---|
4084 | default:
|
---|
4085 | break;
|
---|
4086 |
|
---|
4087 | }
|
---|
4088 |
|
---|
4089 | }
|
---|
4090 |
|
---|
4091 | };
|
---|
4092 |
|
---|
4093 | Effect.prototype.parseExtraTechnique= function ( element ) {
|
---|
4094 |
|
---|
4095 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4096 |
|
---|
4097 | var child = element.childNodes[i];
|
---|
4098 | if ( child.nodeType != 1 ) continue;
|
---|
4099 |
|
---|
4100 | switch ( child.nodeName ) {
|
---|
4101 |
|
---|
4102 | case 'bump':
|
---|
4103 | this.shader.parse( element );
|
---|
4104 | break;
|
---|
4105 | default:
|
---|
4106 | break;
|
---|
4107 |
|
---|
4108 | }
|
---|
4109 |
|
---|
4110 | }
|
---|
4111 |
|
---|
4112 | };
|
---|
4113 |
|
---|
4114 | function InstanceEffect () {
|
---|
4115 |
|
---|
4116 | this.url = "";
|
---|
4117 |
|
---|
4118 | };
|
---|
4119 |
|
---|
4120 | InstanceEffect.prototype.parse = function ( element ) {
|
---|
4121 |
|
---|
4122 | this.url = element.getAttribute( 'url' ).replace( /^#/, '' );
|
---|
4123 | return this;
|
---|
4124 |
|
---|
4125 | };
|
---|
4126 |
|
---|
4127 | function Animation() {
|
---|
4128 |
|
---|
4129 | this.id = "";
|
---|
4130 | this.name = "";
|
---|
4131 | this.source = {};
|
---|
4132 | this.sampler = [];
|
---|
4133 | this.channel = [];
|
---|
4134 |
|
---|
4135 | };
|
---|
4136 |
|
---|
4137 | Animation.prototype.parse = function ( element ) {
|
---|
4138 |
|
---|
4139 | this.id = element.getAttribute( 'id' );
|
---|
4140 | this.name = element.getAttribute( 'name' );
|
---|
4141 | this.source = {};
|
---|
4142 |
|
---|
4143 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4144 |
|
---|
4145 | var child = element.childNodes[ i ];
|
---|
4146 |
|
---|
4147 | if ( child.nodeType != 1 ) continue;
|
---|
4148 |
|
---|
4149 | switch ( child.nodeName ) {
|
---|
4150 |
|
---|
4151 | case 'animation':
|
---|
4152 |
|
---|
4153 | var anim = ( new Animation() ).parse( child );
|
---|
4154 |
|
---|
4155 | for ( var src in anim.source ) {
|
---|
4156 |
|
---|
4157 | this.source[ src ] = anim.source[ src ];
|
---|
4158 |
|
---|
4159 | }
|
---|
4160 |
|
---|
4161 | for ( var j = 0; j < anim.channel.length; j ++ ) {
|
---|
4162 |
|
---|
4163 | this.channel.push( anim.channel[ j ] );
|
---|
4164 | this.sampler.push( anim.sampler[ j ] );
|
---|
4165 |
|
---|
4166 | }
|
---|
4167 |
|
---|
4168 | break;
|
---|
4169 |
|
---|
4170 | case 'source':
|
---|
4171 |
|
---|
4172 | var src = ( new Source() ).parse( child );
|
---|
4173 | this.source[ src.id ] = src;
|
---|
4174 | break;
|
---|
4175 |
|
---|
4176 | case 'sampler':
|
---|
4177 |
|
---|
4178 | this.sampler.push( ( new Sampler( this ) ).parse( child ) );
|
---|
4179 | break;
|
---|
4180 |
|
---|
4181 | case 'channel':
|
---|
4182 |
|
---|
4183 | this.channel.push( ( new Channel( this ) ).parse( child ) );
|
---|
4184 | break;
|
---|
4185 |
|
---|
4186 | default:
|
---|
4187 | break;
|
---|
4188 |
|
---|
4189 | }
|
---|
4190 |
|
---|
4191 | }
|
---|
4192 |
|
---|
4193 | return this;
|
---|
4194 |
|
---|
4195 | };
|
---|
4196 |
|
---|
4197 | function Channel( animation ) {
|
---|
4198 |
|
---|
4199 | this.animation = animation;
|
---|
4200 | this.source = "";
|
---|
4201 | this.target = "";
|
---|
4202 | this.fullSid = null;
|
---|
4203 | this.sid = null;
|
---|
4204 | this.dotSyntax = null;
|
---|
4205 | this.arrSyntax = null;
|
---|
4206 | this.arrIndices = null;
|
---|
4207 | this.member = null;
|
---|
4208 |
|
---|
4209 | };
|
---|
4210 |
|
---|
4211 | Channel.prototype.parse = function ( element ) {
|
---|
4212 |
|
---|
4213 | this.source = element.getAttribute( 'source' ).replace( /^#/, '' );
|
---|
4214 | this.target = element.getAttribute( 'target' );
|
---|
4215 |
|
---|
4216 | var parts = this.target.split( '/' );
|
---|
4217 |
|
---|
4218 | var id = parts.shift();
|
---|
4219 | var sid = parts.shift();
|
---|
4220 |
|
---|
4221 | var dotSyntax = ( sid.indexOf(".") >= 0 );
|
---|
4222 | var arrSyntax = ( sid.indexOf("(") >= 0 );
|
---|
4223 |
|
---|
4224 | if ( dotSyntax ) {
|
---|
4225 |
|
---|
4226 | parts = sid.split(".");
|
---|
4227 | this.sid = parts.shift();
|
---|
4228 | this.member = parts.shift();
|
---|
4229 |
|
---|
4230 | } else if ( arrSyntax ) {
|
---|
4231 |
|
---|
4232 | var arrIndices = sid.split("(");
|
---|
4233 | this.sid = arrIndices.shift();
|
---|
4234 |
|
---|
4235 | for (var j = 0; j < arrIndices.length; j ++ ) {
|
---|
4236 |
|
---|
4237 | arrIndices[j] = parseInt( arrIndices[j].replace(/\)/, '') );
|
---|
4238 |
|
---|
4239 | }
|
---|
4240 |
|
---|
4241 | this.arrIndices = arrIndices;
|
---|
4242 |
|
---|
4243 | } else {
|
---|
4244 |
|
---|
4245 | this.sid = sid;
|
---|
4246 |
|
---|
4247 | }
|
---|
4248 |
|
---|
4249 | this.fullSid = sid;
|
---|
4250 | this.dotSyntax = dotSyntax;
|
---|
4251 | this.arrSyntax = arrSyntax;
|
---|
4252 |
|
---|
4253 | return this;
|
---|
4254 |
|
---|
4255 | };
|
---|
4256 |
|
---|
4257 | function Sampler ( animation ) {
|
---|
4258 |
|
---|
4259 | this.id = "";
|
---|
4260 | this.animation = animation;
|
---|
4261 | this.inputs = [];
|
---|
4262 | this.input = null;
|
---|
4263 | this.output = null;
|
---|
4264 | this.strideOut = null;
|
---|
4265 | this.interpolation = null;
|
---|
4266 | this.startTime = null;
|
---|
4267 | this.endTime = null;
|
---|
4268 | this.duration = 0;
|
---|
4269 |
|
---|
4270 | };
|
---|
4271 |
|
---|
4272 | Sampler.prototype.parse = function ( element ) {
|
---|
4273 |
|
---|
4274 | this.id = element.getAttribute( 'id' );
|
---|
4275 | this.inputs = [];
|
---|
4276 |
|
---|
4277 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4278 |
|
---|
4279 | var child = element.childNodes[ i ];
|
---|
4280 | if ( child.nodeType != 1 ) continue;
|
---|
4281 |
|
---|
4282 | switch ( child.nodeName ) {
|
---|
4283 |
|
---|
4284 | case 'input':
|
---|
4285 |
|
---|
4286 | this.inputs.push( (new Input()).parse( child ) );
|
---|
4287 | break;
|
---|
4288 |
|
---|
4289 | default:
|
---|
4290 | break;
|
---|
4291 |
|
---|
4292 | }
|
---|
4293 |
|
---|
4294 | }
|
---|
4295 |
|
---|
4296 | return this;
|
---|
4297 |
|
---|
4298 | };
|
---|
4299 |
|
---|
4300 | Sampler.prototype.create = function () {
|
---|
4301 |
|
---|
4302 | for ( var i = 0; i < this.inputs.length; i ++ ) {
|
---|
4303 |
|
---|
4304 | var input = this.inputs[ i ];
|
---|
4305 | var source = this.animation.source[ input.source ];
|
---|
4306 |
|
---|
4307 | switch ( input.semantic ) {
|
---|
4308 |
|
---|
4309 | case 'INPUT':
|
---|
4310 |
|
---|
4311 | this.input = source.read();
|
---|
4312 | break;
|
---|
4313 |
|
---|
4314 | case 'OUTPUT':
|
---|
4315 |
|
---|
4316 | this.output = source.read();
|
---|
4317 | this.strideOut = source.accessor.stride;
|
---|
4318 | break;
|
---|
4319 |
|
---|
4320 | case 'INTERPOLATION':
|
---|
4321 |
|
---|
4322 | this.interpolation = source.read();
|
---|
4323 | break;
|
---|
4324 |
|
---|
4325 | case 'IN_TANGENT':
|
---|
4326 |
|
---|
4327 | break;
|
---|
4328 |
|
---|
4329 | case 'OUT_TANGENT':
|
---|
4330 |
|
---|
4331 | break;
|
---|
4332 |
|
---|
4333 | default:
|
---|
4334 |
|
---|
4335 | console.log(input.semantic);
|
---|
4336 | break;
|
---|
4337 |
|
---|
4338 | }
|
---|
4339 |
|
---|
4340 | }
|
---|
4341 |
|
---|
4342 | this.startTime = 0;
|
---|
4343 | this.endTime = 0;
|
---|
4344 | this.duration = 0;
|
---|
4345 |
|
---|
4346 | if ( this.input.length ) {
|
---|
4347 |
|
---|
4348 | this.startTime = 100000000;
|
---|
4349 | this.endTime = -100000000;
|
---|
4350 |
|
---|
4351 | for ( var i = 0; i < this.input.length; i ++ ) {
|
---|
4352 |
|
---|
4353 | this.startTime = Math.min( this.startTime, this.input[ i ] );
|
---|
4354 | this.endTime = Math.max( this.endTime, this.input[ i ] );
|
---|
4355 |
|
---|
4356 | }
|
---|
4357 |
|
---|
4358 | this.duration = this.endTime - this.startTime;
|
---|
4359 |
|
---|
4360 | }
|
---|
4361 |
|
---|
4362 | };
|
---|
4363 |
|
---|
4364 | Sampler.prototype.getData = function ( type, ndx, member ) {
|
---|
4365 |
|
---|
4366 | var data;
|
---|
4367 |
|
---|
4368 | if ( type === 'matrix' && this.strideOut === 16 ) {
|
---|
4369 |
|
---|
4370 | data = this.output[ ndx ];
|
---|
4371 |
|
---|
4372 | } else if ( this.strideOut > 1 ) {
|
---|
4373 |
|
---|
4374 | data = [];
|
---|
4375 | ndx *= this.strideOut;
|
---|
4376 |
|
---|
4377 | for ( var i = 0; i < this.strideOut; ++i ) {
|
---|
4378 |
|
---|
4379 | data[ i ] = this.output[ ndx + i ];
|
---|
4380 |
|
---|
4381 | }
|
---|
4382 |
|
---|
4383 | if ( this.strideOut === 3 ) {
|
---|
4384 |
|
---|
4385 | switch ( type ) {
|
---|
4386 |
|
---|
4387 | case 'rotate':
|
---|
4388 | case 'translate':
|
---|
4389 |
|
---|
4390 | fixCoords( data, -1 );
|
---|
4391 | break;
|
---|
4392 |
|
---|
4393 | case 'scale':
|
---|
4394 |
|
---|
4395 | fixCoords( data, 1 );
|
---|
4396 | break;
|
---|
4397 |
|
---|
4398 | }
|
---|
4399 |
|
---|
4400 | } else if ( this.strideOut === 4 && type === 'matrix' ) {
|
---|
4401 |
|
---|
4402 | fixCoords( data, -1 );
|
---|
4403 |
|
---|
4404 | }
|
---|
4405 |
|
---|
4406 | } else {
|
---|
4407 |
|
---|
4408 | data = this.output[ ndx ];
|
---|
4409 |
|
---|
4410 | if ( member && type === 'translate' ) {
|
---|
4411 | data = getConvertedTranslation( member, data );
|
---|
4412 | }
|
---|
4413 |
|
---|
4414 | }
|
---|
4415 |
|
---|
4416 | return data;
|
---|
4417 |
|
---|
4418 | };
|
---|
4419 |
|
---|
4420 | function Key ( time ) {
|
---|
4421 |
|
---|
4422 | this.targets = [];
|
---|
4423 | this.time = time;
|
---|
4424 |
|
---|
4425 | };
|
---|
4426 |
|
---|
4427 | Key.prototype.addTarget = function ( fullSid, transform, member, data ) {
|
---|
4428 |
|
---|
4429 | this.targets.push( {
|
---|
4430 | sid: fullSid,
|
---|
4431 | member: member,
|
---|
4432 | transform: transform,
|
---|
4433 | data: data
|
---|
4434 | } );
|
---|
4435 |
|
---|
4436 | };
|
---|
4437 |
|
---|
4438 | Key.prototype.apply = function ( opt_sid ) {
|
---|
4439 |
|
---|
4440 | for ( var i = 0; i < this.targets.length; ++i ) {
|
---|
4441 |
|
---|
4442 | var target = this.targets[ i ];
|
---|
4443 |
|
---|
4444 | if ( !opt_sid || target.sid === opt_sid ) {
|
---|
4445 |
|
---|
4446 | target.transform.update( target.data, target.member );
|
---|
4447 |
|
---|
4448 | }
|
---|
4449 |
|
---|
4450 | }
|
---|
4451 |
|
---|
4452 | };
|
---|
4453 |
|
---|
4454 | Key.prototype.getTarget = function ( fullSid ) {
|
---|
4455 |
|
---|
4456 | for ( var i = 0; i < this.targets.length; ++i ) {
|
---|
4457 |
|
---|
4458 | if ( this.targets[ i ].sid === fullSid ) {
|
---|
4459 |
|
---|
4460 | return this.targets[ i ];
|
---|
4461 |
|
---|
4462 | }
|
---|
4463 |
|
---|
4464 | }
|
---|
4465 |
|
---|
4466 | return null;
|
---|
4467 |
|
---|
4468 | };
|
---|
4469 |
|
---|
4470 | Key.prototype.hasTarget = function ( fullSid ) {
|
---|
4471 |
|
---|
4472 | for ( var i = 0; i < this.targets.length; ++i ) {
|
---|
4473 |
|
---|
4474 | if ( this.targets[ i ].sid === fullSid ) {
|
---|
4475 |
|
---|
4476 | return true;
|
---|
4477 |
|
---|
4478 | }
|
---|
4479 |
|
---|
4480 | }
|
---|
4481 |
|
---|
4482 | return false;
|
---|
4483 |
|
---|
4484 | };
|
---|
4485 |
|
---|
4486 | // TODO: Currently only doing linear interpolation. Should support full COLLADA spec.
|
---|
4487 | Key.prototype.interpolate = function ( nextKey, time ) {
|
---|
4488 |
|
---|
4489 | for ( var i = 0, l = this.targets.length; i < l; i ++ ) {
|
---|
4490 |
|
---|
4491 | var target = this.targets[ i ],
|
---|
4492 | nextTarget = nextKey.getTarget( target.sid ),
|
---|
4493 | data;
|
---|
4494 |
|
---|
4495 | if ( target.transform.type !== 'matrix' && nextTarget ) {
|
---|
4496 |
|
---|
4497 | var scale = ( time - this.time ) / ( nextKey.time - this.time ),
|
---|
4498 | nextData = nextTarget.data,
|
---|
4499 | prevData = target.data;
|
---|
4500 |
|
---|
4501 | if ( scale < 0 ) scale = 0;
|
---|
4502 | if ( scale > 1 ) scale = 1;
|
---|
4503 |
|
---|
4504 | if ( prevData.length ) {
|
---|
4505 |
|
---|
4506 | data = [];
|
---|
4507 |
|
---|
4508 | for ( var j = 0; j < prevData.length; ++j ) {
|
---|
4509 |
|
---|
4510 | data[ j ] = prevData[ j ] + ( nextData[ j ] - prevData[ j ] ) * scale;
|
---|
4511 |
|
---|
4512 | }
|
---|
4513 |
|
---|
4514 | } else {
|
---|
4515 |
|
---|
4516 | data = prevData + ( nextData - prevData ) * scale;
|
---|
4517 |
|
---|
4518 | }
|
---|
4519 |
|
---|
4520 | } else {
|
---|
4521 |
|
---|
4522 | data = target.data;
|
---|
4523 |
|
---|
4524 | }
|
---|
4525 |
|
---|
4526 | target.transform.update( data, target.member );
|
---|
4527 |
|
---|
4528 | }
|
---|
4529 |
|
---|
4530 | };
|
---|
4531 |
|
---|
4532 | // Camera
|
---|
4533 | function Camera() {
|
---|
4534 |
|
---|
4535 | this.id = "";
|
---|
4536 | this.name = "";
|
---|
4537 | this.technique = "";
|
---|
4538 |
|
---|
4539 | };
|
---|
4540 |
|
---|
4541 | Camera.prototype.parse = function ( element ) {
|
---|
4542 |
|
---|
4543 | this.id = element.getAttribute( 'id' );
|
---|
4544 | this.name = element.getAttribute( 'name' );
|
---|
4545 |
|
---|
4546 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4547 |
|
---|
4548 | var child = element.childNodes[ i ];
|
---|
4549 | if ( child.nodeType != 1 ) continue;
|
---|
4550 |
|
---|
4551 | switch ( child.nodeName ) {
|
---|
4552 |
|
---|
4553 | case 'optics':
|
---|
4554 |
|
---|
4555 | this.parseOptics( child );
|
---|
4556 | break;
|
---|
4557 |
|
---|
4558 | default:
|
---|
4559 | break;
|
---|
4560 |
|
---|
4561 | }
|
---|
4562 |
|
---|
4563 | }
|
---|
4564 |
|
---|
4565 | return this;
|
---|
4566 |
|
---|
4567 | };
|
---|
4568 |
|
---|
4569 | Camera.prototype.parseOptics = function ( element ) {
|
---|
4570 |
|
---|
4571 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4572 |
|
---|
4573 | if ( element.childNodes[ i ].nodeName === 'technique_common' ) {
|
---|
4574 |
|
---|
4575 | var technique = element.childNodes[ i ];
|
---|
4576 |
|
---|
4577 | for ( var j = 0; j < technique.childNodes.length; j ++ ) {
|
---|
4578 |
|
---|
4579 | this.technique = technique.childNodes[ j ].nodeName;
|
---|
4580 |
|
---|
4581 | if ( this.technique === 'perspective' ) {
|
---|
4582 |
|
---|
4583 | var perspective = technique.childNodes[ j ];
|
---|
4584 |
|
---|
4585 | for ( var k = 0; k < perspective.childNodes.length; k ++ ) {
|
---|
4586 |
|
---|
4587 | var param = perspective.childNodes[ k ];
|
---|
4588 |
|
---|
4589 | switch ( param.nodeName ) {
|
---|
4590 |
|
---|
4591 | case 'yfov':
|
---|
4592 | this.yfov = param.textContent;
|
---|
4593 | break;
|
---|
4594 | case 'xfov':
|
---|
4595 | this.xfov = param.textContent;
|
---|
4596 | break;
|
---|
4597 | case 'znear':
|
---|
4598 | this.znear = param.textContent;
|
---|
4599 | break;
|
---|
4600 | case 'zfar':
|
---|
4601 | this.zfar = param.textContent;
|
---|
4602 | break;
|
---|
4603 | case 'aspect_ratio':
|
---|
4604 | this.aspect_ratio = param.textContent;
|
---|
4605 | break;
|
---|
4606 |
|
---|
4607 | }
|
---|
4608 |
|
---|
4609 | }
|
---|
4610 |
|
---|
4611 | } else if ( this.technique === 'orthographic' ) {
|
---|
4612 |
|
---|
4613 | var orthographic = technique.childNodes[ j ];
|
---|
4614 |
|
---|
4615 | for ( var k = 0; k < orthographic.childNodes.length; k ++ ) {
|
---|
4616 |
|
---|
4617 | var param = orthographic.childNodes[ k ];
|
---|
4618 |
|
---|
4619 | switch ( param.nodeName ) {
|
---|
4620 |
|
---|
4621 | case 'xmag':
|
---|
4622 | this.xmag = param.textContent;
|
---|
4623 | break;
|
---|
4624 | case 'ymag':
|
---|
4625 | this.ymag = param.textContent;
|
---|
4626 | break;
|
---|
4627 | case 'znear':
|
---|
4628 | this.znear = param.textContent;
|
---|
4629 | break;
|
---|
4630 | case 'zfar':
|
---|
4631 | this.zfar = param.textContent;
|
---|
4632 | break;
|
---|
4633 | case 'aspect_ratio':
|
---|
4634 | this.aspect_ratio = param.textContent;
|
---|
4635 | break;
|
---|
4636 |
|
---|
4637 | }
|
---|
4638 |
|
---|
4639 | }
|
---|
4640 |
|
---|
4641 | }
|
---|
4642 |
|
---|
4643 | }
|
---|
4644 |
|
---|
4645 | }
|
---|
4646 |
|
---|
4647 | }
|
---|
4648 |
|
---|
4649 | return this;
|
---|
4650 |
|
---|
4651 | };
|
---|
4652 |
|
---|
4653 | function InstanceCamera() {
|
---|
4654 |
|
---|
4655 | this.url = "";
|
---|
4656 |
|
---|
4657 | };
|
---|
4658 |
|
---|
4659 | InstanceCamera.prototype.parse = function ( element ) {
|
---|
4660 |
|
---|
4661 | this.url = element.getAttribute('url').replace(/^#/, '');
|
---|
4662 |
|
---|
4663 | return this;
|
---|
4664 |
|
---|
4665 | };
|
---|
4666 |
|
---|
4667 | // Light
|
---|
4668 |
|
---|
4669 | function Light() {
|
---|
4670 |
|
---|
4671 | this.id = "";
|
---|
4672 | this.name = "";
|
---|
4673 | this.technique = "";
|
---|
4674 |
|
---|
4675 | };
|
---|
4676 |
|
---|
4677 | Light.prototype.parse = function ( element ) {
|
---|
4678 |
|
---|
4679 | this.id = element.getAttribute( 'id' );
|
---|
4680 | this.name = element.getAttribute( 'name' );
|
---|
4681 |
|
---|
4682 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4683 |
|
---|
4684 | var child = element.childNodes[ i ];
|
---|
4685 | if ( child.nodeType != 1 ) continue;
|
---|
4686 |
|
---|
4687 | switch ( child.nodeName ) {
|
---|
4688 |
|
---|
4689 | case 'technique_common':
|
---|
4690 |
|
---|
4691 | this.parseCommon( child );
|
---|
4692 | break;
|
---|
4693 |
|
---|
4694 | case 'technique':
|
---|
4695 |
|
---|
4696 | this.parseTechnique( child );
|
---|
4697 | break;
|
---|
4698 |
|
---|
4699 | default:
|
---|
4700 | break;
|
---|
4701 |
|
---|
4702 | }
|
---|
4703 |
|
---|
4704 | }
|
---|
4705 |
|
---|
4706 | return this;
|
---|
4707 |
|
---|
4708 | };
|
---|
4709 |
|
---|
4710 | Light.prototype.parseCommon = function ( element ) {
|
---|
4711 |
|
---|
4712 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4713 |
|
---|
4714 | switch ( element.childNodes[ i ].nodeName ) {
|
---|
4715 |
|
---|
4716 | case 'directional':
|
---|
4717 | case 'point':
|
---|
4718 | case 'spot':
|
---|
4719 | case 'ambient':
|
---|
4720 |
|
---|
4721 | this.technique = element.childNodes[ i ].nodeName;
|
---|
4722 |
|
---|
4723 | var light = element.childNodes[ i ];
|
---|
4724 |
|
---|
4725 | for ( var j = 0; j < light.childNodes.length; j ++ ) {
|
---|
4726 |
|
---|
4727 | var child = light.childNodes[j];
|
---|
4728 |
|
---|
4729 | switch ( child.nodeName ) {
|
---|
4730 |
|
---|
4731 | case 'color':
|
---|
4732 |
|
---|
4733 | var rgba = _floats( child.textContent );
|
---|
4734 | this.color = new THREE.Color(0);
|
---|
4735 | this.color.setRGB( rgba[0], rgba[1], rgba[2] );
|
---|
4736 | this.color.a = rgba[3];
|
---|
4737 | break;
|
---|
4738 |
|
---|
4739 | case 'falloff_angle':
|
---|
4740 |
|
---|
4741 | this.falloff_angle = parseFloat( child.textContent );
|
---|
4742 | break;
|
---|
4743 |
|
---|
4744 | case 'quadratic_attenuation':
|
---|
4745 | var f = parseFloat( child.textContent );
|
---|
4746 | this.distance = f ? Math.sqrt( 1/f ) : 0;
|
---|
4747 | }
|
---|
4748 |
|
---|
4749 | }
|
---|
4750 |
|
---|
4751 | }
|
---|
4752 |
|
---|
4753 | }
|
---|
4754 |
|
---|
4755 | return this;
|
---|
4756 |
|
---|
4757 | };
|
---|
4758 |
|
---|
4759 | Light.prototype.parseTechnique = function ( element ) {
|
---|
4760 |
|
---|
4761 | this.profile = element.getAttribute( 'profile' );
|
---|
4762 |
|
---|
4763 | for ( var i = 0; i < element.childNodes.length; i ++ ) {
|
---|
4764 |
|
---|
4765 | var child = element.childNodes[ i ];
|
---|
4766 |
|
---|
4767 | switch ( child.nodeName ) {
|
---|
4768 |
|
---|
4769 | case 'intensity':
|
---|
4770 |
|
---|
4771 | this.intensity = parseFloat(child.textContent);
|
---|
4772 | break;
|
---|
4773 |
|
---|
4774 | }
|
---|
4775 |
|
---|
4776 | }
|
---|
4777 |
|
---|
4778 | return this;
|
---|
4779 |
|
---|
4780 | };
|
---|
4781 |
|
---|
4782 | function InstanceLight() {
|
---|
4783 |
|
---|
4784 | this.url = "";
|
---|
4785 |
|
---|
4786 | };
|
---|
4787 |
|
---|
4788 | InstanceLight.prototype.parse = function ( element ) {
|
---|
4789 |
|
---|
4790 | this.url = element.getAttribute('url').replace(/^#/, '');
|
---|
4791 |
|
---|
4792 | return this;
|
---|
4793 |
|
---|
4794 | };
|
---|
4795 |
|
---|
4796 | function KinematicsModel( ) {
|
---|
4797 |
|
---|
4798 | this.id = '';
|
---|
4799 | this.name = '';
|
---|
4800 | this.joints = [];
|
---|
4801 | this.links = [];
|
---|
4802 |
|
---|
4803 | }
|
---|
4804 |
|
---|
4805 | KinematicsModel.prototype.parse = function( element ) {
|
---|
4806 |
|
---|
4807 | this.id = element.getAttribute('id');
|
---|
4808 | this.name = element.getAttribute('name');
|
---|
4809 | this.joints = [];
|
---|
4810 | this.links = [];
|
---|
4811 |
|
---|
4812 | for (var i = 0; i < element.childNodes.length; i++ ) {
|
---|
4813 |
|
---|
4814 | var child = element.childNodes[ i ];
|
---|
4815 | if ( child.nodeType != 1 ) continue;
|
---|
4816 |
|
---|
4817 | switch ( child.nodeName ) {
|
---|
4818 |
|
---|
4819 | case 'technique_common':
|
---|
4820 |
|
---|
4821 | this.parseCommon(child);
|
---|
4822 | break;
|
---|
4823 |
|
---|
4824 | default:
|
---|
4825 | break;
|
---|
4826 |
|
---|
4827 | }
|
---|
4828 |
|
---|
4829 | }
|
---|
4830 |
|
---|
4831 | return this;
|
---|
4832 |
|
---|
4833 | };
|
---|
4834 |
|
---|
4835 | KinematicsModel.prototype.parseCommon = function( element ) {
|
---|
4836 |
|
---|
4837 | for (var i = 0; i < element.childNodes.length; i++ ) {
|
---|
4838 |
|
---|
4839 | var child = element.childNodes[ i ];
|
---|
4840 | if ( child.nodeType != 1 ) continue;
|
---|
4841 |
|
---|
4842 | switch ( element.childNodes[ i ].nodeName ) {
|
---|
4843 |
|
---|
4844 | case 'joint':
|
---|
4845 | this.joints.push( (new Joint()).parse(child) );
|
---|
4846 | break;
|
---|
4847 |
|
---|
4848 | case 'link':
|
---|
4849 | this.links.push( (new Link()).parse(child) );
|
---|
4850 | break;
|
---|
4851 |
|
---|
4852 | default:
|
---|
4853 | break;
|
---|
4854 |
|
---|
4855 | }
|
---|
4856 |
|
---|
4857 | }
|
---|
4858 |
|
---|
4859 | return this;
|
---|
4860 |
|
---|
4861 | };
|
---|
4862 |
|
---|
4863 | function Joint( ) {
|
---|
4864 |
|
---|
4865 | this.sid = '';
|
---|
4866 | this.name = '';
|
---|
4867 | this.axis = new THREE.Vector3();
|
---|
4868 | this.limits = {
|
---|
4869 | min: 0,
|
---|
4870 | max: 0
|
---|
4871 | };
|
---|
4872 | this.type = '';
|
---|
4873 | this.static = false;
|
---|
4874 | this.zeroPosition = 0.0;
|
---|
4875 | this.middlePosition = 0.0;
|
---|
4876 |
|
---|
4877 | }
|
---|
4878 |
|
---|
4879 | Joint.prototype.parse = function( element ) {
|
---|
4880 |
|
---|
4881 | this.sid = element.getAttribute('sid');
|
---|
4882 | this.name = element.getAttribute('name');
|
---|
4883 | this.axis = new THREE.Vector3();
|
---|
4884 | this.limits = {
|
---|
4885 | min: 0,
|
---|
4886 | max: 0
|
---|
4887 | };
|
---|
4888 | this.type = '';
|
---|
4889 | this.static = false;
|
---|
4890 | this.zeroPosition = 0.0;
|
---|
4891 | this.middlePosition = 0.0;
|
---|
4892 |
|
---|
4893 | var axisElement = element.querySelector('axis');
|
---|
4894 | var _axis = _floats(axisElement.textContent);
|
---|
4895 | this.axis = getConvertedVec3(_axis, 0);
|
---|
4896 |
|
---|
4897 | var min = element.querySelector('limits min') ? parseFloat(element.querySelector('limits min').textContent) : -360;
|
---|
4898 | var max = element.querySelector('limits max') ? parseFloat(element.querySelector('limits max').textContent) : 360;
|
---|
4899 |
|
---|
4900 | this.limits = {
|
---|
4901 | min: min,
|
---|
4902 | max: max
|
---|
4903 | };
|
---|
4904 |
|
---|
4905 | var jointTypes = ['prismatic', 'revolute'];
|
---|
4906 | for (var i = 0; i < jointTypes.length; i++ ) {
|
---|
4907 |
|
---|
4908 | var type = jointTypes[ i ];
|
---|
4909 |
|
---|
4910 | var jointElement = element.querySelector(type);
|
---|
4911 |
|
---|
4912 | if ( jointElement ) {
|
---|
4913 |
|
---|
4914 | this.type = type;
|
---|
4915 |
|
---|
4916 | }
|
---|
4917 |
|
---|
4918 | }
|
---|
4919 |
|
---|
4920 | // if the min is equal to or somehow greater than the max, consider the joint static
|
---|
4921 | if ( this.limits.min >= this.limits.max ) {
|
---|
4922 |
|
---|
4923 | this.static = true;
|
---|
4924 |
|
---|
4925 | }
|
---|
4926 |
|
---|
4927 | this.middlePosition = (this.limits.min + this.limits.max) / 2.0;
|
---|
4928 | return this;
|
---|
4929 |
|
---|
4930 | };
|
---|
4931 |
|
---|
4932 | function Link( ) {
|
---|
4933 |
|
---|
4934 | this.sid = '';
|
---|
4935 | this.name = '';
|
---|
4936 | this.transforms = [];
|
---|
4937 | this.attachments = [];
|
---|
4938 |
|
---|
4939 | }
|
---|
4940 |
|
---|
4941 | Link.prototype.parse = function( element ) {
|
---|
4942 |
|
---|
4943 | this.sid = element.getAttribute('sid');
|
---|
4944 | this.name = element.getAttribute('name');
|
---|
4945 | this.transforms = [];
|
---|
4946 | this.attachments = [];
|
---|
4947 |
|
---|
4948 | for (var i = 0; i < element.childNodes.length; i++ ) {
|
---|
4949 |
|
---|
4950 | var child = element.childNodes[ i ];
|
---|
4951 | if ( child.nodeType != 1 ) continue;
|
---|
4952 |
|
---|
4953 | switch ( child.nodeName ) {
|
---|
4954 |
|
---|
4955 | case 'attachment_full':
|
---|
4956 | this.attachments.push( (new Attachment()).parse(child) );
|
---|
4957 | break;
|
---|
4958 |
|
---|
4959 | case 'rotate':
|
---|
4960 | case 'translate':
|
---|
4961 | case 'matrix':
|
---|
4962 |
|
---|
4963 | this.transforms.push( (new Transform()).parse(child) );
|
---|
4964 | break;
|
---|
4965 |
|
---|
4966 | default:
|
---|
4967 |
|
---|
4968 | break;
|
---|
4969 |
|
---|
4970 | }
|
---|
4971 |
|
---|
4972 | }
|
---|
4973 |
|
---|
4974 | return this;
|
---|
4975 |
|
---|
4976 | };
|
---|
4977 |
|
---|
4978 | function Attachment( ) {
|
---|
4979 |
|
---|
4980 | this.joint = '';
|
---|
4981 | this.transforms = [];
|
---|
4982 | this.links = [];
|
---|
4983 |
|
---|
4984 | }
|
---|
4985 |
|
---|
4986 | Attachment.prototype.parse = function( element ) {
|
---|
4987 |
|
---|
4988 | this.joint = element.getAttribute('joint').split('/').pop();
|
---|
4989 | this.links = [];
|
---|
4990 |
|
---|
4991 | for (var i = 0; i < element.childNodes.length; i++ ) {
|
---|
4992 |
|
---|
4993 | var child = element.childNodes[ i ];
|
---|
4994 | if ( child.nodeType != 1 ) continue;
|
---|
4995 |
|
---|
4996 | switch ( child.nodeName ) {
|
---|
4997 |
|
---|
4998 | case 'link':
|
---|
4999 | this.links.push( (new Link()).parse(child) );
|
---|
5000 | break;
|
---|
5001 |
|
---|
5002 | case 'rotate':
|
---|
5003 | case 'translate':
|
---|
5004 | case 'matrix':
|
---|
5005 |
|
---|
5006 | this.transforms.push( (new Transform()).parse(child) );
|
---|
5007 | break;
|
---|
5008 |
|
---|
5009 | default:
|
---|
5010 |
|
---|
5011 | break;
|
---|
5012 |
|
---|
5013 | }
|
---|
5014 |
|
---|
5015 | }
|
---|
5016 |
|
---|
5017 | return this;
|
---|
5018 |
|
---|
5019 | };
|
---|
5020 |
|
---|
5021 | function _source( element ) {
|
---|
5022 |
|
---|
5023 | var id = element.getAttribute( 'id' );
|
---|
5024 |
|
---|
5025 | if ( sources[ id ] != undefined ) {
|
---|
5026 |
|
---|
5027 | return sources[ id ];
|
---|
5028 |
|
---|
5029 | }
|
---|
5030 |
|
---|
5031 | sources[ id ] = ( new Source(id )).parse( element );
|
---|
5032 | return sources[ id ];
|
---|
5033 |
|
---|
5034 | };
|
---|
5035 |
|
---|
5036 | function _nsResolver( nsPrefix ) {
|
---|
5037 |
|
---|
5038 | if ( nsPrefix === "dae" ) {
|
---|
5039 |
|
---|
5040 | return "http://www.collada.org/2005/11/COLLADASchema";
|
---|
5041 |
|
---|
5042 | }
|
---|
5043 |
|
---|
5044 | return null;
|
---|
5045 |
|
---|
5046 | };
|
---|
5047 |
|
---|
5048 | function _bools( str ) {
|
---|
5049 |
|
---|
5050 | var raw = _strings( str );
|
---|
5051 | var data = [];
|
---|
5052 |
|
---|
5053 | for ( var i = 0, l = raw.length; i < l; i ++ ) {
|
---|
5054 |
|
---|
5055 | data.push( (raw[i] === 'true' || raw[i] === '1') ? true : false );
|
---|
5056 |
|
---|
5057 | }
|
---|
5058 |
|
---|
5059 | return data;
|
---|
5060 |
|
---|
5061 | };
|
---|
5062 |
|
---|
5063 | function _floats( str ) {
|
---|
5064 |
|
---|
5065 | var raw = _strings(str);
|
---|
5066 | var data = [];
|
---|
5067 |
|
---|
5068 | for ( var i = 0, l = raw.length; i < l; i ++ ) {
|
---|
5069 |
|
---|
5070 | data.push( parseFloat( raw[ i ] ) );
|
---|
5071 |
|
---|
5072 | }
|
---|
5073 |
|
---|
5074 | return data;
|
---|
5075 |
|
---|
5076 | };
|
---|
5077 |
|
---|
5078 | function _ints( str ) {
|
---|
5079 |
|
---|
5080 | var raw = _strings( str );
|
---|
5081 | var data = [];
|
---|
5082 |
|
---|
5083 | for ( var i = 0, l = raw.length; i < l; i ++ ) {
|
---|
5084 |
|
---|
5085 | data.push( parseInt( raw[ i ], 10 ) );
|
---|
5086 |
|
---|
5087 | }
|
---|
5088 |
|
---|
5089 | return data;
|
---|
5090 |
|
---|
5091 | };
|
---|
5092 |
|
---|
5093 | function _strings( str ) {
|
---|
5094 |
|
---|
5095 | return ( str.length > 0 ) ? _trimString( str ).split( /\s+/ ) : [];
|
---|
5096 |
|
---|
5097 | };
|
---|
5098 |
|
---|
5099 | function _trimString( str ) {
|
---|
5100 |
|
---|
5101 | return str.replace( /^\s+/, "" ).replace( /\s+$/, "" );
|
---|
5102 |
|
---|
5103 | };
|
---|
5104 |
|
---|
5105 | function _attr_as_float( element, name, defaultValue ) {
|
---|
5106 |
|
---|
5107 | if ( element.hasAttribute( name ) ) {
|
---|
5108 |
|
---|
5109 | return parseFloat( element.getAttribute( name ) );
|
---|
5110 |
|
---|
5111 | } else {
|
---|
5112 |
|
---|
5113 | return defaultValue;
|
---|
5114 |
|
---|
5115 | }
|
---|
5116 |
|
---|
5117 | };
|
---|
5118 |
|
---|
5119 | function _attr_as_int( element, name, defaultValue ) {
|
---|
5120 |
|
---|
5121 | if ( element.hasAttribute( name ) ) {
|
---|
5122 |
|
---|
5123 | return parseInt( element.getAttribute( name ), 10) ;
|
---|
5124 |
|
---|
5125 | } else {
|
---|
5126 |
|
---|
5127 | return defaultValue;
|
---|
5128 |
|
---|
5129 | }
|
---|
5130 |
|
---|
5131 | };
|
---|
5132 |
|
---|
5133 | function _attr_as_string( element, name, defaultValue ) {
|
---|
5134 |
|
---|
5135 | if ( element.hasAttribute( name ) ) {
|
---|
5136 |
|
---|
5137 | return element.getAttribute( name );
|
---|
5138 |
|
---|
5139 | } else {
|
---|
5140 |
|
---|
5141 | return defaultValue;
|
---|
5142 |
|
---|
5143 | }
|
---|
5144 |
|
---|
5145 | };
|
---|
5146 |
|
---|
5147 | function _format_float( f, num ) {
|
---|
5148 |
|
---|
5149 | if ( f === undefined ) {
|
---|
5150 |
|
---|
5151 | var s = '0.';
|
---|
5152 |
|
---|
5153 | while ( s.length < num + 2 ) {
|
---|
5154 |
|
---|
5155 | s += '0';
|
---|
5156 |
|
---|
5157 | }
|
---|
5158 |
|
---|
5159 | return s;
|
---|
5160 |
|
---|
5161 | }
|
---|
5162 |
|
---|
5163 | num = num || 2;
|
---|
5164 |
|
---|
5165 | var parts = f.toString().split( '.' );
|
---|
5166 | parts[ 1 ] = parts.length > 1 ? parts[ 1 ].substr( 0, num ) : "0";
|
---|
5167 |
|
---|
5168 | while( parts[ 1 ].length < num ) {
|
---|
5169 |
|
---|
5170 | parts[ 1 ] += '0';
|
---|
5171 |
|
---|
5172 | }
|
---|
5173 |
|
---|
5174 | return parts.join( '.' );
|
---|
5175 |
|
---|
5176 | };
|
---|
5177 |
|
---|
5178 | function loadTextureImage ( texture, url ) {
|
---|
5179 |
|
---|
5180 | loader = new THREE.ImageLoader();
|
---|
5181 |
|
---|
5182 | loader.load( url, function ( image ) {
|
---|
5183 |
|
---|
5184 | texture.image = image;
|
---|
5185 | texture.needsUpdate = true;
|
---|
5186 |
|
---|
5187 | } );
|
---|
5188 |
|
---|
5189 | };
|
---|
5190 |
|
---|
5191 | function extractDoubleSided( obj, element ) {
|
---|
5192 |
|
---|
5193 | obj.doubleSided = false;
|
---|
5194 |
|
---|
5195 | var node = element.querySelectorAll('extra double_sided')[0];
|
---|
5196 |
|
---|
5197 | if ( node ) {
|
---|
5198 |
|
---|
5199 | if ( node && parseInt( node.textContent, 10 ) === 1 ) {
|
---|
5200 |
|
---|
5201 | obj.doubleSided = true;
|
---|
5202 |
|
---|
5203 | }
|
---|
5204 |
|
---|
5205 | }
|
---|
5206 |
|
---|
5207 | };
|
---|
5208 |
|
---|
5209 | // Up axis conversion
|
---|
5210 |
|
---|
5211 | function setUpConversion() {
|
---|
5212 |
|
---|
5213 | if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) {
|
---|
5214 |
|
---|
5215 | upConversion = null;
|
---|
5216 |
|
---|
5217 | } else {
|
---|
5218 |
|
---|
5219 | switch ( colladaUp ) {
|
---|
5220 |
|
---|
5221 | case 'X':
|
---|
5222 |
|
---|
5223 | upConversion = options.upAxis === 'Y' ? 'XtoY' : 'XtoZ';
|
---|
5224 | break;
|
---|
5225 |
|
---|
5226 | case 'Y':
|
---|
5227 |
|
---|
5228 | upConversion = options.upAxis === 'X' ? 'YtoX' : 'YtoZ';
|
---|
5229 | break;
|
---|
5230 |
|
---|
5231 | case 'Z':
|
---|
5232 |
|
---|
5233 | upConversion = options.upAxis === 'X' ? 'ZtoX' : 'ZtoY';
|
---|
5234 | break;
|
---|
5235 |
|
---|
5236 | }
|
---|
5237 |
|
---|
5238 | }
|
---|
5239 |
|
---|
5240 | };
|
---|
5241 |
|
---|
5242 | function fixCoords( data, sign ) {
|
---|
5243 |
|
---|
5244 | if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) {
|
---|
5245 |
|
---|
5246 | return;
|
---|
5247 |
|
---|
5248 | }
|
---|
5249 |
|
---|
5250 | switch ( upConversion ) {
|
---|
5251 |
|
---|
5252 | case 'XtoY':
|
---|
5253 |
|
---|
5254 | var tmp = data[ 0 ];
|
---|
5255 | data[ 0 ] = sign * data[ 1 ];
|
---|
5256 | data[ 1 ] = tmp;
|
---|
5257 | break;
|
---|
5258 |
|
---|
5259 | case 'XtoZ':
|
---|
5260 |
|
---|
5261 | var tmp = data[ 2 ];
|
---|
5262 | data[ 2 ] = data[ 1 ];
|
---|
5263 | data[ 1 ] = data[ 0 ];
|
---|
5264 | data[ 0 ] = tmp;
|
---|
5265 | break;
|
---|
5266 |
|
---|
5267 | case 'YtoX':
|
---|
5268 |
|
---|
5269 | var tmp = data[ 0 ];
|
---|
5270 | data[ 0 ] = data[ 1 ];
|
---|
5271 | data[ 1 ] = sign * tmp;
|
---|
5272 | break;
|
---|
5273 |
|
---|
5274 | case 'YtoZ':
|
---|
5275 |
|
---|
5276 | var tmp = data[ 1 ];
|
---|
5277 | data[ 1 ] = sign * data[ 2 ];
|
---|
5278 | data[ 2 ] = tmp;
|
---|
5279 | break;
|
---|
5280 |
|
---|
5281 | case 'ZtoX':
|
---|
5282 |
|
---|
5283 | var tmp = data[ 0 ];
|
---|
5284 | data[ 0 ] = data[ 1 ];
|
---|
5285 | data[ 1 ] = data[ 2 ];
|
---|
5286 | data[ 2 ] = tmp;
|
---|
5287 | break;
|
---|
5288 |
|
---|
5289 | case 'ZtoY':
|
---|
5290 |
|
---|
5291 | var tmp = data[ 1 ];
|
---|
5292 | data[ 1 ] = data[ 2 ];
|
---|
5293 | data[ 2 ] = sign * tmp;
|
---|
5294 | break;
|
---|
5295 |
|
---|
5296 | }
|
---|
5297 |
|
---|
5298 | };
|
---|
5299 |
|
---|
5300 | function getConvertedTranslation( axis, data ) {
|
---|
5301 |
|
---|
5302 | if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) {
|
---|
5303 |
|
---|
5304 | return data;
|
---|
5305 |
|
---|
5306 | }
|
---|
5307 |
|
---|
5308 | switch ( axis ) {
|
---|
5309 | case 'X':
|
---|
5310 | data = upConversion === 'XtoY' ? data * -1 : data;
|
---|
5311 | break;
|
---|
5312 | case 'Y':
|
---|
5313 | data = upConversion === 'YtoZ' || upConversion === 'YtoX' ? data * -1 : data;
|
---|
5314 | break;
|
---|
5315 | case 'Z':
|
---|
5316 | data = upConversion === 'ZtoY' ? data * -1 : data ;
|
---|
5317 | break;
|
---|
5318 | default:
|
---|
5319 | break;
|
---|
5320 | }
|
---|
5321 |
|
---|
5322 | return data;
|
---|
5323 | };
|
---|
5324 |
|
---|
5325 | function getConvertedVec3( data, offset ) {
|
---|
5326 |
|
---|
5327 | var arr = [ data[ offset ], data[ offset + 1 ], data[ offset + 2 ] ];
|
---|
5328 | fixCoords( arr, -1 );
|
---|
5329 | return new THREE.Vector3( arr[ 0 ], arr[ 1 ], arr[ 2 ] );
|
---|
5330 |
|
---|
5331 | };
|
---|
5332 |
|
---|
5333 | function getConvertedMat4( data ) {
|
---|
5334 |
|
---|
5335 | if ( options.convertUpAxis ) {
|
---|
5336 |
|
---|
5337 | // First fix rotation and scale
|
---|
5338 |
|
---|
5339 | // Columns first
|
---|
5340 | var arr = [ data[ 0 ], data[ 4 ], data[ 8 ] ];
|
---|
5341 | fixCoords( arr, -1 );
|
---|
5342 | data[ 0 ] = arr[ 0 ];
|
---|
5343 | data[ 4 ] = arr[ 1 ];
|
---|
5344 | data[ 8 ] = arr[ 2 ];
|
---|
5345 | arr = [ data[ 1 ], data[ 5 ], data[ 9 ] ];
|
---|
5346 | fixCoords( arr, -1 );
|
---|
5347 | data[ 1 ] = arr[ 0 ];
|
---|
5348 | data[ 5 ] = arr[ 1 ];
|
---|
5349 | data[ 9 ] = arr[ 2 ];
|
---|
5350 | arr = [ data[ 2 ], data[ 6 ], data[ 10 ] ];
|
---|
5351 | fixCoords( arr, -1 );
|
---|
5352 | data[ 2 ] = arr[ 0 ];
|
---|
5353 | data[ 6 ] = arr[ 1 ];
|
---|
5354 | data[ 10 ] = arr[ 2 ];
|
---|
5355 | // Rows second
|
---|
5356 | arr = [ data[ 0 ], data[ 1 ], data[ 2 ] ];
|
---|
5357 | fixCoords( arr, -1 );
|
---|
5358 | data[ 0 ] = arr[ 0 ];
|
---|
5359 | data[ 1 ] = arr[ 1 ];
|
---|
5360 | data[ 2 ] = arr[ 2 ];
|
---|
5361 | arr = [ data[ 4 ], data[ 5 ], data[ 6 ] ];
|
---|
5362 | fixCoords( arr, -1 );
|
---|
5363 | data[ 4 ] = arr[ 0 ];
|
---|
5364 | data[ 5 ] = arr[ 1 ];
|
---|
5365 | data[ 6 ] = arr[ 2 ];
|
---|
5366 | arr = [ data[ 8 ], data[ 9 ], data[ 10 ] ];
|
---|
5367 | fixCoords( arr, -1 );
|
---|
5368 | data[ 8 ] = arr[ 0 ];
|
---|
5369 | data[ 9 ] = arr[ 1 ];
|
---|
5370 | data[ 10 ] = arr[ 2 ];
|
---|
5371 |
|
---|
5372 | // Now fix translation
|
---|
5373 | arr = [ data[ 3 ], data[ 7 ], data[ 11 ] ];
|
---|
5374 | fixCoords( arr, -1 );
|
---|
5375 | data[ 3 ] = arr[ 0 ];
|
---|
5376 | data[ 7 ] = arr[ 1 ];
|
---|
5377 | data[ 11 ] = arr[ 2 ];
|
---|
5378 |
|
---|
5379 | }
|
---|
5380 |
|
---|
5381 | return new THREE.Matrix4().set(
|
---|
5382 | data[0], data[1], data[2], data[3],
|
---|
5383 | data[4], data[5], data[6], data[7],
|
---|
5384 | data[8], data[9], data[10], data[11],
|
---|
5385 | data[12], data[13], data[14], data[15]
|
---|
5386 | );
|
---|
5387 |
|
---|
5388 | };
|
---|
5389 |
|
---|
5390 | function getConvertedIndex( index ) {
|
---|
5391 |
|
---|
5392 | if ( index > -1 && index < 3 ) {
|
---|
5393 |
|
---|
5394 | var members = ['X', 'Y', 'Z'],
|
---|
5395 | indices = { X: 0, Y: 1, Z: 2 };
|
---|
5396 |
|
---|
5397 | index = getConvertedMember( members[ index ] );
|
---|
5398 | index = indices[ index ];
|
---|
5399 |
|
---|
5400 | }
|
---|
5401 |
|
---|
5402 | return index;
|
---|
5403 |
|
---|
5404 | };
|
---|
5405 |
|
---|
5406 | function getConvertedMember( member ) {
|
---|
5407 |
|
---|
5408 | if ( options.convertUpAxis ) {
|
---|
5409 |
|
---|
5410 | switch ( member ) {
|
---|
5411 |
|
---|
5412 | case 'X':
|
---|
5413 |
|
---|
5414 | switch ( upConversion ) {
|
---|
5415 |
|
---|
5416 | case 'XtoY':
|
---|
5417 | case 'XtoZ':
|
---|
5418 | case 'YtoX':
|
---|
5419 |
|
---|
5420 | member = 'Y';
|
---|
5421 | break;
|
---|
5422 |
|
---|
5423 | case 'ZtoX':
|
---|
5424 |
|
---|
5425 | member = 'Z';
|
---|
5426 | break;
|
---|
5427 |
|
---|
5428 | }
|
---|
5429 |
|
---|
5430 | break;
|
---|
5431 |
|
---|
5432 | case 'Y':
|
---|
5433 |
|
---|
5434 | switch ( upConversion ) {
|
---|
5435 |
|
---|
5436 | case 'XtoY':
|
---|
5437 | case 'YtoX':
|
---|
5438 | case 'ZtoX':
|
---|
5439 |
|
---|
5440 | member = 'X';
|
---|
5441 | break;
|
---|
5442 |
|
---|
5443 | case 'XtoZ':
|
---|
5444 | case 'YtoZ':
|
---|
5445 | case 'ZtoY':
|
---|
5446 |
|
---|
5447 | member = 'Z';
|
---|
5448 | break;
|
---|
5449 |
|
---|
5450 | }
|
---|
5451 |
|
---|
5452 | break;
|
---|
5453 |
|
---|
5454 | case 'Z':
|
---|
5455 |
|
---|
5456 | switch ( upConversion ) {
|
---|
5457 |
|
---|
5458 | case 'XtoZ':
|
---|
5459 |
|
---|
5460 | member = 'X';
|
---|
5461 | break;
|
---|
5462 |
|
---|
5463 | case 'YtoZ':
|
---|
5464 | case 'ZtoX':
|
---|
5465 | case 'ZtoY':
|
---|
5466 |
|
---|
5467 | member = 'Y';
|
---|
5468 | break;
|
---|
5469 |
|
---|
5470 | }
|
---|
5471 |
|
---|
5472 | break;
|
---|
5473 |
|
---|
5474 | }
|
---|
5475 |
|
---|
5476 | }
|
---|
5477 |
|
---|
5478 | return member;
|
---|
5479 |
|
---|
5480 | };
|
---|
5481 |
|
---|
5482 | return {
|
---|
5483 |
|
---|
5484 | load: load,
|
---|
5485 | parse: parse,
|
---|
5486 | setPreferredShading: setPreferredShading,
|
---|
5487 | applySkin: applySkin,
|
---|
5488 | geometries : geometries,
|
---|
5489 | options: options
|
---|
5490 |
|
---|
5491 | };
|
---|
5492 |
|
---|
5493 | };
|
---|