From 78458614254eb4b18a2fdc669368107624ba1b91 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Thu, 15 Jun 2017 14:41:46 -0400 Subject: [PATCH 1/4] This test works. Why not in the main program? --- test/json-test.html | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 test/json-test.html diff --git a/test/json-test.html b/test/json-test.html new file mode 100644 index 0000000..2d4f202 --- /dev/null +++ b/test/json-test.html @@ -0,0 +1,47 @@ + + + + + JSON Test + + + + + + + + From 5efb27e97b18472ea9a64e45c5b1e0abdb185bef Mon Sep 17 00:00:00 2001 From: John Carlson Date: Thu, 15 Jun 2017 14:58:56 -0400 Subject: [PATCH 2/4] Enabled logging of output --- src/utils/JSONParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/JSONParser.js b/src/utils/JSONParser.js index 7a47d82..2d2c3aa 100644 --- a/src/utils/JSONParser.js +++ b/src/utils/JSONParser.js @@ -13,7 +13,7 @@ JSONParser.prototype.constructor = JSONParser; JSONParser.prototype.parseJavaScript = function(jsobj) { var child = this.CreateElement('scene'); this.ConvertToX3DOM(jsobj, "", child); - // console.log(jsobj, child); + console.log(jsobj, child); return child; }; From d1b518a63592e4b1e729b28581bd12afc11c38a8 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Thu, 15 Jun 2017 15:48:59 -0400 Subject: [PATCH 3/4] Added log message --- src/utils/JSONParser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/JSONParser.js b/src/utils/JSONParser.js index 2d2c3aa..bdc4539 100644 --- a/src/utils/JSONParser.js +++ b/src/utils/JSONParser.js @@ -1,6 +1,6 @@ "use strict"; -var JSONParser = function(scene) +var JSONParser = function() { } From 61c6250ab7c5b5dbf9cf66ac5e400d129118a493 Mon Sep 17 00:00:00 2001 From: John Carlson Date: Fri, 23 Jun 2017 22:06:49 -0400 Subject: [PATCH 4/4] added test/json-test.html and slightly modified src/utils/JSONParser. This code is released the public domain. --- Release/XSeen.js | 8 +- Release/XSeen.min.js | 19375 +++++++++++++++++++++-------------------- 2 files changed, 9692 insertions(+), 9691 deletions(-) diff --git a/Release/XSeen.js b/Release/XSeen.js index 4fde00a..e87e8d9 100644 --- a/Release/XSeen.js +++ b/Release/XSeen.js @@ -1,6 +1,6 @@ /* - * XSeen V0.3.6+12_b17c405 - * Built Fri Jun 23 14:35:00 2017 + * XSeen V0.3.6+12_6e139de + * Built Fri Jun 23 22:05:41 2017 * Dual licensed under the MIT and GPL licenses. @@ -9257,7 +9257,7 @@ THREE.GLTFLoader = ( function () { // File: utils/JSONParser.js "use strict"; -var JSONParser = function(scene) +var JSONParser = function() { } @@ -9270,7 +9270,7 @@ JSONParser.prototype.constructor = JSONParser; JSONParser.prototype.parseJavaScript = function(jsobj) { var child = this.CreateElement('scene'); this.ConvertToX3DOM(jsobj, "", child); - // console.log(jsobj, child); + console.log(jsobj, child); return child; }; diff --git a/Release/XSeen.min.js b/Release/XSeen.min.js index afaca0b..d90c2e6 100644 --- a/Release/XSeen.min.js +++ b/Release/XSeen.min.js @@ -1,9691 +1,9692 @@ /* - * XSeen V0.3.6+12_b17c405 - * Built Fri Jun 23 14:35:00 2017 + * XSeen V0.3.6+12_6e139de + * Built Fri Jun 23 22:05:41 2017 * -Dual licensed under the MIT and GPL licenses. - -==[MIT]==================================================================== -Copyright (c) 2017, Daly Realism - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -==[GPL]==================================================================== - -XSeen - Declarative 3D for HTML - -Copyright (C) 2017, Daly Realism - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - - -=== COPYRIGHT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - -Copyright (C) 2017, Daly Realism for XSeen -Copyright, Fraunhofer for X3DOM -Copyright, Mozilla for A-Frame -Copyright, THREE and Khronos for various parts of THREE.js -Copyright (C) 2017, John Carlson for JSON->XML converter (JSONParser.js) - -=== +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - */ -/** -* @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com -* @author Tony Parisi / http://www.tonyparisi.com/ -*/ -THREE.ColladaLoader = function () { -var COLLADA = null; -var scene = null; -var visualScene; -var kinematicsModel; -var readyCallbackFunc = null; -var sources = {}; -var images = {}; -var animations = {}; -var controllers = {}; -var geometries = {}; -var materials = {}; -var effects = {}; -var cameras = {}; -var lights = {}; -var animData; -var kinematics; -var visualScenes; -var kinematicsModels; -var baseUrl; -var morphs; -var skins; -var flip_uv = true; -var preferredShading = THREE.SmoothShading; -var options = { -centerGeometry: false, -convertUpAxis: false, -subdivideFaces: true, -upAxis: 'Y', -defaultEnvMap: null -}; -var colladaUnit = 1.0; -var colladaUp = 'Y'; -var upConversion = null; -function load ( url, readyCallback, progressCallback, failCallback ) { -var length = 0; -if ( document.implementation && document.implementation.createDocument ) { -var request = new XMLHttpRequest(); -request.onreadystatechange = function() { -if ( request.readyState === 4 ) { -if ( request.status === 0 || request.status === 200 ) { -if ( request.response ) { -readyCallbackFunc = readyCallback; -parse( request.response, undefined, url ); -} else { -if ( failCallback ) { -failCallback( { type: 'error', url: url } ); -} else { -console.error( "ColladaLoader: Empty or non-existing file (" + url + ")" ); -} -} -}else{ -if( failCallback ){ -failCallback( { type: 'error', url: url } ); -}else{ -console.error( 'ColladaLoader: Couldn\'t load "' + url + '" (' + request.status + ')' ); -} -} -} else if ( request.readyState === 3 ) { -if ( progressCallback ) { -if ( length === 0 ) { -length = request.getResponseHeader( "Content-Length" ); -} -progressCallback( { total: length, loaded: request.responseText.length } ); -} -} -}; -request.open( "GET", url, true ); -request.send( null ); -} else { -alert( "Don't know how to parse XML!" ); -} -} -function parse( text, callBack, url ) { -COLLADA = new DOMParser().parseFromString( text, 'text/xml' ); -callBack = callBack || readyCallbackFunc; -if ( url !== undefined ) { -var parts = url.split( '/' ); -parts.pop(); -baseUrl = ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/'; -} -parseAsset(); -setUpConversion(); -images = parseLib( "library_images image", _Image, "image" ); -materials = parseLib( "library_materials material", Material, "material" ); -effects = parseLib( "library_effects effect", Effect, "effect" ); -geometries = parseLib( "library_geometries geometry", Geometry, "geometry" ); -cameras = parseLib( "library_cameras camera", Camera, "camera" ); -lights = parseLib( "library_lights light", Light, "light" ); -controllers = parseLib( "library_controllers controller", Controller, "controller" ); -animations = parseLib( "library_animations animation", Animation, "animation" ); -visualScenes = parseLib( "library_visual_scenes visual_scene", VisualScene, "visual_scene" ); -kinematicsModels = parseLib( "library_kinematics_models kinematics_model", KinematicsModel, "kinematics_model" ); -morphs = []; -skins = []; -visualScene = parseScene(); -scene = new THREE.Group(); -for ( var i = 0; i < visualScene.nodes.length; i ++ ) { -scene.add( createSceneGraph( visualScene.nodes[ i ] ) ); -} -scene.scale.multiplyScalar( colladaUnit ); -createAnimations(); -kinematicsModel = parseKinematicsModel(); -createKinematics(); -var result = { -scene: scene, -morphs: morphs, -skins: skins, -animations: animData, -kinematics: kinematics, -dae: { -images: images, -materials: materials, -cameras: cameras, -lights: lights, -effects: effects, -geometries: geometries, -controllers: controllers, -animations: animations, -visualScenes: visualScenes, -visualScene: visualScene, -scene: visualScene, -kinematicsModels: kinematicsModels, -kinematicsModel: kinematicsModel -} -}; -if ( callBack ) { -callBack( result ); -} -return result; -} -function setPreferredShading ( shading ) { -preferredShading = shading; -} -function parseAsset () { -var elements = COLLADA.querySelectorAll('asset'); -var element = elements[0]; -if ( element && element.childNodes ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'unit': -var meter = child.getAttribute( 'meter' ); -if ( meter ) { -colladaUnit = parseFloat( meter ); -} -break; -case 'up_axis': -colladaUp = child.textContent.charAt(0); -break; -} -} -} -} -function parseLib ( q, classSpec, prefix ) { -var elements = COLLADA.querySelectorAll(q); -var lib = {}; -var i = 0; -var elementsLength = elements.length; -for ( var j = 0; j < elementsLength; j ++ ) { -var element = elements[j]; -var daeElement = ( new classSpec() ).parse( element ); -if ( !daeElement.id || daeElement.id.length === 0 ) daeElement.id = prefix + ( i ++ ); -lib[ daeElement.id ] = daeElement; -} -return lib; -} -function parseScene() { -var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0]; -if ( sceneElement ) { -var url = sceneElement.getAttribute( 'url' ).replace( /^#/, '' ); -return visualScenes[ url.length > 0 ? url : 'visual_scene0' ]; -} else { -return null; -} -} -function parseKinematicsModel() { -var kinematicsModelElement = COLLADA.querySelectorAll('instance_kinematics_model')[0]; -if ( kinematicsModelElement ) { -var url = kinematicsModelElement.getAttribute( 'url' ).replace(/^#/, ''); -return kinematicsModels[ url.length > 0 ? url : 'kinematics_model0' ]; -} else { -return null; -} -} -function createAnimations() { -animData = []; -recurseHierarchy( scene ); -} -function recurseHierarchy( node ) { -var n = visualScene.getChildById( node.colladaId, true ), -newData = null; -if ( n && n.keys ) { -newData = { -fps: 60, -hierarchy: [ { -node: n, -keys: n.keys, -sids: n.sids -} ], -node: node, -name: 'animation_' + node.name, -length: 0 -}; -animData.push(newData); -for ( var i = 0, il = n.keys.length; i < il; i ++ ) { -newData.length = Math.max( newData.length, n.keys[i].time ); -} -} else { -newData = { -hierarchy: [ { -keys: [], -sids: [] -} ] -} -} -for ( var i = 0, il = node.children.length; i < il; i ++ ) { -var d = recurseHierarchy( node.children[i] ); -for ( var j = 0, jl = d.hierarchy.length; j < jl; j ++ ) { -newData.hierarchy.push( { -keys: [], -sids: [] -} ); -} -} -return newData; -} -function calcAnimationBounds () { -var start = 1000000; -var end = -start; -var frames = 0; -var ID; -for ( var id in animations ) { -var animation = animations[ id ]; -ID = ID || animation.id; -for ( var i = 0; i < animation.sampler.length; i ++ ) { -var sampler = animation.sampler[ i ]; -sampler.create(); -start = Math.min( start, sampler.startTime ); -end = Math.max( end, sampler.endTime ); -frames = Math.max( frames, sampler.input.length ); -} -} -return { start:start, end:end, frames:frames,ID:ID }; -} -function createMorph ( geometry, ctrl ) { -var morphCtrl = ctrl instanceof InstanceController ? controllers[ ctrl.url ] : ctrl; -if ( !morphCtrl || !morphCtrl.morph ) { -console.log("could not find morph controller!"); -return; -} -var morph = morphCtrl.morph; -for ( var i = 0; i < morph.targets.length; i ++ ) { -var target_id = morph.targets[ i ]; -var daeGeometry = geometries[ target_id ]; -if ( !daeGeometry.mesh || -!daeGeometry.mesh.primitives || -!daeGeometry.mesh.primitives.length ) { -continue; -} -var target = daeGeometry.mesh.primitives[ 0 ].geometry; -if ( target.vertices.length === geometry.vertices.length ) { -geometry.morphTargets.push( { name: "target_1", vertices: target.vertices } ); -} -} -geometry.morphTargets.push( { name: "target_Z", vertices: geometry.vertices } ); -} -function createSkin ( geometry, ctrl, applyBindShape ) { -var skinCtrl = controllers[ ctrl.url ]; -if ( !skinCtrl || !skinCtrl.skin ) { -console.log( "could not find skin controller!" ); -return; -} -if ( !ctrl.skeleton || !ctrl.skeleton.length ) { -console.log( "could not find the skeleton for the skin!" ); -return; -} -var skin = skinCtrl.skin; -var skeleton = visualScene.getChildById( ctrl.skeleton[ 0 ] ); -var hierarchy = []; -applyBindShape = applyBindShape !== undefined ? applyBindShape : true; -var bones = []; -geometry.skinWeights = []; -geometry.skinIndices = []; -/* -geometry.animation = { -name: 'take_001', -fps: 30, -length: 2, -JIT: true, -hierarchy: hierarchy -}; -*/ -if ( applyBindShape ) { -for ( var i = 0; i < geometry.vertices.length; i ++ ) { -geometry.vertices[ i ].applyMatrix4( skin.bindShapeMatrix ); -} -} -} -function setupSkeleton ( node, bones, frame, parent ) { -node.world = node.world || new THREE.Matrix4(); -node.localworld = node.localworld || new THREE.Matrix4(); -node.world.copy( node.matrix ); -node.localworld.copy( node.matrix ); -if ( node.channels && node.channels.length ) { -var channel = node.channels[ 0 ]; -var m = channel.sampler.output[ frame ]; -if ( m instanceof THREE.Matrix4 ) { -node.world.copy( m ); -node.localworld.copy(m); -if (frame === 0) -node.matrix.copy(m); -} -} -if ( parent ) { -node.world.multiplyMatrices( parent, node.world ); -} -bones.push( node ); -for ( var i = 0; i < node.nodes.length; i ++ ) { -setupSkeleton( node.nodes[ i ], bones, frame, node.world ); -} -} -function setupSkinningMatrices ( bones, skin ) { -for ( var i = 0; i < bones.length; i ++ ) { -var bone = bones[ i ]; -var found = -1; -if ( bone.type != 'JOINT' ) continue; -for ( var j = 0; j < skin.joints.length; j ++ ) { -if ( bone.sid === skin.joints[ j ] ) { -found = j; -break; -} -} -if ( found >= 0 ) { -var inv = skin.invBindMatrices[ found ]; -bone.invBindMatrix = inv; -bone.skinningMatrix = new THREE.Matrix4(); -bone.skinningMatrix.multiplyMatrices(bone.world, inv); // (IBMi * JMi) -bone.animatrix = new THREE.Matrix4(); -bone.animatrix.copy(bone.localworld); -bone.weights = []; -for ( var j = 0; j < skin.weights.length; j ++ ) { -for (var k = 0; k < skin.weights[ j ].length; k ++ ) { -var w = skin.weights[ j ][ k ]; -if ( w.joint === found ) { -bone.weights.push( w ); -} -} -} -} else { -console.warn( "ColladaLoader: Could not find joint '" + bone.sid + "'." ); -bone.skinningMatrix = new THREE.Matrix4(); -bone.weights = []; -} -} -} -function flattenSkeleton(skeleton) { -var list = []; -var walk = function(parentid, node, list) { -var bone = {}; -bone.name = node.sid; -bone.parent = parentid; -bone.matrix = node.matrix; -var data = [ new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3() ]; -bone.matrix.decompose(data[0], data[1], data[2]); -bone.pos = [ data[0].x,data[0].y,data[0].z ]; -bone.scl = [ data[2].x,data[2].y,data[2].z ]; -bone.rotq = [ data[1].x,data[1].y,data[1].z,data[1].w ]; -list.push(bone); -for (var i in node.nodes) { -walk(node.sid, node.nodes[i], list); -} -}; -walk(-1, skeleton, list); -return list; -} -function skinToBindPose(geometry,skeleton,skinController) { -var bones = []; -setupSkeleton( skeleton, bones, -1 ); -setupSkinningMatrices( bones, skinController.skin ); -var v = new THREE.Vector3(); -var skinned = []; -for (var i = 0; i < geometry.vertices.length; i ++) { -skinned.push(new THREE.Vector3()); -} -for ( i = 0; i < bones.length; i ++ ) { -if ( bones[ i ].type != 'JOINT' ) continue; -for ( var j = 0; j < bones[ i ].weights.length; j ++ ) { -var w = bones[ i ].weights[ j ]; -var vidx = w.index; -var weight = w.weight; -var o = geometry.vertices[vidx]; -var s = skinned[vidx]; -v.x = o.x; -v.y = o.y; -v.z = o.z; -v.applyMatrix4( bones[i].skinningMatrix ); -s.x += (v.x * weight); -s.y += (v.y * weight); -s.z += (v.z * weight); -} -} -for (var i = 0; i < geometry.vertices.length; i ++) { -geometry.vertices[i] = skinned[i]; -} -} -function applySkin ( geometry, instanceCtrl, frame ) { -var skinController = controllers[ instanceCtrl.url ]; -frame = frame !== undefined ? frame : 40; -if ( !skinController || !skinController.skin ) { -console.log( 'ColladaLoader: Could not find skin controller.' ); -return; -} -if ( !instanceCtrl.skeleton || !instanceCtrl.skeleton.length ) { -console.log( 'ColladaLoader: Could not find the skeleton for the skin. ' ); -return; -} -var animationBounds = calcAnimationBounds(); -var skeleton = visualScene.getChildById( instanceCtrl.skeleton[0], true ) || visualScene.getChildBySid( instanceCtrl.skeleton[0], true ); -var bonelist = flattenSkeleton(skeleton); -var joints = skinController.skin.joints; -var sortedbones = []; -for (var i = 0; i < joints.length; i ++) { -for (var j = 0; j < bonelist.length; j ++) { -if (bonelist[j].name === joints[i]) { -sortedbones[i] = bonelist[j]; -} -} -} -for (var i = 0; i < sortedbones.length; i ++) { -for (var j = 0; j < sortedbones.length; j ++) { -if (sortedbones[i].parent === sortedbones[j].name) { -sortedbones[i].parent = j; -} -} -} -var i, j, w, vidx, weight; -var v = new THREE.Vector3(), o, s; -for ( i = 0; i < geometry.vertices.length; i ++ ) { -geometry.vertices[i].applyMatrix4( skinController.skin.bindShapeMatrix ); -} -var skinIndices = []; -var skinWeights = []; -var weights = skinController.skin.weights; -for ( var i =0; i < weights.length; i ++ ) { -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); -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); -skinIndices.push(indicies); -skinWeights.push(weight); -} -geometry.skinIndices = skinIndices; -geometry.skinWeights = skinWeights; -geometry.bones = sortedbones; -var animationdata = { "name":animationBounds.ID,"fps":30,"length":animationBounds.frames / 30,"hierarchy":[] }; -for (var j = 0; j < sortedbones.length; j ++) { -animationdata.hierarchy.push({ parent:sortedbones[j].parent, name:sortedbones[j].name, keys:[] }); -} -console.log( 'ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.' ); -skinToBindPose(geometry, skeleton, skinController); -for ( frame = 0; frame < animationBounds.frames; frame ++ ) { -var bones = []; -var skinned = []; -setupSkeleton( skeleton, bones, frame ); -setupSkinningMatrices( bones, skinController.skin ); -for (var i = 0; i < bones.length; i ++) { -for (var j = 0; j < animationdata.hierarchy.length; j ++) { -if (animationdata.hierarchy[j].name === bones[i].sid) { -var key = {}; -key.time = (frame / 30); -key.matrix = bones[i].animatrix; -if (frame === 0) -bones[i].matrix = key.matrix; -var data = [ new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3() ]; -key.matrix.decompose(data[0], data[1], data[2]); -key.pos = [ data[0].x,data[0].y,data[0].z ]; -key.scl = [ data[2].x,data[2].y,data[2].z ]; -key.rot = data[1]; -animationdata.hierarchy[j].keys.push(key); -} -} -} -geometry.animation = animationdata; -} -} -function createKinematics() { -if ( kinematicsModel && kinematicsModel.joints.length === 0 ) { -kinematics = undefined; -return; -} -var jointMap = {}; -var _addToMap = function( jointIndex, parentVisualElement ) { -var parentVisualElementId = parentVisualElement.getAttribute( 'id' ); -var colladaNode = visualScene.getChildById( parentVisualElementId, true ); -var joint = kinematicsModel.joints[ jointIndex ]; -scene.traverse(function( node ) { -if ( node.colladaId == parentVisualElementId ) { -jointMap[ jointIndex ] = { -node: node, -transforms: colladaNode.transforms, -joint: joint, -position: joint.zeroPosition -}; -} -}); -}; -kinematics = { -joints: kinematicsModel && kinematicsModel.joints, -getJointValue: function( jointIndex ) { -var jointData = jointMap[ jointIndex ]; -if ( jointData ) { -return jointData.position; -} else { -console.log( 'getJointValue: joint ' + jointIndex + ' doesn\'t exist' ); -} -}, -setJointValue: function( jointIndex, value ) { -var jointData = jointMap[ jointIndex ]; -if ( jointData ) { -var joint = jointData.joint; -if ( value > joint.limits.max || value < joint.limits.min ) { -console.log( 'setJointValue: joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ')' ); -} else if ( joint.static ) { -console.log( 'setJointValue: joint ' + jointIndex + ' is static' ); -} else { -var threejsNode = jointData.node; -var axis = joint.axis; -var transforms = jointData.transforms; -var matrix = new THREE.Matrix4(); -var m1 = new THREE.Matrix4(); -for (i = 0; i < transforms.length; i ++ ) { -var transform = transforms[ i ]; -if ( transform.sid && transform.sid.indexOf( 'joint' + jointIndex ) !== -1 ) { -switch ( joint.type ) { -case 'revolute': -matrix.multiply( m1.makeRotationAxis( axis, THREE.Math.degToRad(value) ) ); -break; -case 'prismatic': -matrix.multiply( m1.makeTranslation(axis.x * value, axis.y * value, axis.z * value ) ); -break; -default: -console.warn( 'setJointValue: unknown joint type: ' + joint.type ); -break; -} -} else { -switch ( transform.type ) { -case 'matrix': -matrix.multiply( transform.obj ); -break; -case 'translate': -matrix.multiply( m1.makeTranslation( transform.obj.x, transform.obj.y, transform.obj.z ) ); -break; -case 'rotate': -matrix.multiply( m1.makeRotationAxis( transform.obj, transform.angle ) ); -break; -} -} -} -var elementsFloat32Arr = matrix.elements; -var elements = Array.prototype.slice.call( elementsFloat32Arr ); -var elementsRowMajor = [ -elements[ 0 ], -elements[ 4 ], -elements[ 8 ], -elements[ 12 ], -elements[ 1 ], -elements[ 5 ], -elements[ 9 ], -elements[ 13 ], -elements[ 2 ], -elements[ 6 ], -elements[ 10 ], -elements[ 14 ], -elements[ 3 ], -elements[ 7 ], -elements[ 11 ], -elements[ 15 ] -]; -threejsNode.matrix.set.apply( threejsNode.matrix, elementsRowMajor ); -threejsNode.matrix.decompose( threejsNode.position, threejsNode.quaternion, threejsNode.scale ); -jointMap[ jointIndex ].position = value; -} -} else { -console.log( 'setJointValue: joint ' + jointIndex + ' doesn\'t exist' ); -} -} -}; -var element = COLLADA.querySelector('scene instance_kinematics_scene'); -if ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'bind_joint_axis': -var visualTarget = child.getAttribute( 'target' ).split( '/' ).pop(); -var axis = child.querySelector('axis param').textContent; -var jointIndex = parseInt( axis.split( 'joint' ).pop().split( '.' )[0] ); -var visualTargetElement = COLLADA.querySelector( '[sid="' + visualTarget + '"]' ); -if ( visualTargetElement ) { -var parentVisualElement = visualTargetElement.parentElement; -_addToMap(jointIndex, parentVisualElement); -} -break; -default: -break; -} -} -} -} -function createSceneGraph ( node, parent ) { -var obj = new THREE.Object3D(); -var skinned = false; -var skinController; -var morphController; -var i, j; -for ( i = 0; i < node.controllers.length; i ++ ) { -var controller = controllers[ node.controllers[ i ].url ]; -switch ( controller.type ) { -case 'skin': -if ( geometries[ controller.skin.source ] ) { -var inst_geom = new InstanceGeometry(); -inst_geom.url = controller.skin.source; -inst_geom.instance_material = node.controllers[ i ].instance_material; -node.geometries.push( inst_geom ); -skinned = true; -skinController = node.controllers[ i ]; -} else if ( controllers[ controller.skin.source ] ) { -var second = controllers[ controller.skin.source ]; -morphController = second; -if ( second.morph && geometries[ second.morph.source ] ) { -var inst_geom = new InstanceGeometry(); -inst_geom.url = second.morph.source; -inst_geom.instance_material = node.controllers[ i ].instance_material; -node.geometries.push( inst_geom ); -} -} -break; -case 'morph': -if ( geometries[ controller.morph.source ] ) { -var inst_geom = new InstanceGeometry(); -inst_geom.url = controller.morph.source; -inst_geom.instance_material = node.controllers[ i ].instance_material; -node.geometries.push( inst_geom ); -morphController = node.controllers[ i ]; -} -console.log( 'ColladaLoader: Morph-controller partially supported.' ); -default: -break; -} -} -var double_sided_materials = {}; -for ( i = 0; i < node.geometries.length; i ++ ) { -var instance_geometry = node.geometries[i]; -var instance_materials = instance_geometry.instance_material; -var geometry = geometries[ instance_geometry.url ]; -var used_materials = {}; -var used_materials_array = []; -var num_materials = 0; -var first_material; -if ( geometry ) { -if ( !geometry.mesh || !geometry.mesh.primitives ) -continue; -if ( obj.name.length === 0 ) { -obj.name = geometry.id; -} -if ( instance_materials ) { -for ( j = 0; j < instance_materials.length; j ++ ) { -var instance_material = instance_materials[ j ]; -var mat = materials[ instance_material.target ]; -var effect_id = mat.instance_effect.url; -var shader = effects[ effect_id ].shader; -var material3js = shader.material; -if ( geometry.doubleSided ) { -if ( !( instance_material.symbol in double_sided_materials ) ) { -var _copied_material = material3js.clone(); -_copied_material.side = THREE.DoubleSide; -double_sided_materials[ instance_material.symbol ] = _copied_material; -} -material3js = double_sided_materials[ instance_material.symbol ]; -} -material3js.opacity = !material3js.opacity ? 1 : material3js.opacity; -used_materials[ instance_material.symbol ] = num_materials; -used_materials_array.push( material3js ); -first_material = material3js; -first_material.name = mat.name === null || mat.name === '' ? mat.id : mat.name; -num_materials ++; -} -} -var mesh; -var material = first_material || new THREE.MeshLambertMaterial( { color: 0xdddddd, side: geometry.doubleSided ? THREE.DoubleSide : THREE.FrontSide } ); -var geom = geometry.mesh.geometry3js; -if ( num_materials > 1 ) { -material = new THREE.MultiMaterial( used_materials_array ); -for ( j = 0; j < geom.faces.length; j ++ ) { -var face = geom.faces[ j ]; -face.materialIndex = used_materials[ face.daeMaterial ] -} -} -if ( skinController !== undefined ) { -applySkin( geom, skinController ); -if ( geom.morphTargets.length > 0 ) { -material.morphTargets = true; -material.skinning = false; -} else { -material.morphTargets = false; -material.skinning = true; -} -mesh = new THREE.SkinnedMesh( geom, material, false ); -mesh.name = 'skin_' + skins.length; -skins.push( mesh ); -} else if ( morphController !== undefined ) { -createMorph( geom, morphController ); -material.morphTargets = true; -mesh = new THREE.Mesh( geom, material ); -mesh.name = 'morph_' + morphs.length; -morphs.push( mesh ); -} else { -if ( geom.isLineStrip === true ) { -mesh = new THREE.Line( geom ); -} else { -mesh = new THREE.Mesh( geom, material ); -} -} -obj.add(mesh); -} -} -for ( i = 0; i < node.cameras.length; i ++ ) { -var instance_camera = node.cameras[i]; -var cparams = cameras[instance_camera.url]; -var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio), -parseFloat(cparams.znear), parseFloat(cparams.zfar)); -obj.add(cam); -} -for ( i = 0; i < node.lights.length; i ++ ) { -var light = null; -var instance_light = node.lights[i]; -var lparams = lights[instance_light.url]; -if ( lparams && lparams.technique ) { -var color = lparams.color.getHex(); -var intensity = lparams.intensity; -var distance = lparams.distance; -var angle = lparams.falloff_angle; -switch ( lparams.technique ) { -case 'directional': -light = new THREE.DirectionalLight( color, intensity, distance ); -light.position.set(0, 0, 1); -break; -case 'point': -light = new THREE.PointLight( color, intensity, distance ); -break; -case 'spot': -light = new THREE.SpotLight( color, intensity, distance, angle ); -light.position.set(0, 0, 1); -break; -case 'ambient': -light = new THREE.AmbientLight( color ); -break; -} -} -if (light) { -obj.add(light); -} -} -obj.name = node.name || node.id || ""; -obj.colladaId = node.id || ""; -obj.layer = node.layer || ""; -obj.matrix = node.matrix; -obj.matrix.decompose( obj.position, obj.quaternion, obj.scale ); -if ( options.centerGeometry && obj.geometry ) { -var delta = obj.geometry.center(); -delta.multiply( obj.scale ); -delta.applyQuaternion( obj.quaternion ); -obj.position.sub( delta ); -} -for ( i = 0; i < node.nodes.length; i ++ ) { -obj.add( createSceneGraph( node.nodes[i], node ) ); -} -return obj; -} -function getJointId( skin, id ) { -for ( var i = 0; i < skin.joints.length; i ++ ) { -if ( skin.joints[ i ] === id ) { -return i; -} -} -} -function getLibraryNode( id ) { -var nodes = COLLADA.querySelectorAll('library_nodes node'); -for ( var i = 0; i < nodes.length; i++ ) { -var attObj = nodes[i].attributes.getNamedItem('id'); -if ( attObj && attObj.value === id ) { -return nodes[i]; -} -} -return undefined; -} -function getChannelsForNode ( node ) { -var channels = []; -var startTime = 1000000; -var endTime = -1000000; -for ( var id in animations ) { -var animation = animations[id]; -for ( var i = 0; i < animation.channel.length; i ++ ) { -var channel = animation.channel[i]; -var sampler = animation.sampler[i]; -var id = channel.target.split('/')[0]; -if ( id == node.id ) { -sampler.create(); -channel.sampler = sampler; -startTime = Math.min(startTime, sampler.startTime); -endTime = Math.max(endTime, sampler.endTime); -channels.push(channel); -} -} -} -if ( channels.length ) { -node.startTime = startTime; -node.endTime = endTime; -} -return channels; -} -function calcFrameDuration( node ) { -var minT = 10000000; -for ( var i = 0; i < node.channels.length; i ++ ) { -var sampler = node.channels[i].sampler; -for ( var j = 0; j < sampler.input.length - 1; j ++ ) { -var t0 = sampler.input[ j ]; -var t1 = sampler.input[ j + 1 ]; -minT = Math.min( minT, t1 - t0 ); -} -} -return minT; -} -function calcMatrixAt( node, t ) { -var animated = {}; -var i, j; -for ( i = 0; i < node.channels.length; i ++ ) { -var channel = node.channels[ i ]; -animated[ channel.sid ] = channel; -} -var matrix = new THREE.Matrix4(); -for ( i = 0; i < node.transforms.length; i ++ ) { -var transform = node.transforms[ i ]; -var channel = animated[ transform.sid ]; -if ( channel !== undefined ) { -var sampler = channel.sampler; -var value; -for ( j = 0; j < sampler.input.length - 1; j ++ ) { -if ( sampler.input[ j + 1 ] > t ) { -value = sampler.output[ j ]; -break; -} -} -if ( value !== undefined ) { -if ( value instanceof THREE.Matrix4 ) { -matrix.multiplyMatrices( matrix, value ); -} else { -matrix.multiplyMatrices( matrix, transform.matrix ); -} -} else { -matrix.multiplyMatrices( matrix, transform.matrix ); -} -} else { -matrix.multiplyMatrices( matrix, transform.matrix ); -} -} -return matrix; -} -function bakeAnimations ( node ) { -if ( node.channels && node.channels.length ) { -var keys = [], -sids = []; -for ( var i = 0, il = node.channels.length; i < il; i ++ ) { -var channel = node.channels[i], -fullSid = channel.fullSid, -sampler = channel.sampler, -input = sampler.input, -transform = node.getTransformBySid( channel.sid ), -member; -if ( channel.arrIndices ) { -member = []; -for ( var j = 0, jl = channel.arrIndices.length; j < jl; j ++ ) { -member[ j ] = getConvertedIndex( channel.arrIndices[ j ] ); -} -} else { -member = getConvertedMember( channel.member ); -} -if ( transform ) { -if ( sids.indexOf( fullSid ) === -1 ) { -sids.push( fullSid ); -} -for ( var j = 0, jl = input.length; j < jl; j ++ ) { -var time = input[j], -data = sampler.getData( transform.type, j, member ), -key = findKey( keys, time ); -if ( !key ) { -key = new Key( time ); -var timeNdx = findTimeNdx( keys, time ); -keys.splice( timeNdx === -1 ? keys.length : timeNdx, 0, key ); -} -key.addTarget( fullSid, transform, member, data ); -} -} else { -console.log( 'Could not find transform "' + channel.sid + '" in node ' + node.id ); -} -} -for ( var i = 0; i < sids.length; i ++ ) { -var sid = sids[ i ]; -for ( var j = 0; j < keys.length; j ++ ) { -var key = keys[ j ]; -if ( !key.hasTarget( sid ) ) { -interpolateKeys( keys, key, j, sid ); -} -} -} -node.keys = keys; -node.sids = sids; -} -} -function findKey ( keys, time) { -var retVal = null; -for ( var i = 0, il = keys.length; i < il && retVal === null; i ++ ) { -var key = keys[i]; -if ( key.time === time ) { -retVal = key; -} else if ( key.time > time ) { -break; -} -} -return retVal; -} -function findTimeNdx ( keys, time) { -var ndx = -1; -for ( var i = 0, il = keys.length; i < il && ndx === -1; i ++ ) { -var key = keys[i]; -if ( key.time >= time ) { -ndx = i; -} -} -return ndx; -} -function interpolateKeys ( keys, key, ndx, fullSid ) { -var prevKey = getPrevKeyWith( keys, fullSid, ndx ? ndx - 1 : 0 ), -nextKey = getNextKeyWith( keys, fullSid, ndx + 1 ); -if ( prevKey && nextKey ) { -var scale = (key.time - prevKey.time) / (nextKey.time - prevKey.time), -prevTarget = prevKey.getTarget( fullSid ), -nextData = nextKey.getTarget( fullSid ).data, -prevData = prevTarget.data, -data; -if ( prevTarget.type === 'matrix' ) { -data = prevData; -} else if ( prevData.length ) { -data = []; -for ( var i = 0; i < prevData.length; ++ i ) { -data[ i ] = prevData[ i ] + ( nextData[ i ] - prevData[ i ] ) * scale; -} -} else { -data = prevData + ( nextData - prevData ) * scale; -} -key.addTarget( fullSid, prevTarget.transform, prevTarget.member, data ); -} -} -function getNextKeyWith( keys, fullSid, ndx ) { -for ( ; ndx < keys.length; ndx ++ ) { -var key = keys[ ndx ]; -if ( key.hasTarget( fullSid ) ) { -return key; -} -} -return null; -} -function getPrevKeyWith( keys, fullSid, ndx ) { -ndx = ndx >= 0 ? ndx : ndx + keys.length; -for ( ; ndx >= 0; ndx -- ) { -var key = keys[ ndx ]; -if ( key.hasTarget( fullSid ) ) { -return key; -} -} -return null; -} -function _Image() { -this.id = ""; -this.init_from = ""; -} -_Image.prototype.parse = function(element) { -this.id = element.getAttribute('id'); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeName === 'init_from' ) { -this.init_from = child.textContent; -} -} -return this; -}; -function Controller() { -this.id = ""; -this.name = ""; -this.type = ""; -this.skin = null; -this.morph = null; -} -Controller.prototype.parse = function( element ) { -this.id = element.getAttribute('id'); -this.name = element.getAttribute('name'); -this.type = "none"; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'skin': -this.skin = (new Skin()).parse(child); -this.type = child.nodeName; -break; -case 'morph': -this.morph = (new Morph()).parse(child); -this.type = child.nodeName; -break; -default: -break; -} -} -return this; -}; -function Morph() { -this.method = null; -this.source = null; -this.targets = null; -this.weights = null; -} -Morph.prototype.parse = function( element ) { -var sources = {}; -var inputs = []; -var i; -this.method = element.getAttribute( 'method' ); -this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); -for ( i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'source': -var source = ( new Source() ).parse( child ); -sources[ source.id ] = source; -break; -case 'targets': -inputs = this.parseInputs( child ); -break; -default: -console.log( child.nodeName ); -break; -} -} -for ( i = 0; i < inputs.length; i ++ ) { -var input = inputs[ i ]; -var source = sources[ input.source ]; -switch ( input.semantic ) { -case 'MORPH_TARGET': -this.targets = source.read(); -break; -case 'MORPH_WEIGHT': -this.weights = source.read(); -break; -default: -break; -} -} -return this; -}; -Morph.prototype.parseInputs = function(element) { -var inputs = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1) continue; -switch ( child.nodeName ) { -case 'input': -inputs.push( (new Input()).parse(child) ); -break; -default: -break; -} -} -return inputs; -}; -function Skin() { -this.source = ""; -this.bindShapeMatrix = null; -this.invBindMatrices = []; -this.joints = []; -this.weights = []; -} -Skin.prototype.parse = function( element ) { -var sources = {}; -var joints, weights; -this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); -this.invBindMatrices = []; -this.joints = []; -this.weights = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'bind_shape_matrix': -var f = _floats(child.textContent); -this.bindShapeMatrix = getConvertedMat4( f ); -break; -case 'source': -var src = new Source().parse(child); -sources[ src.id ] = src; -break; -case 'joints': -joints = child; -break; -case 'vertex_weights': -weights = child; -break; -default: -console.log( child.nodeName ); -break; -} -} -this.parseJoints( joints, sources ); -this.parseWeights( weights, sources ); -return this; -}; -Skin.prototype.parseJoints = function ( element, sources ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'input': -var input = ( new Input() ).parse( child ); -var source = sources[ input.source ]; -if ( input.semantic === 'JOINT' ) { -this.joints = source.read(); -} else if ( input.semantic === 'INV_BIND_MATRIX' ) { -this.invBindMatrices = source.read(); -} -break; -default: -break; -} -} -}; -Skin.prototype.parseWeights = function ( element, sources ) { -var v, vcount, inputs = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'input': -inputs.push( ( new Input() ).parse( child ) ); -break; -case 'v': -v = _ints( child.textContent ); -break; -case 'vcount': -vcount = _ints( child.textContent ); -break; -default: -break; -} -} -var index = 0; -for ( var i = 0; i < vcount.length; i ++ ) { -var numBones = vcount[i]; -var vertex_weights = []; -for ( var j = 0; j < numBones; j ++ ) { -var influence = {}; -for ( var k = 0; k < inputs.length; k ++ ) { -var input = inputs[ k ]; -var value = v[ index + input.offset ]; -switch ( input.semantic ) { -case 'JOINT': -influence.joint = value;//this.joints[value]; -break; -case 'WEIGHT': -influence.weight = sources[ input.source ].data[ value ]; -break; -default: -break; -} -} -vertex_weights.push( influence ); -index += inputs.length; -} -for ( var j = 0; j < vertex_weights.length; j ++ ) { -vertex_weights[ j ].index = i; -} -this.weights.push( vertex_weights ); -} -}; -function VisualScene () { -this.id = ""; -this.name = ""; -this.nodes = []; -this.scene = new THREE.Group(); -} -VisualScene.prototype.getChildById = function( id, recursive ) { -for ( var i = 0; i < this.nodes.length; i ++ ) { -var node = this.nodes[ i ].getChildById( id, recursive ); -if ( node ) { -return node; -} -} -return null; -}; -VisualScene.prototype.getChildBySid = function( sid, recursive ) { -for ( var i = 0; i < this.nodes.length; i ++ ) { -var node = this.nodes[ i ].getChildBySid( sid, recursive ); -if ( node ) { -return node; -} -} -return null; -}; -VisualScene.prototype.parse = function( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -this.nodes = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'node': -this.nodes.push( ( new Node() ).parse( child ) ); -break; -default: -break; -} -} -return this; -}; -function Node() { -this.id = ""; -this.name = ""; -this.sid = ""; -this.nodes = []; -this.controllers = []; -this.transforms = []; -this.geometries = []; -this.channels = []; -this.matrix = new THREE.Matrix4(); -} -Node.prototype.getChannelForTransform = function( transformSid ) { -for ( var i = 0; i < this.channels.length; i ++ ) { -var channel = this.channels[i]; -var parts = channel.target.split('/'); -var id = parts.shift(); -var sid = parts.shift(); -var dotSyntax = (sid.indexOf(".") >= 0); -var arrSyntax = (sid.indexOf("(") >= 0); -var arrIndices; -var member; -if ( dotSyntax ) { -parts = sid.split("."); -sid = parts.shift(); -member = parts.shift(); -} else if ( arrSyntax ) { -arrIndices = sid.split("("); -sid = arrIndices.shift(); -for ( var j = 0; j < arrIndices.length; j ++ ) { -arrIndices[ j ] = parseInt( arrIndices[ j ].replace( /\)/, '' ) ); -} -} -if ( sid === transformSid ) { -channel.info = { sid: sid, dotSyntax: dotSyntax, arrSyntax: arrSyntax, arrIndices: arrIndices }; -return channel; -} -} -return null; -}; -Node.prototype.getChildById = function ( id, recursive ) { -if ( this.id === id ) { -return this; -} -if ( recursive ) { -for ( var i = 0; i < this.nodes.length; i ++ ) { -var n = this.nodes[ i ].getChildById( id, recursive ); -if ( n ) { -return n; -} -} -} -return null; -}; -Node.prototype.getChildBySid = function ( sid, recursive ) { -if ( this.sid === sid ) { -return this; -} -if ( recursive ) { -for ( var i = 0; i < this.nodes.length; i ++ ) { -var n = this.nodes[ i ].getChildBySid( sid, recursive ); -if ( n ) { -return n; -} -} -} -return null; -}; -Node.prototype.getTransformBySid = function ( sid ) { -for ( var i = 0; i < this.transforms.length; i ++ ) { -if ( this.transforms[ i ].sid === sid ) return this.transforms[ i ]; -} -return null; -}; -Node.prototype.parse = function( element ) { -var url; -this.id = element.getAttribute('id'); -this.sid = element.getAttribute('sid'); -this.name = element.getAttribute('name'); -this.type = element.getAttribute('type'); -this.layer = element.getAttribute('layer'); -this.type = this.type === 'JOINT' ? this.type : 'NODE'; -this.nodes = []; -this.transforms = []; -this.geometries = []; -this.cameras = []; -this.lights = []; -this.controllers = []; -this.matrix = new THREE.Matrix4(); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'node': -this.nodes.push( ( new Node() ).parse( child ) ); -break; -case 'instance_camera': -this.cameras.push( ( new InstanceCamera() ).parse( child ) ); -break; -case 'instance_controller': -this.controllers.push( ( new InstanceController() ).parse( child ) ); -break; -case 'instance_geometry': -this.geometries.push( ( new InstanceGeometry() ).parse( child ) ); -break; -case 'instance_light': -this.lights.push( ( new InstanceLight() ).parse( child ) ); -break; -case 'instance_node': -url = child.getAttribute( 'url' ).replace( /^#/, '' ); -var iNode = getLibraryNode( url ); -if ( iNode ) { -this.nodes.push( ( new Node() ).parse( iNode )) ; -} -break; -case 'rotate': -case 'translate': -case 'scale': -case 'matrix': -case 'lookat': -case 'skew': -this.transforms.push( ( new Transform() ).parse( child ) ); -break; -case 'extra': -break; -default: -console.log( child.nodeName ); -break; -} -} -this.channels = getChannelsForNode( this ); -bakeAnimations( this ); -this.updateMatrix(); -return this; -}; -Node.prototype.updateMatrix = function () { -this.matrix.identity(); -for ( var i = 0; i < this.transforms.length; i ++ ) { -this.transforms[ i ].apply( this.matrix ); -} -}; -function Transform () { -this.sid = ""; -this.type = ""; -this.data = []; -this.obj = null; -} -Transform.prototype.parse = function ( element ) { -this.sid = element.getAttribute( 'sid' ); -this.type = element.nodeName; -this.data = _floats( element.textContent ); -this.convert(); -return this; -}; -Transform.prototype.convert = function () { -switch ( this.type ) { -case 'matrix': -this.obj = getConvertedMat4( this.data ); -break; -case 'rotate': -this.angle = THREE.Math.degToRad( this.data[3] ); -case 'translate': -fixCoords( this.data, -1 ); -this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] ); -break; -case 'scale': -fixCoords( this.data, 1 ); -this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] ); -break; -default: -console.log( 'Can not convert Transform of type ' + this.type ); -break; -} -}; -Transform.prototype.apply = function () { -var m1 = new THREE.Matrix4(); -return function ( matrix ) { -switch ( this.type ) { -case 'matrix': -matrix.multiply( this.obj ); -break; -case 'translate': -matrix.multiply( m1.makeTranslation( this.obj.x, this.obj.y, this.obj.z ) ); -break; -case 'rotate': -matrix.multiply( m1.makeRotationAxis( this.obj, this.angle ) ); -break; -case 'scale': -matrix.scale( this.obj ); -break; -} -}; -}(); -Transform.prototype.update = function ( data, member ) { -var members = [ 'X', 'Y', 'Z', 'ANGLE' ]; -switch ( this.type ) { -case 'matrix': -if ( ! member ) { -this.obj.copy( data ); -} else if ( member.length === 1 ) { -switch ( member[ 0 ] ) { -case 0: -this.obj.n11 = data[ 0 ]; -this.obj.n21 = data[ 1 ]; -this.obj.n31 = data[ 2 ]; -this.obj.n41 = data[ 3 ]; -break; -case 1: -this.obj.n12 = data[ 0 ]; -this.obj.n22 = data[ 1 ]; -this.obj.n32 = data[ 2 ]; -this.obj.n42 = data[ 3 ]; -break; -case 2: -this.obj.n13 = data[ 0 ]; -this.obj.n23 = data[ 1 ]; -this.obj.n33 = data[ 2 ]; -this.obj.n43 = data[ 3 ]; -break; -case 3: -this.obj.n14 = data[ 0 ]; -this.obj.n24 = data[ 1 ]; -this.obj.n34 = data[ 2 ]; -this.obj.n44 = data[ 3 ]; -break; -} -} else if ( member.length === 2 ) { -var propName = 'n' + ( member[ 0 ] + 1 ) + ( member[ 1 ] + 1 ); -this.obj[ propName ] = data; -} else { -console.log('Incorrect addressing of matrix in transform.'); -} -break; -case 'translate': -case 'scale': -if ( Object.prototype.toString.call( member ) === '[object Array]' ) { -member = members[ member[ 0 ] ]; -} -switch ( member ) { -case 'X': -this.obj.x = data; -break; -case 'Y': -this.obj.y = data; -break; -case 'Z': -this.obj.z = data; -break; -default: -this.obj.x = data[ 0 ]; -this.obj.y = data[ 1 ]; -this.obj.z = data[ 2 ]; -break; -} -break; -case 'rotate': -if ( Object.prototype.toString.call( member ) === '[object Array]' ) { -member = members[ member[ 0 ] ]; -} -switch ( member ) { -case 'X': -this.obj.x = data; -break; -case 'Y': -this.obj.y = data; -break; -case 'Z': -this.obj.z = data; -break; -case 'ANGLE': -this.angle = THREE.Math.degToRad( data ); -break; -default: -this.obj.x = data[ 0 ]; -this.obj.y = data[ 1 ]; -this.obj.z = data[ 2 ]; -this.angle = THREE.Math.degToRad( data[ 3 ] ); -break; -} -break; -} -}; -function InstanceController() { -this.url = ""; -this.skeleton = []; -this.instance_material = []; -} -InstanceController.prototype.parse = function ( element ) { -this.url = element.getAttribute('url').replace(/^#/, ''); -this.skeleton = []; -this.instance_material = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType !== 1 ) continue; -switch ( child.nodeName ) { -case 'skeleton': -this.skeleton.push( child.textContent.replace(/^#/, '') ); -break; -case 'bind_material': -var instances = child.querySelectorAll('instance_material'); -for ( var j = 0; j < instances.length; j ++ ) { -var instance = instances[j]; -this.instance_material.push( (new InstanceMaterial()).parse(instance) ); -} -break; -case 'extra': -break; -default: -break; -} -} -return this; -}; -function InstanceMaterial () { -this.symbol = ""; -this.target = ""; -} -InstanceMaterial.prototype.parse = function ( element ) { -this.symbol = element.getAttribute('symbol'); -this.target = element.getAttribute('target').replace(/^#/, ''); -return this; -}; -function InstanceGeometry() { -this.url = ""; -this.instance_material = []; -} -InstanceGeometry.prototype.parse = function ( element ) { -this.url = element.getAttribute('url').replace(/^#/, ''); -this.instance_material = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1 ) continue; -if ( child.nodeName === 'bind_material' ) { -var instances = child.querySelectorAll('instance_material'); -for ( var j = 0; j < instances.length; j ++ ) { -var instance = instances[j]; -this.instance_material.push( (new InstanceMaterial()).parse(instance) ); -} -break; -} -} -return this; -}; -function Geometry() { -this.id = ""; -this.mesh = null; -} -Geometry.prototype.parse = function ( element ) { -this.id = element.getAttribute('id'); -extractDoubleSided( this, element ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -switch ( child.nodeName ) { -case 'mesh': -this.mesh = (new Mesh(this)).parse(child); -break; -case 'extra': -break; -default: -break; -} -} -return this; -}; -function Mesh( geometry ) { -this.geometry = geometry.id; -this.primitives = []; -this.vertices = null; -this.geometry3js = null; -} -Mesh.prototype.parse = function ( element ) { -this.primitives = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'source': -_source( child ); -break; -case 'vertices': -this.vertices = ( new Vertices() ).parse( child ); -break; -case 'linestrips': -this.primitives.push( ( new LineStrips().parse( child ) ) ); -break; -case 'triangles': -this.primitives.push( ( new Triangles().parse( child ) ) ); -break; -case 'polygons': -this.primitives.push( ( new Polygons().parse( child ) ) ); -break; -case 'polylist': -this.primitives.push( ( new Polylist().parse( child ) ) ); -break; -default: -break; -} -} -this.geometry3js = new THREE.Geometry(); -if ( this.vertices === null ) { -return this; -} -var vertexData = sources[ this.vertices.input['POSITION'].source ].data; -for ( var i = 0; i < vertexData.length; i += 3 ) { -this.geometry3js.vertices.push( getConvertedVec3( vertexData, i ).clone() ); -} -for ( var i = 0; i < this.primitives.length; i ++ ) { -var primitive = this.primitives[ i ]; -primitive.setVertices( this.vertices ); -this.handlePrimitive( primitive, this.geometry3js ); -} -if ( this.geometry3js.calcNormals ) { -this.geometry3js.computeVertexNormals(); -delete this.geometry3js.calcNormals; -} -return this; -}; -Mesh.prototype.handlePrimitive = function ( primitive, geom ) { -if ( primitive instanceof LineStrips ) { -geom.isLineStrip = true; -return; -} -var j, k, pList = primitive.p, inputs = primitive.inputs; -var input, index, idx32; -var source, numParams; -var vcIndex = 0, vcount = 3, maxOffset = 0; -var texture_sets = []; -for ( j = 0; j < inputs.length; j ++ ) { -input = inputs[ j ]; -var offset = input.offset + 1; -maxOffset = (maxOffset < offset) ? offset : maxOffset; -switch ( input.semantic ) { -case 'TEXCOORD': -texture_sets.push( input.set ); -break; -} -} -for ( var pCount = 0; pCount < pList.length; ++ pCount ) { -var p = pList[ pCount ], i = 0; -while ( i < p.length ) { -var vs = []; -var ns = []; -var ts = null; -var cs = []; -if ( primitive.vcount ) { -vcount = primitive.vcount.length ? primitive.vcount[ vcIndex ++ ] : primitive.vcount; -} else { -vcount = p.length / maxOffset; -} -for ( j = 0; j < vcount; j ++ ) { -for ( k = 0; k < inputs.length; k ++ ) { -input = inputs[ k ]; -source = sources[ input.source ]; -index = p[ i + ( j * maxOffset ) + input.offset ]; -numParams = source.accessor.params.length; -idx32 = index * numParams; -switch ( input.semantic ) { -case 'VERTEX': -vs.push( index ); -break; -case 'NORMAL': -ns.push( getConvertedVec3( source.data, idx32 ) ); -break; -case 'TEXCOORD': -ts = ts || { }; -if ( ts[ input.set ] === undefined ) ts[ input.set ] = []; -ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], source.data[ idx32 + 1 ] ) ); -break; -case 'COLOR': -cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) ); -break; -default: -break; -} -} -} -if ( ns.length === 0 ) { -input = this.vertices.input.NORMAL; -if ( input ) { -source = sources[ input.source ]; -numParams = source.accessor.params.length; -for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { -ns.push( getConvertedVec3( source.data, vs[ ndx ] * numParams ) ); -} -} else { -geom.calcNormals = true; -} -} -if ( !ts ) { -ts = { }; -input = this.vertices.input.TEXCOORD; -if ( input ) { -texture_sets.push( input.set ); -source = sources[ input.source ]; -numParams = source.accessor.params.length; -for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { -idx32 = vs[ ndx ] * numParams; -if ( ts[ input.set ] === undefined ) ts[ input.set ] = [ ]; -ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], 1.0 - source.data[ idx32 + 1 ] ) ); -} -} -} -if ( cs.length === 0 ) { -input = this.vertices.input.COLOR; -if ( input ) { -source = sources[ input.source ]; -numParams = source.accessor.params.length; -for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { -idx32 = vs[ ndx ] * numParams; -cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) ); -} -} -} -var face = null, faces = [], uv, uvArr; -if ( vcount === 3 ) { -faces.push( new THREE.Face3( vs[0], vs[1], vs[2], ns, cs.length ? cs : new THREE.Color() ) ); -} else if ( vcount === 4 ) { -faces.push( new THREE.Face3( vs[0], vs[1], vs[3], ns.length ? [ ns[0].clone(), ns[1].clone(), ns[3].clone() ] : [], cs.length ? [ cs[0], cs[1], cs[3] ] : new THREE.Color() ) ); -faces.push( new THREE.Face3( vs[1], vs[2], vs[3], ns.length ? [ ns[1].clone(), ns[2].clone(), ns[3].clone() ] : [], cs.length ? [ cs[1], cs[2], cs[3] ] : new THREE.Color() ) ); -} else if ( vcount > 4 && options.subdivideFaces ) { -var clr = cs.length ? cs : new THREE.Color(), -vec1, vec2, vec3, v1, v2, norm; -for ( k = 1; k < vcount - 1; ) { -faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], ns.length ? [ ns[0].clone(), ns[k ++].clone(), ns[k].clone() ] : [], clr ) ); -} -} -if ( faces.length ) { -for ( var ndx = 0, len = faces.length; ndx < len; ndx ++ ) { -face = faces[ndx]; -face.daeMaterial = primitive.material; -geom.faces.push( face ); -for ( k = 0; k < texture_sets.length; k ++ ) { -uv = ts[ texture_sets[k] ]; -if ( vcount > 4 ) { -uvArr = [ uv[0], uv[ndx + 1], uv[ndx + 2] ]; -} else if ( vcount === 4 ) { -if ( ndx === 0 ) { -uvArr = [ uv[0], uv[1], uv[3] ]; -} else { -uvArr = [ uv[1].clone(), uv[2], uv[3].clone() ]; -} -} else { -uvArr = [ uv[0], uv[1], uv[2] ]; -} -if ( geom.faceVertexUvs[k] === undefined ) { -geom.faceVertexUvs[k] = []; -} -geom.faceVertexUvs[k].push( uvArr ); -} -} -} else { -console.log( 'dropped face with vcount ' + vcount + ' for geometry with id: ' + geom.id ); -} -i += maxOffset * vcount; -} -} -}; -function Polygons () { -this.material = ""; -this.count = 0; -this.inputs = []; -this.vcount = null; -this.p = []; -this.geometry = new THREE.Geometry(); -} -Polygons.prototype.setVertices = function ( vertices ) { -for ( var i = 0; i < this.inputs.length; i ++ ) { -if ( this.inputs[ i ].source === vertices.id ) { -this.inputs[ i ].source = vertices.input[ 'POSITION' ].source; -} -} -}; -Polygons.prototype.parse = function ( element ) { -this.material = element.getAttribute( 'material' ); -this.count = _attr_as_int( element, 'count', 0 ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'input': -this.inputs.push( ( new Input() ).parse( element.childNodes[ i ] ) ); -break; -case 'vcount': -this.vcount = _ints( child.textContent ); -break; -case 'p': -this.p.push( _ints( child.textContent ) ); -break; -case 'ph': -console.warn( 'polygon holes not yet supported!' ); -break; -default: -break; -} -} -return this; -}; -function Polylist () { -Polygons.call( this ); -this.vcount = []; -} -Polylist.prototype = Object.create( Polygons.prototype ); -Polylist.prototype.constructor = Polylist; -function LineStrips() { -Polygons.call( this ); -this.vcount = 1; -} -LineStrips.prototype = Object.create( Polygons.prototype ); -LineStrips.prototype.constructor = LineStrips; -function Triangles () { -Polygons.call( this ); -this.vcount = 3; -} -Triangles.prototype = Object.create( Polygons.prototype ); -Triangles.prototype.constructor = Triangles; -function Accessor() { -this.source = ""; -this.count = 0; -this.stride = 0; -this.params = []; -} -Accessor.prototype.parse = function ( element ) { -this.params = []; -this.source = element.getAttribute( 'source' ); -this.count = _attr_as_int( element, 'count', 0 ); -this.stride = _attr_as_int( element, 'stride', 0 ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeName === 'param' ) { -var param = {}; -param[ 'name' ] = child.getAttribute( 'name' ); -param[ 'type' ] = child.getAttribute( 'type' ); -this.params.push( param ); -} -} -return this; -}; -function Vertices() { -this.input = {}; -} -Vertices.prototype.parse = function ( element ) { -this.id = element.getAttribute('id'); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -if ( element.childNodes[i].nodeName === 'input' ) { -var input = ( new Input() ).parse( element.childNodes[ i ] ); -this.input[ input.semantic ] = input; -} -} -return this; -}; -function Input () { -this.semantic = ""; -this.offset = 0; -this.source = ""; -this.set = 0; -} -Input.prototype.parse = function ( element ) { -this.semantic = element.getAttribute('semantic'); -this.source = element.getAttribute('source').replace(/^#/, ''); -this.set = _attr_as_int(element, 'set', -1); -this.offset = _attr_as_int(element, 'offset', 0); -if ( this.semantic === 'TEXCOORD' && this.set < 0 ) { -this.set = 0; -} -return this; -}; -function Source ( id ) { -this.id = id; -this.type = null; -} -Source.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -switch ( child.nodeName ) { -case 'bool_array': -this.data = _bools( child.textContent ); -this.type = child.nodeName; -break; -case 'float_array': -this.data = _floats( child.textContent ); -this.type = child.nodeName; -break; -case 'int_array': -this.data = _ints( child.textContent ); -this.type = child.nodeName; -break; -case 'IDREF_array': -case 'Name_array': -this.data = _strings( child.textContent ); -this.type = child.nodeName; -break; -case 'technique_common': -for ( var j = 0; j < child.childNodes.length; j ++ ) { -if ( child.childNodes[ j ].nodeName === 'accessor' ) { -this.accessor = ( new Accessor() ).parse( child.childNodes[ j ] ); -break; -} -} -break; -default: -break; -} -} -return this; -}; -Source.prototype.read = function () { -var result = []; -var param = this.accessor.params[ 0 ]; -switch ( param.type ) { -case 'IDREF': -case 'Name': case 'name': -case 'float': -return this.data; -case 'float4x4': -for ( var j = 0; j < this.data.length; j += 16 ) { -var s = this.data.slice( j, j + 16 ); -var m = getConvertedMat4( s ); -result.push( m ); -} -break; -default: -console.log( 'ColladaLoader: Source: Read dont know how to read ' + param.type + '.' ); -break; -} -return result; -}; -function Material () { -this.id = ""; -this.name = ""; -this.instance_effect = null; -} -Material.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -if ( element.childNodes[ i ].nodeName === 'instance_effect' ) { -this.instance_effect = ( new InstanceEffect() ).parse( element.childNodes[ i ] ); -break; -} -} -return this; -}; -function ColorOrTexture () { -this.color = new THREE.Color(); -this.color.setRGB( Math.random(), Math.random(), Math.random() ); -this.color.a = 1.0; -this.texture = null; -this.texcoord = null; -this.texOpts = null; -} -ColorOrTexture.prototype.isColor = function () { -return ( this.texture === null ); -}; -ColorOrTexture.prototype.isTexture = function () { -return ( this.texture != null ); -}; -ColorOrTexture.prototype.parse = function ( element ) { -if (element.nodeName === 'transparent') { -this.opaque = element.getAttribute('opaque'); -} -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'color': -var rgba = _floats( child.textContent ); -this.color = new THREE.Color(); -this.color.setRGB( rgba[0], rgba[1], rgba[2] ); -this.color.a = rgba[3]; -break; -case 'texture': -this.texture = child.getAttribute('texture'); -this.texcoord = child.getAttribute('texcoord'); -this.texOpts = { -offsetU: 0, -offsetV: 0, -repeatU: 1, -repeatV: 1, -wrapU: 1, -wrapV: 1 -}; -this.parseTexture( child ); -break; -default: -break; -} -} -return this; -}; -ColorOrTexture.prototype.parseTexture = function ( element ) { -if ( ! element.childNodes ) return this; -if ( element.childNodes[1] && element.childNodes[1].nodeName === 'extra' ) { -element = element.childNodes[1]; -if ( element.childNodes[1] && element.childNodes[1].nodeName === 'technique' ) { -element = element.childNodes[1]; -} -} -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'offsetU': -case 'offsetV': -case 'repeatU': -case 'repeatV': -this.texOpts[ child.nodeName ] = parseFloat( child.textContent ); -break; -case 'wrapU': -case 'wrapV': -if ( child.textContent.toUpperCase() === 'TRUE' ) { -this.texOpts[ child.nodeName ] = 1; -} else { -this.texOpts[ child.nodeName ] = parseInt( child.textContent ); -} -break; -default: -this.texOpts[ child.nodeName ] = child.textContent; -break; -} -} -return this; -}; -function Shader ( type, effect ) { -this.type = type; -this.effect = effect; -this.material = null; -} -Shader.prototype.parse = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'emission': -case 'diffuse': -case 'specular': -case 'transparent': -this[ child.nodeName ] = ( new ColorOrTexture() ).parse( child ); -break; -case 'bump': -var bumpType = child.getAttribute( 'bumptype' ); -if ( bumpType ) { -if ( bumpType.toLowerCase() === "heightfield" ) { -this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); -} else if ( bumpType.toLowerCase() === "normalmap" ) { -this[ 'normal' ] = ( new ColorOrTexture() ).parse( child ); -} else { -console.error( "Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType + ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'" ); -this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); -} -} else { -console.warn( "Shader.prototype.parse: Attribute 'bumptype' missing from bump node - defaulting to 'HEIGHTFIELD'" ); -this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); -} -break; -case 'shininess': -case 'reflectivity': -case 'index_of_refraction': -case 'transparency': -var f = child.querySelectorAll('float'); -if ( f.length > 0 ) -this[ child.nodeName ] = parseFloat( f[ 0 ].textContent ); -break; -default: -break; -} -} -this.create(); -return this; -}; -Shader.prototype.create = function() { -var props = {}; -var transparent = false; -if (this['transparency'] !== undefined && this['transparent'] !== undefined) { -var transparentColor = this['transparent']; -var transparencyLevel = (this.transparent.color.r + this.transparent.color.g + this.transparent.color.b) / 3 * this.transparency; -if (transparencyLevel > 0) { -transparent = true; -props[ 'transparent' ] = true; -props[ 'opacity' ] = 1 - transparencyLevel; -} -} -var keys = { -'diffuse':'map', -'ambient':'lightMap', -'specular':'specularMap', -'emission':'emissionMap', -'bump':'bumpMap', -'normal':'normalMap' -}; -for ( var prop in this ) { -switch ( prop ) { -case 'ambient': -case 'emission': -case 'diffuse': -case 'specular': -case 'bump': -case 'normal': -var cot = this[ prop ]; -if ( cot instanceof ColorOrTexture ) { -if ( cot.isTexture() ) { -var samplerId = cot.texture; -var sampler = this.effect.sampler[samplerId]; -if ( sampler !== undefined && sampler.source !== undefined ) { -var surface = this.effect.surface[sampler.source]; -if ( surface !== undefined ) { -var image = images[ surface.init_from ]; -if ( image ) { -var url = baseUrl + image.init_from; -var texture; -var loader = THREE.Loader.Handlers.get( url ); -if ( loader !== null ) { -texture = loader.load( url ); -} else { -texture = new THREE.Texture(); -loadTextureImage( texture, url ); -} -if ( sampler.wrap_s === "MIRROR" ) { -texture.wrapS = THREE.MirroredRepeatWrapping; -} else if ( sampler.wrap_s === "WRAP" || cot.texOpts.wrapU ) { -texture.wrapS = THREE.RepeatWrapping; -} else { -texture.wrapS = THREE.ClampToEdgeWrapping; -} -if ( sampler.wrap_t === "MIRROR" ) { -texture.wrapT = THREE.MirroredRepeatWrapping; -} else if ( sampler.wrap_t === "WRAP" || cot.texOpts.wrapV ) { -texture.wrapT = THREE.RepeatWrapping; -} else { -texture.wrapT = THREE.ClampToEdgeWrapping; -} -texture.offset.x = cot.texOpts.offsetU; -texture.offset.y = cot.texOpts.offsetV; -texture.repeat.x = cot.texOpts.repeatU; -texture.repeat.y = cot.texOpts.repeatV; -props[keys[prop]] = texture; -if (prop === 'emission') props['emissive'] = 0xffffff; -} -} -} -} else if ( prop === 'diffuse' || !transparent ) { -if ( prop === 'emission' ) { -props[ 'emissive' ] = cot.color.getHex(); -} else { -props[ prop ] = cot.color.getHex(); -} -} -} -break; -case 'shininess': -props[ prop ] = this[ prop ]; -break; -case 'reflectivity': -props[ prop ] = this[ prop ]; -if ( props[ prop ] > 0.0 ) props['envMap'] = options.defaultEnvMap; -props['combine'] = THREE.MixOperation; //mix regular shading with reflective component -break; -case 'index_of_refraction': -props[ 'refractionRatio' ] = this[ prop ]; //TODO: "index_of_refraction" becomes "refractionRatio" in shader, but I'm not sure if the two are actually comparable -if ( this[ prop ] !== 1.0 ) props['envMap'] = options.defaultEnvMap; -break; -case 'transparency': -break; -default: -break; -} -} -props[ 'shading' ] = preferredShading; -props[ 'side' ] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide; -if ( props.diffuse !== undefined ) { -props.color = props.diffuse; -delete props.diffuse; -} -switch ( this.type ) { -case 'constant': -if (props.emissive != undefined) props.color = props.emissive; -this.material = new THREE.MeshBasicMaterial( props ); -break; -case 'phong': -case 'blinn': -this.material = new THREE.MeshPhongMaterial( props ); -break; -case 'lambert': -default: -this.material = new THREE.MeshLambertMaterial( props ); -break; -} -return this.material; -}; -function Surface ( effect ) { -this.effect = effect; -this.init_from = null; -this.format = null; -} -Surface.prototype.parse = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'init_from': -this.init_from = child.textContent; -break; -case 'format': -this.format = child.textContent; -break; -default: -console.log( "unhandled Surface prop: " + child.nodeName ); -break; -} -} -return this; -}; -function Sampler2D ( effect ) { -this.effect = effect; -this.source = null; -this.wrap_s = null; -this.wrap_t = null; -this.minfilter = null; -this.magfilter = null; -this.mipfilter = null; -} -Sampler2D.prototype.parse = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'source': -this.source = child.textContent; -break; -case 'minfilter': -this.minfilter = child.textContent; -break; -case 'magfilter': -this.magfilter = child.textContent; -break; -case 'mipfilter': -this.mipfilter = child.textContent; -break; -case 'wrap_s': -this.wrap_s = child.textContent; -break; -case 'wrap_t': -this.wrap_t = child.textContent; -break; -default: -console.log( "unhandled Sampler2D prop: " + child.nodeName ); -break; -} -} -return this; -}; -function Effect () { -this.id = ""; -this.name = ""; -this.shader = null; -this.surface = {}; -this.sampler = {}; -} -Effect.prototype.create = function () { -if ( this.shader === null ) { -return null; -} -}; -Effect.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -extractDoubleSided( this, element ); -this.shader = null; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'profile_COMMON': -this.parseTechnique( this.parseProfileCOMMON( child ) ); -break; -default: -break; -} -} -return this; -}; -Effect.prototype.parseNewparam = function ( element ) { -var sid = element.getAttribute( 'sid' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'surface': -this.surface[sid] = ( new Surface( this ) ).parse( child ); -break; -case 'sampler2D': -this.sampler[sid] = ( new Sampler2D( this ) ).parse( child ); -break; -case 'extra': -break; -default: -console.log( child.nodeName ); -break; -} -} -}; -Effect.prototype.parseProfileCOMMON = function ( element ) { -var technique; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'profile_COMMON': -this.parseProfileCOMMON( child ); -break; -case 'technique': -technique = child; -break; -case 'newparam': -this.parseNewparam( child ); -break; -case 'image': -var _image = ( new _Image() ).parse( child ); -images[ _image.id ] = _image; -break; -case 'extra': -break; -default: -console.log( child.nodeName ); -break; -} -} -return technique; -}; -Effect.prototype.parseTechnique = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'constant': -case 'lambert': -case 'blinn': -case 'phong': -this.shader = ( new Shader( child.nodeName, this ) ).parse( child ); -break; -case 'extra': -this.parseExtra(child); -break; -default: -break; -} -} -}; -Effect.prototype.parseExtra = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'technique': -this.parseExtraTechnique( child ); -break; -default: -break; -} -} -}; -Effect.prototype.parseExtraTechnique = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[i]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'bump': -this.shader.parse( element ); -break; -default: -break; -} -} -}; -function InstanceEffect () { -this.url = ""; -} -InstanceEffect.prototype.parse = function ( element ) { -this.url = element.getAttribute( 'url' ).replace( /^#/, '' ); -return this; -}; -function Animation() { -this.id = ""; -this.name = ""; -this.source = {}; -this.sampler = []; -this.channel = []; -} -Animation.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -this.source = {}; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'animation': -var anim = ( new Animation() ).parse( child ); -for ( var src in anim.source ) { -this.source[ src ] = anim.source[ src ]; -} -for ( var j = 0; j < anim.channel.length; j ++ ) { -this.channel.push( anim.channel[ j ] ); -this.sampler.push( anim.sampler[ j ] ); -} -break; -case 'source': -var src = ( new Source() ).parse( child ); -this.source[ src.id ] = src; -break; -case 'sampler': -this.sampler.push( ( new Sampler( this ) ).parse( child ) ); -break; -case 'channel': -this.channel.push( ( new Channel( this ) ).parse( child ) ); -break; -default: -break; -} -} -return this; -}; -function Channel( animation ) { -this.animation = animation; -this.source = ""; -this.target = ""; -this.fullSid = null; -this.sid = null; -this.dotSyntax = null; -this.arrSyntax = null; -this.arrIndices = null; -this.member = null; -} -Channel.prototype.parse = function ( element ) { -this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); -this.target = element.getAttribute( 'target' ); -var parts = this.target.split( '/' ); -var id = parts.shift(); -var sid = parts.shift(); -var dotSyntax = ( sid.indexOf(".") >= 0 ); -var arrSyntax = ( sid.indexOf("(") >= 0 ); -if ( dotSyntax ) { -parts = sid.split("."); -this.sid = parts.shift(); -this.member = parts.shift(); -} else if ( arrSyntax ) { -var arrIndices = sid.split("("); -this.sid = arrIndices.shift(); -for (var j = 0; j < arrIndices.length; j ++ ) { -arrIndices[j] = parseInt( arrIndices[j].replace(/\)/, '') ); -} -this.arrIndices = arrIndices; -} else { -this.sid = sid; -} -this.fullSid = sid; -this.dotSyntax = dotSyntax; -this.arrSyntax = arrSyntax; -return this; -}; -function Sampler ( animation ) { -this.id = ""; -this.animation = animation; -this.inputs = []; -this.input = null; -this.output = null; -this.strideOut = null; -this.interpolation = null; -this.startTime = null; -this.endTime = null; -this.duration = 0; -} -Sampler.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.inputs = []; -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'input': -this.inputs.push( (new Input()).parse( child ) ); -break; -default: -break; -} -} -return this; -}; -Sampler.prototype.create = function () { -for ( var i = 0; i < this.inputs.length; i ++ ) { -var input = this.inputs[ i ]; -var source = this.animation.source[ input.source ]; -switch ( input.semantic ) { -case 'INPUT': -this.input = source.read(); -break; -case 'OUTPUT': -this.output = source.read(); -this.strideOut = source.accessor.stride; -break; -case 'INTERPOLATION': -this.interpolation = source.read(); -break; -case 'IN_TANGENT': -break; -case 'OUT_TANGENT': -break; -default: -console.log(input.semantic); -break; -} -} -this.startTime = 0; -this.endTime = 0; -this.duration = 0; -if ( this.input.length ) { -this.startTime = 100000000; -this.endTime = -100000000; -for ( var i = 0; i < this.input.length; i ++ ) { -this.startTime = Math.min( this.startTime, this.input[ i ] ); -this.endTime = Math.max( this.endTime, this.input[ i ] ); -} -this.duration = this.endTime - this.startTime; -} -}; -Sampler.prototype.getData = function ( type, ndx, member ) { -var data; -if ( type === 'matrix' && this.strideOut === 16 ) { -data = this.output[ ndx ]; -} else if ( this.strideOut > 1 ) { -data = []; -ndx *= this.strideOut; -for ( var i = 0; i < this.strideOut; ++ i ) { -data[ i ] = this.output[ ndx + i ]; -} -if ( this.strideOut === 3 ) { -switch ( type ) { -case 'rotate': -case 'translate': -fixCoords( data, -1 ); -break; -case 'scale': -fixCoords( data, 1 ); -break; -} -} else if ( this.strideOut === 4 && type === 'matrix' ) { -fixCoords( data, -1 ); -} -} else { -data = this.output[ ndx ]; -if ( member && type === 'translate' ) { -data = getConvertedTranslation( member, data ); -} -} -return data; -}; -function Key ( time ) { -this.targets = []; -this.time = time; -} -Key.prototype.addTarget = function ( fullSid, transform, member, data ) { -this.targets.push( { -sid: fullSid, -member: member, -transform: transform, -data: data -} ); -}; -Key.prototype.apply = function ( opt_sid ) { -for ( var i = 0; i < this.targets.length; ++ i ) { -var target = this.targets[ i ]; -if ( !opt_sid || target.sid === opt_sid ) { -target.transform.update( target.data, target.member ); -} -} -}; -Key.prototype.getTarget = function ( fullSid ) { -for ( var i = 0; i < this.targets.length; ++ i ) { -if ( this.targets[ i ].sid === fullSid ) { -return this.targets[ i ]; -} -} -return null; -}; -Key.prototype.hasTarget = function ( fullSid ) { -for ( var i = 0; i < this.targets.length; ++ i ) { -if ( this.targets[ i ].sid === fullSid ) { -return true; -} -} -return false; -}; -Key.prototype.interpolate = function ( nextKey, time ) { -for ( var i = 0, l = this.targets.length; i < l; i ++ ) { -var target = this.targets[ i ], -nextTarget = nextKey.getTarget( target.sid ), -data; -if ( target.transform.type !== 'matrix' && nextTarget ) { -var scale = ( time - this.time ) / ( nextKey.time - this.time ), -nextData = nextTarget.data, -prevData = target.data; -if ( scale < 0 ) scale = 0; -if ( scale > 1 ) scale = 1; -if ( prevData.length ) { -data = []; -for ( var j = 0; j < prevData.length; ++ j ) { -data[ j ] = prevData[ j ] + ( nextData[ j ] - prevData[ j ] ) * scale; -} -} else { -data = prevData + ( nextData - prevData ) * scale; -} -} else { -data = target.data; -} -target.transform.update( data, target.member ); -} -}; -function Camera() { -this.id = ""; -this.name = ""; -this.technique = ""; -} -Camera.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'optics': -this.parseOptics( child ); -break; -default: -break; -} -} -return this; -}; -Camera.prototype.parseOptics = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -if ( element.childNodes[ i ].nodeName === 'technique_common' ) { -var technique = element.childNodes[ i ]; -for ( var j = 0; j < technique.childNodes.length; j ++ ) { -this.technique = technique.childNodes[ j ].nodeName; -if ( this.technique === 'perspective' ) { -var perspective = technique.childNodes[ j ]; -for ( var k = 0; k < perspective.childNodes.length; k ++ ) { -var param = perspective.childNodes[ k ]; -switch ( param.nodeName ) { -case 'yfov': -this.yfov = param.textContent; -break; -case 'xfov': -this.xfov = param.textContent; -break; -case 'znear': -this.znear = param.textContent; -break; -case 'zfar': -this.zfar = param.textContent; -break; -case 'aspect_ratio': -this.aspect_ratio = param.textContent; -break; -} -} -} else if ( this.technique === 'orthographic' ) { -var orthographic = technique.childNodes[ j ]; -for ( var k = 0; k < orthographic.childNodes.length; k ++ ) { -var param = orthographic.childNodes[ k ]; -switch ( param.nodeName ) { -case 'xmag': -this.xmag = param.textContent; -break; -case 'ymag': -this.ymag = param.textContent; -break; -case 'znear': -this.znear = param.textContent; -break; -case 'zfar': -this.zfar = param.textContent; -break; -case 'aspect_ratio': -this.aspect_ratio = param.textContent; -break; -} -} -} -} -} -} -return this; -}; -function InstanceCamera() { -this.url = ""; -} -InstanceCamera.prototype.parse = function ( element ) { -this.url = element.getAttribute('url').replace(/^#/, ''); -return this; -}; -function Light() { -this.id = ""; -this.name = ""; -this.technique = ""; -} -Light.prototype.parse = function ( element ) { -this.id = element.getAttribute( 'id' ); -this.name = element.getAttribute( 'name' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'technique_common': -this.parseCommon( child ); -break; -case 'technique': -this.parseTechnique( child ); -break; -default: -break; -} -} -return this; -}; -Light.prototype.parseCommon = function ( element ) { -for ( var i = 0; i < element.childNodes.length; i ++ ) { -switch ( element.childNodes[ i ].nodeName ) { -case 'directional': -case 'point': -case 'spot': -case 'ambient': -this.technique = element.childNodes[ i ].nodeName; -var light = element.childNodes[ i ]; -for ( var j = 0; j < light.childNodes.length; j ++ ) { -var child = light.childNodes[j]; -switch ( child.nodeName ) { -case 'color': -var rgba = _floats( child.textContent ); -this.color = new THREE.Color(0); -this.color.setRGB( rgba[0], rgba[1], rgba[2] ); -this.color.a = rgba[3]; -break; -case 'falloff_angle': -this.falloff_angle = parseFloat( child.textContent ); -break; -case 'quadratic_attenuation': -var f = parseFloat( child.textContent ); -this.distance = f ? Math.sqrt( 1 / f ) : 0; -} -} -} -} -return this; -}; -Light.prototype.parseTechnique = function ( element ) { -this.profile = element.getAttribute( 'profile' ); -for ( var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -switch ( child.nodeName ) { -case 'intensity': -this.intensity = parseFloat(child.textContent); -break; -} -} -return this; -}; -function InstanceLight() { -this.url = ""; -} -InstanceLight.prototype.parse = function ( element ) { -this.url = element.getAttribute('url').replace(/^#/, ''); -return this; -}; -function KinematicsModel( ) { -this.id = ''; -this.name = ''; -this.joints = []; -this.links = []; -} -KinematicsModel.prototype.parse = function( element ) { -this.id = element.getAttribute('id'); -this.name = element.getAttribute('name'); -this.joints = []; -this.links = []; -for (var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'technique_common': -this.parseCommon(child); -break; -default: -break; -} -} -return this; -}; -KinematicsModel.prototype.parseCommon = function( element ) { -for (var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( element.childNodes[ i ].nodeName ) { -case 'joint': -this.joints.push( (new Joint()).parse(child) ); -break; -case 'link': -this.links.push( (new Link()).parse(child) ); -break; -default: -break; -} -} -return this; -}; -function Joint( ) { -this.sid = ''; -this.name = ''; -this.axis = new THREE.Vector3(); -this.limits = { -min: 0, -max: 0 -}; -this.type = ''; -this.static = false; -this.zeroPosition = 0.0; -this.middlePosition = 0.0; -} -Joint.prototype.parse = function( element ) { -this.sid = element.getAttribute('sid'); -this.name = element.getAttribute('name'); -this.axis = new THREE.Vector3(); -this.limits = { -min: 0, -max: 0 -}; -this.type = ''; -this.static = false; -this.zeroPosition = 0.0; -this.middlePosition = 0.0; -var axisElement = element.querySelector('axis'); -var _axis = _floats(axisElement.textContent); -this.axis = getConvertedVec3(_axis, 0); -var min = element.querySelector('limits min') ? parseFloat(element.querySelector('limits min').textContent) : -360; -var max = element.querySelector('limits max') ? parseFloat(element.querySelector('limits max').textContent) : 360; -this.limits = { -min: min, -max: max -}; -var jointTypes = [ 'prismatic', 'revolute' ]; -for (var i = 0; i < jointTypes.length; i ++ ) { -var type = jointTypes[ i ]; -var jointElement = element.querySelector(type); -if ( jointElement ) { -this.type = type; -} -} -if ( this.limits.min >= this.limits.max ) { -this.static = true; -} -this.middlePosition = (this.limits.min + this.limits.max) / 2.0; -return this; -}; -function Link( ) { -this.sid = ''; -this.name = ''; -this.transforms = []; -this.attachments = []; -} -Link.prototype.parse = function( element ) { -this.sid = element.getAttribute('sid'); -this.name = element.getAttribute('name'); -this.transforms = []; -this.attachments = []; -for (var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'attachment_full': -this.attachments.push( (new Attachment()).parse(child) ); -break; -case 'rotate': -case 'translate': -case 'matrix': -this.transforms.push( (new Transform()).parse(child) ); -break; -default: -break; -} -} -return this; -}; -function Attachment( ) { -this.joint = ''; -this.transforms = []; -this.links = []; -} -Attachment.prototype.parse = function( element ) { -this.joint = element.getAttribute('joint').split('/').pop(); -this.links = []; -for (var i = 0; i < element.childNodes.length; i ++ ) { -var child = element.childNodes[ i ]; -if ( child.nodeType != 1 ) continue; -switch ( child.nodeName ) { -case 'link': -this.links.push( (new Link()).parse(child) ); -break; -case 'rotate': -case 'translate': -case 'matrix': -this.transforms.push( (new Transform()).parse(child) ); -break; -default: -break; -} -} -return this; -}; -function _source( element ) { -var id = element.getAttribute( 'id' ); -if ( sources[ id ] != undefined ) { -return sources[ id ]; -} -sources[ id ] = ( new Source(id )).parse( element ); -return sources[ id ]; -} -function _nsResolver( nsPrefix ) { -if ( nsPrefix === "dae" ) { -return "http://www.collada.org/2005/11/COLLADASchema"; -} -return null; -} -function _bools( str ) { -var raw = _strings( str ); -var data = []; -for ( var i = 0, l = raw.length; i < l; i ++ ) { -data.push( (raw[i] === 'true' || raw[i] === '1') ? true : false ); -} -return data; -} -function _floats( str ) { -var raw = _strings(str); -var data = []; -for ( var i = 0, l = raw.length; i < l; i ++ ) { -data.push( parseFloat( raw[ i ] ) ); -} -return data; -} -function _ints( str ) { -var raw = _strings( str ); -var data = []; -for ( var i = 0, l = raw.length; i < l; i ++ ) { -data.push( parseInt( raw[ i ], 10 ) ); -} -return data; -} -function _strings( str ) { -return ( str.length > 0 ) ? _trimString( str ).split( /\s+/ ) : []; -} -function _trimString( str ) { -return str.replace( /^\s+/, "" ).replace( /\s+$/, "" ); -} -function _attr_as_float( element, name, defaultValue ) { -if ( element.hasAttribute( name ) ) { -return parseFloat( element.getAttribute( name ) ); -} else { -return defaultValue; -} -} -function _attr_as_int( element, name, defaultValue ) { -if ( element.hasAttribute( name ) ) { -return parseInt( element.getAttribute( name ), 10) ; -} else { -return defaultValue; -} -} -function _attr_as_string( element, name, defaultValue ) { -if ( element.hasAttribute( name ) ) { -return element.getAttribute( name ); -} else { -return defaultValue; -} -} -function _format_float( f, num ) { -if ( f === undefined ) { -var s = '0.'; -while ( s.length < num + 2 ) { -s += '0'; -} -return s; -} -num = num || 2; -var parts = f.toString().split( '.' ); -parts[ 1 ] = parts.length > 1 ? parts[ 1 ].substr( 0, num ) : "0"; -while ( parts[ 1 ].length < num ) { -parts[ 1 ] += '0'; -} -return parts.join( '.' ); -} -function loadTextureImage ( texture, url ) { -var loader = new THREE.ImageLoader(); -loader.load( url, function ( image ) { -texture.image = image; -texture.needsUpdate = true; -} ); -} -function extractDoubleSided( obj, element ) { -obj.doubleSided = false; -var node = element.querySelectorAll('extra double_sided')[0]; -if ( node ) { -if ( node && parseInt( node.textContent, 10 ) === 1 ) { -obj.doubleSided = true; -} -} -} -function setUpConversion() { -if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { -upConversion = null; -} else { -switch ( colladaUp ) { -case 'X': -upConversion = options.upAxis === 'Y' ? 'XtoY' : 'XtoZ'; -break; -case 'Y': -upConversion = options.upAxis === 'X' ? 'YtoX' : 'YtoZ'; -break; -case 'Z': -upConversion = options.upAxis === 'X' ? 'ZtoX' : 'ZtoY'; -break; -} -} -} -function fixCoords( data, sign ) { -if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { -return; -} -switch ( upConversion ) { -case 'XtoY': -var tmp = data[ 0 ]; -data[ 0 ] = sign * data[ 1 ]; -data[ 1 ] = tmp; -break; -case 'XtoZ': -var tmp = data[ 2 ]; -data[ 2 ] = data[ 1 ]; -data[ 1 ] = data[ 0 ]; -data[ 0 ] = tmp; -break; -case 'YtoX': -var tmp = data[ 0 ]; -data[ 0 ] = data[ 1 ]; -data[ 1 ] = sign * tmp; -break; -case 'YtoZ': -var tmp = data[ 1 ]; -data[ 1 ] = sign * data[ 2 ]; -data[ 2 ] = tmp; -break; -case 'ZtoX': -var tmp = data[ 0 ]; -data[ 0 ] = data[ 1 ]; -data[ 1 ] = data[ 2 ]; -data[ 2 ] = tmp; -break; -case 'ZtoY': -var tmp = data[ 1 ]; -data[ 1 ] = data[ 2 ]; -data[ 2 ] = sign * tmp; -break; -} -} -function getConvertedTranslation( axis, data ) { -if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { -return data; -} -switch ( axis ) { -case 'X': -data = upConversion === 'XtoY' ? data * -1 : data; -break; -case 'Y': -data = upConversion === 'YtoZ' || upConversion === 'YtoX' ? data * -1 : data; -break; -case 'Z': -data = upConversion === 'ZtoY' ? data * -1 : data ; -break; -default: -break; -} -return data; -} -function getConvertedVec3( data, offset ) { -var arr = [ data[ offset ], data[ offset + 1 ], data[ offset + 2 ] ]; -fixCoords( arr, -1 ); -return new THREE.Vector3( arr[ 0 ], arr[ 1 ], arr[ 2 ] ); -} -function getConvertedMat4( data ) { -if ( options.convertUpAxis ) { -var arr = [ data[ 0 ], data[ 4 ], data[ 8 ] ]; -fixCoords( arr, -1 ); -data[ 0 ] = arr[ 0 ]; -data[ 4 ] = arr[ 1 ]; -data[ 8 ] = arr[ 2 ]; -arr = [ data[ 1 ], data[ 5 ], data[ 9 ] ]; -fixCoords( arr, -1 ); -data[ 1 ] = arr[ 0 ]; -data[ 5 ] = arr[ 1 ]; -data[ 9 ] = arr[ 2 ]; -arr = [ data[ 2 ], data[ 6 ], data[ 10 ] ]; -fixCoords( arr, -1 ); -data[ 2 ] = arr[ 0 ]; -data[ 6 ] = arr[ 1 ]; -data[ 10 ] = arr[ 2 ]; -arr = [ data[ 0 ], data[ 1 ], data[ 2 ] ]; -fixCoords( arr, -1 ); -data[ 0 ] = arr[ 0 ]; -data[ 1 ] = arr[ 1 ]; -data[ 2 ] = arr[ 2 ]; -arr = [ data[ 4 ], data[ 5 ], data[ 6 ] ]; -fixCoords( arr, -1 ); -data[ 4 ] = arr[ 0 ]; -data[ 5 ] = arr[ 1 ]; -data[ 6 ] = arr[ 2 ]; -arr = [ data[ 8 ], data[ 9 ], data[ 10 ] ]; -fixCoords( arr, -1 ); -data[ 8 ] = arr[ 0 ]; -data[ 9 ] = arr[ 1 ]; -data[ 10 ] = arr[ 2 ]; -arr = [ data[ 3 ], data[ 7 ], data[ 11 ] ]; -fixCoords( arr, -1 ); -data[ 3 ] = arr[ 0 ]; -data[ 7 ] = arr[ 1 ]; -data[ 11 ] = arr[ 2 ]; -} -return new THREE.Matrix4().set( -data[0], data[1], data[2], data[3], -data[4], data[5], data[6], data[7], -data[8], data[9], data[10], data[11], -data[12], data[13], data[14], data[15] -); -} -function getConvertedIndex( index ) { -if ( index > -1 && index < 3 ) { -var members = [ 'X', 'Y', 'Z' ], -indices = { X: 0, Y: 1, Z: 2 }; -index = getConvertedMember( members[ index ] ); -index = indices[ index ]; -} -return index; -} -function getConvertedMember( member ) { -if ( options.convertUpAxis ) { -switch ( member ) { -case 'X': -switch ( upConversion ) { -case 'XtoY': -case 'XtoZ': -case 'YtoX': -member = 'Y'; -break; -case 'ZtoX': -member = 'Z'; -break; -} -break; -case 'Y': -switch ( upConversion ) { -case 'XtoY': -case 'YtoX': -case 'ZtoX': -member = 'X'; -break; -case 'XtoZ': -case 'YtoZ': -case 'ZtoY': -member = 'Z'; -break; -} -break; -case 'Z': -switch ( upConversion ) { -case 'XtoZ': -member = 'X'; -break; -case 'YtoZ': -case 'ZtoX': -case 'ZtoY': -member = 'Y'; -break; -} -break; -} -} -return member; -} -return { -load: load, -parse: parse, -setPreferredShading: setPreferredShading, -applySkin: applySkin, -geometries : geometries, -options: options -}; -}; -/** -* @author Rich Tibbett / https://github.com/richtr -* @author mrdoob / http://mrdoob.com/ -* @author Tony Parisi / http://www.tonyparisi.com/ -* @author Takahiro / https://github.com/takahirox -* @author Don McCurdy / https://www.donmccurdy.com -*/ -THREE.GLTF2Loader = ( function () { -function GLTF2Loader( manager ) { -this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; -} -GLTF2Loader.prototype = { -constructor: GLTF2Loader, -load: function ( url, onLoad, onProgress, onError ) { -var scope = this; -var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url ); -var loader = new THREE.FileLoader( scope.manager ); -loader.setResponseType( 'arraybuffer' ); -loader.load( url, function ( data ) { -scope.parse( data, onLoad, path ); -}, onProgress, onError ); -}, -setCrossOrigin: function ( value ) { -this.crossOrigin = value; -}, -setPath: function ( value ) { -this.path = value; -}, -parse: function ( data, callback, path ) { -var content; -var extensions = {}; -var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) ); -if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) { -extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); -content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; -} else { -content = convertUint8ArrayToString( new Uint8Array( data ) ); -} -var json = JSON.parse( content ); -if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) { -extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json ); -} -console.time( 'GLTF2Loader' ); -var parser = new GLTFParser( json, extensions, { -path: path || this.path, -crossOrigin: this.crossOrigin -} ); -parser.parse( function ( scene, scenes, cameras, animations ) { -console.timeEnd( 'GLTF2Loader' ); -var glTF = { -"scene": scene, -"scenes": scenes, -"cameras": cameras, -"animations": animations -}; -callback( glTF ); -} ); -} -}; -/* GLTFREGISTRY */ -function GLTFRegistry() { -var objects = {}; -return { -get: function ( key ) { -return objects[ key ]; -}, -add: function ( key, object ) { -objects[ key ] = object; -}, -remove: function ( key ) { -delete objects[ key ]; -}, -removeAll: function () { -objects = {}; -}, -update: function ( scene, camera ) { -for ( var name in objects ) { -var object = objects[ name ]; -if ( object.update ) { -object.update( scene, camera ); -} -} -} -}; -} -/* GLTFSHADER */ -function GLTFShader( targetNode, allNodes ) { -var boundUniforms = {}; -var uniforms = targetNode.material.uniforms; -for ( var uniformId in uniforms ) { -var uniform = uniforms[ uniformId ]; -if ( uniform.semantic ) { -var sourceNodeRef = uniform.node; -var sourceNode = targetNode; -if ( sourceNodeRef ) { -sourceNode = allNodes[ sourceNodeRef ]; -} -boundUniforms[ uniformId ] = { -semantic: uniform.semantic, -sourceNode: sourceNode, -targetNode: targetNode, -uniform: uniform -}; -} -} -this.boundUniforms = boundUniforms; -this._m4 = new THREE.Matrix4(); -} -GLTFShader.prototype.update = function ( scene, camera ) { -var boundUniforms = this.boundUniforms; -for ( var name in boundUniforms ) { -var boundUniform = boundUniforms[ name ]; -switch ( boundUniform.semantic ) { -case "MODELVIEW": -var m4 = boundUniform.uniform.value; -m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); -break; -case "MODELVIEWINVERSETRANSPOSE": -var m3 = boundUniform.uniform.value; -this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); -m3.getNormalMatrix( this._m4 ); -break; -case "PROJECTION": -var m4 = boundUniform.uniform.value; -m4.copy( camera.projectionMatrix ); -break; -case "JOINTMATRIX": -var m4v = boundUniform.uniform.value; -for ( var mi = 0; mi < m4v.length; mi ++ ) { -m4v[ mi ] -.getInverse( boundUniform.sourceNode.matrixWorld ) -.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld ) -.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] ) -.multiply( boundUniform.targetNode.bindMatrix ); -} -break; -default : -console.warn( "Unhandled shader semantic: " + boundUniform.semantic ); -break; -} -} -}; -/*********************************/ -/********** EXTENSIONS ***********/ -/*********************************/ -var EXTENSIONS = { -KHR_BINARY_GLTF: 'KHR_binary_glTF', -KHR_MATERIALS_COMMON: 'KHR_materials_common' -}; -/* MATERIALS COMMON EXTENSION */ -function GLTFMaterialsCommonExtension( json ) { -this.name = EXTENSIONS.KHR_MATERIALS_COMMON; -this.lights = {}; -var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {}; -var lights = extension.lights || {}; -for ( var lightId in lights ) { -var light = lights[ lightId ]; -var lightNode; -var lightParams = light[ light.type ]; -var color = new THREE.Color().fromArray( lightParams.color ); -switch ( light.type ) { -case "directional": -lightNode = new THREE.DirectionalLight( color ); -lightNode.position.set( 0, 0, 1 ); -break; -case "point": -lightNode = new THREE.PointLight( color ); -break; -case "spot": -lightNode = new THREE.SpotLight( color ); -lightNode.position.set( 0, 0, 1 ); -break; -case "ambient": -lightNode = new THREE.AmbientLight( color ); -break; -} -if ( lightNode ) { -this.lights[ lightId ] = lightNode; -} -} -} -/* BINARY EXTENSION */ -var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF'; -var BINARY_EXTENSION_HEADER_MAGIC = 'glTF'; -var BINARY_EXTENSION_HEADER_LENGTH = 12; -var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 }; -function GLTFBinaryExtension( data ) { -this.name = EXTENSIONS.KHR_BINARY_GLTF; -this.content = null; -this.body = null; -var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); -this.header = { -magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ), -version: headerView.getUint32( 4, true ), -length: headerView.getUint32( 8, true ) -}; -if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) { -throw new Error( 'GLTF2Loader: Unsupported glTF-Binary header.' ); -} else if ( this.header.version < 2.0 ) { -throw new Error( 'GLTF2Loader: Legacy binary file detected. Use GLTFLoader instead.' ); -} -var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH ); -var chunkIndex = 0; -while ( chunkIndex < chunkView.byteLength ) { -var chunkLength = chunkView.getUint32( chunkIndex, true ); -chunkIndex += 4; -var chunkType = chunkView.getUint32( chunkIndex, true ); -chunkIndex += 4; -if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) { -var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength ); -this.content = convertUint8ArrayToString( contentArray ); -} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) { -var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex; -this.body = data.slice( byteOffset, byteOffset + chunkLength ); -} -chunkIndex += chunkLength; -} -if ( this.content === null ) { -throw new Error( 'GLTF2Loader: JSON content not found.' ); -} -} -/*********************************/ -/********** INTERNALS ************/ -/*********************************/ -/* CONSTANTS */ -var WEBGL_CONSTANTS = { -FLOAT: 5126, -FLOAT_MAT3: 35675, -FLOAT_MAT4: 35676, -FLOAT_VEC2: 35664, -FLOAT_VEC3: 35665, -FLOAT_VEC4: 35666, -LINEAR: 9729, -REPEAT: 10497, -SAMPLER_2D: 35678, -TRIANGLES: 4, -LINES: 1, -UNSIGNED_BYTE: 5121, -UNSIGNED_SHORT: 5123, -VERTEX_SHADER: 35633, -FRAGMENT_SHADER: 35632 -}; -var WEBGL_TYPE = { -5126: Number, -35675: THREE.Matrix3, -35676: THREE.Matrix4, -35664: THREE.Vector2, -35665: THREE.Vector3, -35666: THREE.Vector4, -35678: THREE.Texture -}; -var WEBGL_COMPONENT_TYPES = { -5120: Int8Array, -5121: Uint8Array, -5122: Int16Array, -5123: Uint16Array, -5125: Uint32Array, -5126: Float32Array -}; -var WEBGL_FILTERS = { -9728: THREE.NearestFilter, -9729: THREE.LinearFilter, -9984: THREE.NearestMipMapNearestFilter, -9985: THREE.LinearMipMapNearestFilter, -9986: THREE.NearestMipMapLinearFilter, -9987: THREE.LinearMipMapLinearFilter -}; -var WEBGL_WRAPPINGS = { -33071: THREE.ClampToEdgeWrapping, -33648: THREE.MirroredRepeatWrapping, -10497: THREE.RepeatWrapping -}; -var WEBGL_TEXTURE_FORMATS = { -6406: THREE.AlphaFormat, -6407: THREE.RGBFormat, -6408: THREE.RGBAFormat, -6409: THREE.LuminanceFormat, -6410: THREE.LuminanceAlphaFormat -}; -var WEBGL_TEXTURE_DATATYPES = { -5121: THREE.UnsignedByteType, -32819: THREE.UnsignedShort4444Type, -32820: THREE.UnsignedShort5551Type, -33635: THREE.UnsignedShort565Type -}; -var WEBGL_SIDES = { -1028: THREE.BackSide, // Culling front -1029: THREE.FrontSide // Culling back -}; -var WEBGL_DEPTH_FUNCS = { -512: THREE.NeverDepth, -513: THREE.LessDepth, -514: THREE.EqualDepth, -515: THREE.LessEqualDepth, -516: THREE.GreaterEqualDepth, -517: THREE.NotEqualDepth, -518: THREE.GreaterEqualDepth, -519: THREE.AlwaysDepth -}; -var WEBGL_BLEND_EQUATIONS = { -32774: THREE.AddEquation, -32778: THREE.SubtractEquation, -32779: THREE.ReverseSubtractEquation -}; -var WEBGL_BLEND_FUNCS = { -0: THREE.ZeroFactor, -1: THREE.OneFactor, -768: THREE.SrcColorFactor, -769: THREE.OneMinusSrcColorFactor, -770: THREE.SrcAlphaFactor, -771: THREE.OneMinusSrcAlphaFactor, -772: THREE.DstAlphaFactor, -773: THREE.OneMinusDstAlphaFactor, -774: THREE.DstColorFactor, -775: THREE.OneMinusDstColorFactor, -776: THREE.SrcAlphaSaturateFactor -}; -var WEBGL_TYPE_SIZES = { -'SCALAR': 1, -'VEC2': 2, -'VEC3': 3, -'VEC4': 4, -'MAT2': 4, -'MAT3': 9, -'MAT4': 16 -}; -var PATH_PROPERTIES = { -scale: 'scale', -translation: 'position', -rotation: 'quaternion' -}; -var INTERPOLATION = { -LINEAR: THREE.InterpolateLinear, -STEP: THREE.InterpolateDiscrete -}; -var STATES_ENABLES = { -2884: 'CULL_FACE', -2929: 'DEPTH_TEST', -3042: 'BLEND', -3089: 'SCISSOR_TEST', -32823: 'POLYGON_OFFSET_FILL', -32926: 'SAMPLE_ALPHA_TO_COVERAGE' -}; -/* UTILITY FUNCTIONS */ -function _each( object, callback, thisObj ) { -if ( !object ) { -return Promise.resolve(); -} -var results; -var fns = []; -if ( Object.prototype.toString.call( object ) === '[object Array]' ) { -results = []; -var length = object.length; -for ( var idx = 0; idx < length; idx ++ ) { -var value = callback.call( thisObj || this, object[ idx ], idx ); -if ( value ) { -fns.push( value ); -if ( value instanceof Promise ) { -value.then( function( key, value ) { -results[ key ] = value; -}.bind( this, idx )); -} else { -results[ idx ] = value; -} -} -} -} else { -results = {}; -for ( var key in object ) { -if ( object.hasOwnProperty( key ) ) { -var value = callback.call( thisObj || this, object[ key ], key ); -if ( value ) { -fns.push( value ); -if ( value instanceof Promise ) { -value.then( function( key, value ) { -results[ key ] = value; -}.bind( this, key )); -} else { -results[ key ] = value; -} -} -} -} -} -return Promise.all( fns ).then( function() { -return results; -}); -} -function resolveURL( url, path ) { -if ( typeof url !== 'string' || url === '' ) -return ''; -if ( /^(https?:)?\/\//i.test( url ) ) { -return url; -} -if ( /^data:.*,.*$/i.test( url ) ) { -return url; -} -if ( /^blob:.*$/i.test( url ) ) { -return url; -} -return ( path || '' ) + url; -} -function convertUint8ArrayToString( array ) { -var s = ''; -for ( var i = 0; i < array.length; i ++ ) { -s += String.fromCharCode( array[ i ] ); -} -return s; -} -function replaceTHREEShaderAttributes( shaderText, technique ) { -var attributes = {}; -for ( var attributeId in technique.attributes ) { -var pname = technique.attributes[ attributeId ]; -var param = technique.parameters[ pname ]; -var atype = param.type; -var semantic = param.semantic; -attributes[ attributeId ] = { -type: atype, -semantic: semantic -}; -} -var shaderParams = technique.parameters; -var shaderAttributes = technique.attributes; -var params = {}; -for ( var attributeId in attributes ) { -var pname = shaderAttributes[ attributeId ]; -var shaderParam = shaderParams[ pname ]; -var semantic = shaderParam.semantic; -if ( semantic ) { -params[ attributeId ] = shaderParam; -} -} -for ( var pname in params ) { -var param = params[ pname ]; -var semantic = param.semantic; -var regEx = new RegExp( "\\b" + pname + "\\b", "g" ); -switch ( semantic ) { -case 'POSITION': -shaderText = shaderText.replace( regEx, 'position' ); -break; -case 'NORMAL': -shaderText = shaderText.replace( regEx, 'normal' ); -break; -case 'TEXCOORD_0': -case 'TEXCOORD0': -case 'TEXCOORD': -shaderText = shaderText.replace( regEx, 'uv' ); -break; -case 'TEXCOORD_1': -shaderText = shaderText.replace( regEx, 'uv2' ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -shaderText = shaderText.replace( regEx, 'color' ); -break; -case 'WEIGHTS_0': -case 'WEIGHT': // WEIGHT semantic deprecated. -shaderText = shaderText.replace( regEx, 'skinWeight' ); -break; -case 'JOINTS_0': -case 'JOINT': // JOINT semantic deprecated. -shaderText = shaderText.replace( regEx, 'skinIndex' ); -break; -} -} -return shaderText; -} -function createDefaultMaterial() { -return new THREE.MeshPhongMaterial( { -color: 0x00000, -emissive: 0x888888, -specular: 0x000000, -shininess: 0, -transparent: false, -depthTest: true, -side: THREE.FrontSide -} ); -} -function DeferredShaderMaterial( params ) { -this.isDeferredShaderMaterial = true; -this.params = params; -} -DeferredShaderMaterial.prototype.create = function () { -var uniforms = THREE.UniformsUtils.clone( this.params.uniforms ); -for ( var uniformId in this.params.uniforms ) { -var originalUniform = this.params.uniforms[ uniformId ]; -if ( originalUniform.value instanceof THREE.Texture ) { -uniforms[ uniformId ].value = originalUniform.value; -uniforms[ uniformId ].value.needsUpdate = true; -} -uniforms[ uniformId ].semantic = originalUniform.semantic; -uniforms[ uniformId ].node = originalUniform.node; -} -this.params.uniforms = uniforms; -return new THREE.RawShaderMaterial( this.params ); -}; -/* GLTF PARSER */ -function GLTFParser( json, extensions, options ) { -this.json = json || {}; -this.extensions = extensions || {}; -this.options = options || {}; -this.cache = new GLTFRegistry(); -} -GLTFParser.prototype._withDependencies = function ( dependencies ) { -var _dependencies = {}; -for ( var i = 0; i < dependencies.length; i ++ ) { -var dependency = dependencies[ i ]; -var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 ); -var cached = this.cache.get( dependency ); -if ( cached !== undefined ) { -_dependencies[ dependency ] = cached; -} else if ( this[ fnName ] ) { -var fn = this[ fnName ](); -this.cache.add( dependency, fn ); -_dependencies[ dependency ] = fn; -} -} -return _each( _dependencies, function ( dependency ) { -return dependency; -} ); -}; -GLTFParser.prototype.parse = function ( callback ) { -var json = this.json; -this.cache.removeAll(); -this._withDependencies( [ -"scenes", -"cameras", -"animations" -] ).then( function ( dependencies ) { -var scenes = []; -for ( var name in dependencies.scenes ) { -scenes.push( dependencies.scenes[ name ] ); -} -var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ]; -var cameras = []; -for ( var name in dependencies.cameras ) { -var camera = dependencies.cameras[ name ]; -cameras.push( camera ); -} -var animations = []; -for ( var name in dependencies.animations ) { -animations.push( dependencies.animations[ name ] ); -} -callback( scene, scenes, cameras, animations ); -} ); -}; -GLTFParser.prototype.loadShaders = function () { -var json = this.json; -var options = this.options; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.shaders, function ( shader ) { -if ( shader.bufferView !== undefined ) { -var bufferView = dependencies.bufferViews[ shader.bufferView ]; -var array = new Uint8Array( bufferView ); -return convertUint8ArrayToString( array ); -} -return new Promise( function ( resolve ) { -var loader = new THREE.FileLoader(); -loader.setResponseType( 'text' ); -loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) { -resolve( shaderText ); -} ); -} ); -} ); -} ); -}; -GLTFParser.prototype.loadBuffers = function () { -var json = this.json; -var extensions = this.extensions; -var options = this.options; -return _each( json.buffers, function ( buffer, name ) { -if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) { -if ( buffer.uri === undefined && name === 0 ) { -return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body; -} -return new Promise( function ( resolve ) { -var loader = new THREE.FileLoader(); -loader.setResponseType( 'arraybuffer' ); -loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) { -resolve( buffer ); -} ); -} ); -} else { -console.warn( 'THREE.GLTF2Loader: ' + buffer.type + ' buffer type is not supported' ); -} -} ); -}; -GLTFParser.prototype.loadBufferViews = function () { -var json = this.json; -return this._withDependencies( [ -"buffers" -] ).then( function ( dependencies ) { -return _each( json.bufferViews, function ( bufferView ) { -var arraybuffer = dependencies.buffers[ bufferView.buffer ]; -var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0; -return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength ); -} ); -} ); -}; -GLTFParser.prototype.loadAccessors = function () { -var json = this.json; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.accessors, function ( accessor ) { -var arraybuffer = dependencies.bufferViews[ accessor.bufferView ]; -var itemSize = WEBGL_TYPE_SIZES[ accessor.type ]; -var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ]; -var elementBytes = TypedArray.BYTES_PER_ELEMENT; -var itemBytes = elementBytes * itemSize; -var array; -if ( accessor.byteStride && accessor.byteStride !== itemBytes ) { -array = new TypedArray( arraybuffer ); -var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes ); -return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes ); -} else { -array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize ); -return new THREE.BufferAttribute( array, itemSize ); -} -} ); -} ); -}; -GLTFParser.prototype.loadTextures = function () { -var json = this.json; -var options = this.options; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.textures, function ( texture ) { -if ( texture.source !== undefined ) { -return new Promise( function ( resolve ) { -var source = json.images[ texture.source ]; -var sourceUri = source.uri; -var urlCreator; -if ( source.bufferView !== undefined ) { -var bufferView = dependencies.bufferViews[ source.bufferView ]; -var blob = new Blob( [ bufferView ], { type: source.mimeType } ); -urlCreator = window.URL || window.webkitURL; -sourceUri = urlCreator.createObjectURL( blob ); -} -var textureLoader = THREE.Loader.Handlers.get( sourceUri ); -if ( textureLoader === null ) { -textureLoader = new THREE.TextureLoader(); -} -textureLoader.setCrossOrigin( options.crossOrigin ); -textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) { -if ( urlCreator !== undefined ) { -urlCreator.revokeObjectURL( sourceUri ); -} -_texture.flipY = false; -if ( texture.name !== undefined ) _texture.name = texture.name; -_texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat; -if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) { -console.warn( 'THREE.GLTF2Loader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' + -'internalFormat will be forced to be the same value as format.' ); -} -_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType; -if ( texture.sampler !== undefined ) { -var sampler = json.samplers[ texture.sampler ]; -_texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter; -_texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipMapLinearFilter; -_texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping; -_texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping; -} -resolve( _texture ); -}, undefined, function () { -resolve(); -} ); -} ); -} -} ); -} ); -}; -GLTFParser.prototype.loadMaterials = function () { -var json = this.json; -return this._withDependencies( [ -"shaders", -"textures" -] ).then( function ( dependencies ) { -return _each( json.materials, function ( material ) { -var materialType; -var materialValues = {}; -var materialParams = {}; -var khr_material; -if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) { -khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]; -} -if ( khr_material ) { -var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ]; -switch ( khr_material.technique ) { -case 'BLINN' : -case 'PHONG' : -materialType = THREE.MeshPhongMaterial; -keys.push( 'diffuse', 'specular', 'shininess' ); -break; -case 'LAMBERT' : -materialType = THREE.MeshLambertMaterial; -keys.push( 'diffuse' ); -break; -case 'CONSTANT' : -default : -materialType = THREE.MeshBasicMaterial; -break; -} -keys.forEach( function( v ) { -if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ]; -} ); -if ( khr_material.doubleSided || materialValues.doubleSided ) { -materialParams.side = THREE.DoubleSide; -} -if ( khr_material.transparent || materialValues.transparent ) { -materialParams.transparent = true; -materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1; -} -} else if ( material.technique === undefined ) { -if ( material.pbrMetallicRoughness !== undefined ) { -materialType = THREE.MeshStandardMaterial; -if ( material.pbrMetallicRoughness !== undefined ) { -var metallicRoughness = material.pbrMetallicRoughness; -materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 ); -materialParams.opacity = 1.0; -if ( Array.isArray( metallicRoughness.baseColorFactor ) ) { -var array = metallicRoughness.baseColorFactor; -materialParams.color.fromArray( array ); -materialParams.opacity = array[ 3 ]; -} -if ( metallicRoughness.baseColorTexture !== undefined ) { -materialParams.map = dependencies.textures[ metallicRoughness.baseColorTexture.index ]; -} -if ( materialParams.opacity < 1.0 || -( materialParams.map !== undefined && -( materialParams.map.format === THREE.AlphaFormat || -materialParams.map.format === THREE.RGBAFormat || -materialParams.map.format === THREE.LuminanceAlphaFormat ) ) ) { -materialParams.transparent = true; -} -materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0; -materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0; -if ( metallicRoughness.metallicRoughnessTexture !== undefined ) { -var textureIndex = metallicRoughness.metallicRoughnessTexture.index; -materialParams.metalnessMap = dependencies.textures[ textureIndex ]; -materialParams.roughnessMap = dependencies.textures[ textureIndex ]; -} -} -} else { -materialType = THREE.MeshPhongMaterial; -} -if ( material.normalTexture !== undefined ) { -materialParams.normalMap = dependencies.textures[ material.normalTexture.index ]; -} -if ( material.occlusionTexture !== undefined ) { -materialParams.aoMap = dependencies.textures[ material.occlusionTexture.index ]; -} -if ( material.emissiveTexture !== undefined ) { -materialParams.emissiveMap = dependencies.textures[ material.emissiveTexture.index ]; -} -materialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 ); -if ( material.emissiveFactor !== undefined ) { -materialParams.emissive.fromArray( material.emissiveFactor ); -} -Object.assign( materialValues, material.values ); -} else { -materialType = DeferredShaderMaterial; -var technique = json.techniques[ material.technique ]; -materialParams.uniforms = {}; -var program = json.programs[ technique.program ]; -if ( program ) { -materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ]; -if ( ! materialParams.fragmentShader ) { -console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader ); -materialType = THREE.MeshPhongMaterial; -} -var vertexShader = dependencies.shaders[ program.vertexShader ]; -if ( ! vertexShader ) { -console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader ); -materialType = THREE.MeshPhongMaterial; -} -materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique ); -var uniforms = technique.uniforms; -for ( var uniformId in uniforms ) { -var pname = uniforms[ uniformId ]; -var shaderParam = technique.parameters[ pname ]; -var ptype = shaderParam.type; -if ( WEBGL_TYPE[ ptype ] ) { -var pcount = shaderParam.count; -var value; -if ( material.values !== undefined ) value = material.values[ pname ]; -var uvalue = new WEBGL_TYPE[ ptype ](); -var usemantic = shaderParam.semantic; -var unode = shaderParam.node; -switch ( ptype ) { -case WEBGL_CONSTANTS.FLOAT: -uvalue = shaderParam.value; -if ( pname == "transparency" ) { -materialParams.transparent = true; -} -if ( value !== undefined ) { -uvalue = value; -} -break; -case WEBGL_CONSTANTS.FLOAT_VEC2: -case WEBGL_CONSTANTS.FLOAT_VEC3: -case WEBGL_CONSTANTS.FLOAT_VEC4: -case WEBGL_CONSTANTS.FLOAT_MAT3: -if ( shaderParam && shaderParam.value ) { -uvalue.fromArray( shaderParam.value ); -} -if ( value ) { -uvalue.fromArray( value ); -} -break; -case WEBGL_CONSTANTS.FLOAT_MAT2: -console.warn( "FLOAT_MAT2 is not a supported uniform type" ); -break; -case WEBGL_CONSTANTS.FLOAT_MAT4: -if ( pcount ) { -uvalue = new Array( pcount ); -for ( var mi = 0; mi < pcount; mi ++ ) { -uvalue[ mi ] = new WEBGL_TYPE[ ptype ](); -} -if ( shaderParam && shaderParam.value ) { -var m4v = shaderParam.value; -uvalue.fromArray( m4v ); -} -if ( value ) { -uvalue.fromArray( value ); -} -} else { -if ( shaderParam && shaderParam.value ) { -var m4 = shaderParam.value; -uvalue.fromArray( m4 ); -} -if ( value ) { -uvalue.fromArray( value ); -} -} -break; -case WEBGL_CONSTANTS.SAMPLER_2D: -if ( value !== undefined ) { -uvalue = dependencies.textures[ value ]; -} else if ( shaderParam.value !== undefined ) { -uvalue = dependencies.textures[ shaderParam.value ]; -} else { -uvalue = null; -} -break; -} -materialParams.uniforms[ uniformId ] = { -value: uvalue, -semantic: usemantic, -node: unode -}; -} else { -throw new Error( "Unknown shader uniform param type: " + ptype ); -} -} -var states = technique.states || {}; -var enables = states.enable || []; -var functions = states.functions || {}; -var enableCullFace = false; -var enableDepthTest = false; -var enableBlend = false; -for ( var i = 0, il = enables.length; i < il; i ++ ) { -var enable = enables[ i ]; -switch ( STATES_ENABLES[ enable ] ) { -case 'CULL_FACE': -enableCullFace = true; -break; -case 'DEPTH_TEST': -enableDepthTest = true; -break; -case 'BLEND': -enableBlend = true; -break; -case 'SCISSOR_TEST': -case 'POLYGON_OFFSET_FILL': -case 'SAMPLE_ALPHA_TO_COVERAGE': -break; -default: -throw new Error( "Unknown technique.states.enable: " + enable ); -} -} -if ( enableCullFace ) { -materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide; -} else { -materialParams.side = THREE.DoubleSide; -} -materialParams.depthTest = enableDepthTest; -materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth; -materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true; -materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending; -materialParams.transparent = enableBlend; -var blendEquationSeparate = functions.blendEquationSeparate; -if ( blendEquationSeparate !== undefined ) { -materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ]; -materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ]; -} else { -materialParams.blendEquation = THREE.AddEquation; -materialParams.blendEquationAlpha = THREE.AddEquation; -} -var blendFuncSeparate = functions.blendFuncSeparate; -if ( blendFuncSeparate !== undefined ) { -materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ]; -materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ]; -materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ]; -materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ]; -} else { -materialParams.blendSrc = THREE.OneFactor; -materialParams.blendDst = THREE.ZeroFactor; -materialParams.blendSrcAlpha = THREE.OneFactor; -materialParams.blendDstAlpha = THREE.ZeroFactor; -} -} -} -if ( Array.isArray( materialValues.diffuse ) ) { -materialParams.color = new THREE.Color().fromArray( materialValues.diffuse ); -} else if ( typeof( materialValues.diffuse ) === 'string' ) { -materialParams.map = dependencies.textures[ materialValues.diffuse ]; -} -delete materialParams.diffuse; -if ( typeof( materialValues.reflective ) === 'string' ) { -materialParams.envMap = dependencies.textures[ materialValues.reflective ]; -} -if ( typeof( materialValues.bump ) === 'string' ) { -materialParams.bumpMap = dependencies.textures[ materialValues.bump ]; -} -if ( Array.isArray( materialValues.emission ) ) { -if ( materialType === THREE.MeshBasicMaterial ) { -materialParams.color = new THREE.Color().fromArray( materialValues.emission ); -} else { -materialParams.emissive = new THREE.Color().fromArray( materialValues.emission ); -} -} else if ( typeof( materialValues.emission ) === 'string' ) { -if ( materialType === THREE.MeshBasicMaterial ) { -materialParams.map = dependencies.textures[ materialValues.emission ]; -} else { -materialParams.emissiveMap = dependencies.textures[ materialValues.emission ]; -} -} -if ( Array.isArray( materialValues.specular ) ) { -materialParams.specular = new THREE.Color().fromArray( materialValues.specular ); -} else if ( typeof( materialValues.specular ) === 'string' ) { -materialParams.specularMap = dependencies.textures[ materialValues.specular ]; -} -if ( materialValues.shininess !== undefined ) { -materialParams.shininess = materialValues.shininess; -} -var _material = new materialType( materialParams ); -if ( material.name !== undefined ) _material.name = material.name; -return _material; -} ); -} ); -}; -GLTFParser.prototype.loadMeshes = function () { -var json = this.json; -return this._withDependencies( [ -"accessors", -"materials" -] ).then( function ( dependencies ) { -return _each( json.meshes, function ( mesh ) { -var group = new THREE.Group(); -if ( mesh.name !== undefined ) group.name = mesh.name; -if ( mesh.extras ) group.userData = mesh.extras; -var primitives = mesh.primitives || []; -for ( var name in primitives ) { -var primitive = primitives[ name ]; -var material = primitive.material !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial(); -var geometry; -var meshNode; -if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) { -geometry = new THREE.BufferGeometry(); -var attributes = primitive.attributes; -for ( var attributeId in attributes ) { -var attributeEntry = attributes[ attributeId ]; -if ( attributeEntry === undefined ) return; -var bufferAttribute = dependencies.accessors[ attributeEntry ]; -switch ( attributeId ) { -case 'POSITION': -geometry.addAttribute( 'position', bufferAttribute ); -break; -case 'NORMAL': -geometry.addAttribute( 'normal', bufferAttribute ); -break; -case 'TEXCOORD_0': -case 'TEXCOORD0': -case 'TEXCOORD': -geometry.addAttribute( 'uv', bufferAttribute ); -break; -case 'TEXCOORD_1': -geometry.addAttribute( 'uv2', bufferAttribute ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -geometry.addAttribute( 'color', bufferAttribute ); -break; -case 'WEIGHTS_0': -case 'WEIGHT': // WEIGHT semantic deprecated. -geometry.addAttribute( 'skinWeight', bufferAttribute ); -break; -case 'JOINTS_0': -case 'JOINT': // JOINT semantic deprecated. -geometry.addAttribute( 'skinIndex', bufferAttribute ); -break; -} -} -if ( primitive.indices !== undefined ) { -geometry.setIndex( dependencies.accessors[ primitive.indices ] ); -} -meshNode = new THREE.Mesh( geometry, material ); -meshNode.castShadow = true; -} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) { -geometry = new THREE.BufferGeometry(); -var attributes = primitive.attributes; -for ( var attributeId in attributes ) { -var attributeEntry = attributes[ attributeId ]; -if ( ! attributeEntry ) return; -var bufferAttribute = dependencies.accessors[ attributeEntry ]; -switch ( attributeId ) { -case 'POSITION': -geometry.addAttribute( 'position', bufferAttribute ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -geometry.addAttribute( 'color', bufferAttribute ); -break; -} -} -if ( primitive.indices !== undefined ) { -geometry.setIndex( dependencies.accessors[ primitive.indices ] ); -meshNode = new THREE.LineSegments( geometry, material ); -} else { -meshNode = new THREE.Line( geometry, material ); -} -} else { -throw new Error( "Only triangular and line primitives are supported" ); -} -if ( geometry.attributes.color !== undefined ) { -material.vertexColors = THREE.VertexColors; -material.needsUpdate = true; -} -meshNode.name = ( name === "0" ? group.name : group.name + name ); -if ( primitive.extras ) meshNode.userData = primitive.extras; -group.add( meshNode ); -} -return group; -} ); -} ); -}; -GLTFParser.prototype.loadCameras = function () { -var json = this.json; -return _each( json.cameras, function ( camera ) { -if ( camera.type == "perspective" && camera.perspective ) { -var yfov = camera.perspective.yfov; -var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1; -var xfov = yfov * aspectRatio; -var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 ); -if ( camera.name !== undefined ) _camera.name = camera.name; -if ( camera.extras ) _camera.userData = camera.extras; -return _camera; -} else if ( camera.type == "orthographic" && camera.orthographic ) { -var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar ); -if ( camera.name !== undefined ) _camera.name = camera.name; -if ( camera.extras ) _camera.userData = camera.extras; -return _camera; -} -} ); -}; -GLTFParser.prototype.loadSkins = function () { -var json = this.json; -return this._withDependencies( [ -"accessors" -] ).then( function ( dependencies ) { -return _each( json.skins, function ( skin ) { -var bindShapeMatrix = new THREE.Matrix4(); -if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix ); -var _skin = { -bindShapeMatrix: bindShapeMatrix, -jointNames: skin.jointNames, -inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ] -}; -return _skin; -} ); -} ); -}; -GLTFParser.prototype.loadAnimations = function () { -var json = this.json; -return this._withDependencies( [ -"accessors", -"nodes" -] ).then( function ( dependencies ) { -return _each( json.animations, function ( animation, animationId ) { -var tracks = []; -for ( var channelId in animation.channels ) { -var channel = animation.channels[ channelId ]; -var sampler = animation.samplers[ channel.sampler ]; -if ( sampler ) { -var target = channel.target; -var name = target.node || target.id; // NOTE: target.id is deprecated. -var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input; -var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output; -var inputAccessor = dependencies.accessors[ input ]; -var outputAccessor = dependencies.accessors[ output ]; -var node = dependencies.nodes[ name ]; -if ( node ) { -node.updateMatrix(); -node.matrixAutoUpdate = true; -var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation -? THREE.QuaternionKeyframeTrack -: THREE.VectorKeyframeTrack; -var targetName = node.name ? node.name : node.uuid; -var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear; -tracks.push( new TypedKeyframeTrack( -targetName + '.' + PATH_PROPERTIES[ target.path ], -THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ), -THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ), -interpolation -) ); -} -} -} -var name = animation.name !== undefined ? animation.name : "animation_" + animationId; -return new THREE.AnimationClip( name, undefined, tracks ); -} ); -} ); -}; -GLTFParser.prototype.loadNodes = function () { -var json = this.json; -var extensions = this.extensions; -var scope = this; -return _each( json.nodes, function ( node ) { -var matrix = new THREE.Matrix4(); -var _node; -if ( node.jointName ) { -_node = new THREE.Bone(); -_node.name = node.name !== undefined ? node.name : node.jointName; -_node.jointName = node.jointName; -} else { -_node = new THREE.Object3D(); -if ( node.name !== undefined ) _node.name = node.name; -} -if ( node.extras ) _node.userData = node.extras; -if ( node.matrix !== undefined ) { -matrix.fromArray( node.matrix ); -_node.applyMatrix( matrix ); -} else { -if ( node.translation !== undefined ) { -_node.position.fromArray( node.translation ); -} -if ( node.rotation !== undefined ) { -_node.quaternion.fromArray( node.rotation ); -} -if ( node.scale !== undefined ) { -_node.scale.fromArray( node.scale ); -} -} -return _node; -} ).then( function ( __nodes ) { -return scope._withDependencies( [ -"meshes", -"skins", -"cameras" -] ).then( function ( dependencies ) { -return _each( __nodes, function ( _node, nodeId ) { -var node = json.nodes[ nodeId ]; -var meshes; -if ( node.mesh !== undefined) { -meshes = [ node.mesh ]; -} else if ( node.meshes !== undefined ) { -console.warn( 'GLTF2Loader: Legacy glTF file detected. Nodes may have no more than 1 mesh.' ); -meshes = node.meshes; -} -if ( meshes !== undefined ) { -for ( var meshId in meshes ) { -var mesh = meshes[ meshId ]; -var group = dependencies.meshes[ mesh ]; -if ( group === undefined ) { -console.warn( 'GLTF2Loader: Couldn\'t find node "' + mesh + '".' ); -continue; -} -for ( var childrenId in group.children ) { -var child = group.children[ childrenId ]; -var originalMaterial = child.material; -var originalGeometry = child.geometry; -var originalUserData = child.userData; -var originalName = child.name; -var material; -if ( originalMaterial.isDeferredShaderMaterial ) { -originalMaterial = material = originalMaterial.create(); -} else { -material = originalMaterial; -} -switch ( child.type ) { -case 'LineSegments': -child = new THREE.LineSegments( originalGeometry, material ); -break; -case 'LineLoop': -child = new THREE.LineLoop( originalGeometry, material ); -break; -case 'Line': -child = new THREE.Line( originalGeometry, material ); -break; -default: -child = new THREE.Mesh( originalGeometry, material ); -} -child.castShadow = true; -child.userData = originalUserData; -child.name = originalName; -var skinEntry; -if ( node.skin !== undefined ) { -skinEntry = dependencies.skins[ node.skin ]; -} -if ( skinEntry ) { -var getJointNode = function ( jointId ) { -var keys = Object.keys( __nodes ); -for ( var i = 0, il = keys.length; i < il; i ++ ) { -var n = __nodes[ keys[ i ] ]; -if ( n.jointName === jointId ) return n; -} -return null; -}; -var geometry = originalGeometry; -var material = originalMaterial; -material.skinning = true; -child = new THREE.SkinnedMesh( geometry, material, false ); -child.castShadow = true; -child.userData = originalUserData; -child.name = originalName; -var bones = []; -var boneInverses = []; -for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) { -var jointId = skinEntry.jointNames[ i ]; -var jointNode = getJointNode( jointId ); -if ( jointNode ) { -bones.push( jointNode ); -var m = skinEntry.inverseBindMatrices.array; -var mat = new THREE.Matrix4().fromArray( m, i * 16 ); -boneInverses.push( mat ); -} else { -console.warn( "WARNING: joint: '" + jointId + "' could not be found" ); -} -} -child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix ); -var buildBoneGraph = function ( parentJson, parentObject, property ) { -var children = parentJson[ property ]; -if ( children === undefined ) return; -for ( var i = 0, il = children.length; i < il; i ++ ) { -var nodeId = children[ i ]; -var bone = __nodes[ nodeId ]; -var boneJson = json.nodes[ nodeId ]; -if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) { -parentObject.add( bone ); -buildBoneGraph( boneJson, bone, 'children' ); -} -} -}; -buildBoneGraph( node, child, 'skeletons' ); -} -_node.add( child ); -} -} -} -if ( node.camera !== undefined ) { -var camera = dependencies.cameras[ node.camera ]; -_node.add( camera ); -} -if ( node.extensions -&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] -&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) { -var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights; -var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ]; -_node.add( light ); -} -return _node; -} ); -} ); -} ); -}; -GLTFParser.prototype.loadScenes = function () { -var json = this.json; -function buildNodeHierachy( nodeId, parentObject, allNodes ) { -var _node = allNodes[ nodeId ]; -parentObject.add( _node ); -var node = json.nodes[ nodeId ]; -if ( node.children ) { -var children = node.children; -for ( var i = 0, l = children.length; i < l; i ++ ) { -var child = children[ i ]; -buildNodeHierachy( child, _node, allNodes ); -} -} -} -return this._withDependencies( [ -"nodes" -] ).then( function ( dependencies ) { -return _each( json.scenes, function ( scene ) { -var _scene = new THREE.Scene(); -if ( scene.name !== undefined ) _scene.name = scene.name; -if ( scene.extras ) _scene.userData = scene.extras; -var nodes = scene.nodes || []; -for ( var i = 0, l = nodes.length; i < l; i ++ ) { -var nodeId = nodes[ i ]; -buildNodeHierachy( nodeId, _scene, dependencies.nodes ); -} -_scene.traverse( function ( child ) { -if ( child.material && child.material.isRawShaderMaterial ) { -child.gltfShader = new GLTFShader( child, dependencies.nodes ); -child.onBeforeRender = function(renderer, scene, camera){ -this.gltfShader.update(scene, camera); -}; -} -} ); -return _scene; -} ); -} ); -}; -return GLTF2Loader; -} )(); -/** -* @author Rich Tibbett / https://github.com/richtr -* @author mrdoob / http://mrdoob.com/ -* @author Tony Parisi / http://www.tonyparisi.com/ -* @author Takahiro / https://github.com/takahirox -*/ -THREE.GLTFLoader = ( function () { -function GLTFLoader( manager ) { -this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; -} -GLTFLoader.prototype = { -constructor: GLTFLoader, -load: function ( url, onLoad, onProgress, onError ) { -var scope = this; -var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url ); -var loader = new THREE.FileLoader( scope.manager ); -loader.setResponseType( 'arraybuffer' ); -loader.load( url, function ( data ) { -scope.parse( data, onLoad, path ); -}, onProgress, onError ); -}, -setCrossOrigin: function ( value ) { -this.crossOrigin = value; -}, -setPath: function ( value ) { -this.path = value; -}, -parse: function ( data, callback, path ) { -var content; -var extensions = {}; -var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) ); -if ( magic === BINARY_EXTENSION_HEADER_DEFAULTS.magic ) { -extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); -content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; -} else { -content = convertUint8ArrayToString( new Uint8Array( data ) ); -} -var json = JSON.parse( content ); -if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) { -extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json ); -} -console.time( 'GLTFLoader' ); -var parser = new GLTFParser( json, extensions, { -path: path || this.path, -crossOrigin: this.crossOrigin -} ); -parser.parse( function ( scene, scenes, cameras, animations ) { -console.timeEnd( 'GLTFLoader' ); -var glTF = { -"scene": scene, -"scenes": scenes, -"cameras": cameras, -"animations": animations -}; -callback( glTF ); -} ); -} -}; -/* GLTFREGISTRY */ -function GLTFRegistry() { -var objects = {}; -return { -get: function ( key ) { -return objects[ key ]; -}, -add: function ( key, object ) { -objects[ key ] = object; -}, -remove: function ( key ) { -delete objects[ key ]; -}, -removeAll: function () { -objects = {}; -}, -update: function ( scene, camera ) { -for ( var name in objects ) { -var object = objects[ name ]; -if ( object.update ) { -object.update( scene, camera ); -} -} -} -}; -} -/* GLTFSHADERS */ -GLTFLoader.Shaders = { -update: function () { -console.warn( 'THREE.GLTFLoader.Shaders has been deprecated, and now updates automatically.' ); -} -}; -/* GLTFSHADER */ -function GLTFShader( targetNode, allNodes ) { -var boundUniforms = {}; -var uniforms = targetNode.material.uniforms; -for ( var uniformId in uniforms ) { -var uniform = uniforms[ uniformId ]; -if ( uniform.semantic ) { -var sourceNodeRef = uniform.node; -var sourceNode = targetNode; -if ( sourceNodeRef ) { -sourceNode = allNodes[ sourceNodeRef ]; -} -boundUniforms[ uniformId ] = { -semantic: uniform.semantic, -sourceNode: sourceNode, -targetNode: targetNode, -uniform: uniform -}; -} -} -this.boundUniforms = boundUniforms; -this._m4 = new THREE.Matrix4(); -} -GLTFShader.prototype.update = function ( scene, camera ) { -var boundUniforms = this.boundUniforms; -for ( var name in boundUniforms ) { -var boundUniform = boundUniforms[ name ]; -switch ( boundUniform.semantic ) { -case "MODELVIEW": -var m4 = boundUniform.uniform.value; -m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); -break; -case "MODELVIEWINVERSETRANSPOSE": -var m3 = boundUniform.uniform.value; -this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); -m3.getNormalMatrix( this._m4 ); -break; -case "PROJECTION": -var m4 = boundUniform.uniform.value; -m4.copy( camera.projectionMatrix ); -break; -case "JOINTMATRIX": -var m4v = boundUniform.uniform.value; -for ( var mi = 0; mi < m4v.length; mi ++ ) { -m4v[ mi ] -.getInverse( boundUniform.sourceNode.matrixWorld ) -.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld ) -.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] ) -.multiply( boundUniform.targetNode.bindMatrix ); -} -break; -default : -console.warn( "Unhandled shader semantic: " + boundUniform.semantic ); -break; -} -} -}; -/* ANIMATION */ -GLTFLoader.Animations = { -update: function () { -console.warn( 'THREE.GLTFLoader.Animation has been deprecated. Use THREE.AnimationMixer instead.' ); -} -}; -/*********************************/ -/********** EXTENSIONS ***********/ -/*********************************/ -var EXTENSIONS = { -KHR_BINARY_GLTF: 'KHR_binary_glTF', -KHR_MATERIALS_COMMON: 'KHR_materials_common' -}; -/* MATERIALS COMMON EXTENSION */ -function GLTFMaterialsCommonExtension( json ) { -this.name = EXTENSIONS.KHR_MATERIALS_COMMON; -this.lights = {}; -var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {}; -var lights = extension.lights || {}; -for ( var lightId in lights ) { -var light = lights[ lightId ]; -var lightNode; -var lightParams = light[ light.type ]; -var color = new THREE.Color().fromArray( lightParams.color ); -switch ( light.type ) { -case "directional": -lightNode = new THREE.DirectionalLight( color ); -lightNode.position.set( 0, 0, 1 ); -break; -case "point": -lightNode = new THREE.PointLight( color ); -break; -case "spot": -lightNode = new THREE.SpotLight( color ); -lightNode.position.set( 0, 0, 1 ); -break; -case "ambient": -lightNode = new THREE.AmbientLight( color ); -break; -} -if ( lightNode ) { -this.lights[ lightId ] = lightNode; -} -} -} -/* BINARY EXTENSION */ -var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF'; -var BINARY_EXTENSION_HEADER_DEFAULTS = { magic: 'glTF', version: 1, contentFormat: 0 }; -var BINARY_EXTENSION_HEADER_LENGTH = 20; -function GLTFBinaryExtension( data ) { -this.name = EXTENSIONS.KHR_BINARY_GLTF; -var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); -var header = { -magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ), -version: headerView.getUint32( 4, true ), -length: headerView.getUint32( 8, true ), -contentLength: headerView.getUint32( 12, true ), -contentFormat: headerView.getUint32( 16, true ) -}; -for ( var key in BINARY_EXTENSION_HEADER_DEFAULTS ) { -var value = BINARY_EXTENSION_HEADER_DEFAULTS[ key ]; -if ( header[ key ] !== value ) { -throw new Error( 'Unsupported glTF-Binary header: Expected "%s" to be "%s".', key, value ); -} -} -var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH, header.contentLength ); -this.header = header; -this.content = convertUint8ArrayToString( contentArray ); -this.body = data.slice( BINARY_EXTENSION_HEADER_LENGTH + header.contentLength, header.length ); -} -GLTFBinaryExtension.prototype.loadShader = function ( shader, bufferViews ) { -var bufferView = bufferViews[ shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].bufferView ]; -var array = new Uint8Array( bufferView ); -return convertUint8ArrayToString( array ); -}; -GLTFBinaryExtension.prototype.loadTextureSourceUri = function ( source, bufferViews ) { -var metadata = source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ]; -var bufferView = bufferViews[ metadata.bufferView ]; -var stringData = convertUint8ArrayToString( new Uint8Array( bufferView ) ); -return 'data:' + metadata.mimeType + ';base64,' + btoa( stringData ); -}; -/*********************************/ -/********** INTERNALS ************/ -/*********************************/ -/* CONSTANTS */ -var WEBGL_CONSTANTS = { -FLOAT: 5126, -FLOAT_MAT3: 35675, -FLOAT_MAT4: 35676, -FLOAT_VEC2: 35664, -FLOAT_VEC3: 35665, -FLOAT_VEC4: 35666, -LINEAR: 9729, -REPEAT: 10497, -SAMPLER_2D: 35678, -TRIANGLES: 4, -LINES: 1, -UNSIGNED_BYTE: 5121, -UNSIGNED_SHORT: 5123, -VERTEX_SHADER: 35633, -FRAGMENT_SHADER: 35632 -}; -var WEBGL_TYPE = { -5126: Number, -35675: THREE.Matrix3, -35676: THREE.Matrix4, -35664: THREE.Vector2, -35665: THREE.Vector3, -35666: THREE.Vector4, -35678: THREE.Texture -}; -var WEBGL_COMPONENT_TYPES = { -5120: Int8Array, -5121: Uint8Array, -5122: Int16Array, -5123: Uint16Array, -5125: Uint32Array, -5126: Float32Array -}; -var WEBGL_FILTERS = { -9728: THREE.NearestFilter, -9729: THREE.LinearFilter, -9984: THREE.NearestMipMapNearestFilter, -9985: THREE.LinearMipMapNearestFilter, -9986: THREE.NearestMipMapLinearFilter, -9987: THREE.LinearMipMapLinearFilter -}; -var WEBGL_WRAPPINGS = { -33071: THREE.ClampToEdgeWrapping, -33648: THREE.MirroredRepeatWrapping, -10497: THREE.RepeatWrapping -}; -var WEBGL_TEXTURE_FORMATS = { -6406: THREE.AlphaFormat, -6407: THREE.RGBFormat, -6408: THREE.RGBAFormat, -6409: THREE.LuminanceFormat, -6410: THREE.LuminanceAlphaFormat -}; -var WEBGL_TEXTURE_DATATYPES = { -5121: THREE.UnsignedByteType, -32819: THREE.UnsignedShort4444Type, -32820: THREE.UnsignedShort5551Type, -33635: THREE.UnsignedShort565Type -}; -var WEBGL_SIDES = { -1028: THREE.BackSide, // Culling front -1029: THREE.FrontSide // Culling back -}; -var WEBGL_DEPTH_FUNCS = { -512: THREE.NeverDepth, -513: THREE.LessDepth, -514: THREE.EqualDepth, -515: THREE.LessEqualDepth, -516: THREE.GreaterEqualDepth, -517: THREE.NotEqualDepth, -518: THREE.GreaterEqualDepth, -519: THREE.AlwaysDepth -}; -var WEBGL_BLEND_EQUATIONS = { -32774: THREE.AddEquation, -32778: THREE.SubtractEquation, -32779: THREE.ReverseSubtractEquation -}; -var WEBGL_BLEND_FUNCS = { -0: THREE.ZeroFactor, -1: THREE.OneFactor, -768: THREE.SrcColorFactor, -769: THREE.OneMinusSrcColorFactor, -770: THREE.SrcAlphaFactor, -771: THREE.OneMinusSrcAlphaFactor, -772: THREE.DstAlphaFactor, -773: THREE.OneMinusDstAlphaFactor, -774: THREE.DstColorFactor, -775: THREE.OneMinusDstColorFactor, -776: THREE.SrcAlphaSaturateFactor -}; -var WEBGL_TYPE_SIZES = { -'SCALAR': 1, -'VEC2': 2, -'VEC3': 3, -'VEC4': 4, -'MAT2': 4, -'MAT3': 9, -'MAT4': 16 -}; -var PATH_PROPERTIES = { -scale: 'scale', -translation: 'position', -rotation: 'quaternion' -}; -var INTERPOLATION = { -LINEAR: THREE.InterpolateLinear, -STEP: THREE.InterpolateDiscrete -}; -var STATES_ENABLES = { -2884: 'CULL_FACE', -2929: 'DEPTH_TEST', -3042: 'BLEND', -3089: 'SCISSOR_TEST', -32823: 'POLYGON_OFFSET_FILL', -32926: 'SAMPLE_ALPHA_TO_COVERAGE' -}; -/* UTILITY FUNCTIONS */ -function _each( object, callback, thisObj ) { -if ( !object ) { -return Promise.resolve(); -} -var results; -var fns = []; -if ( Object.prototype.toString.call( object ) === '[object Array]' ) { -results = []; -var length = object.length; -for ( var idx = 0; idx < length; idx ++ ) { -var value = callback.call( thisObj || this, object[ idx ], idx ); -if ( value ) { -fns.push( value ); -if ( value instanceof Promise ) { -value.then( function( key, value ) { -results[ key ] = value; -}.bind( this, idx )); -} else { -results[ idx ] = value; -} -} -} -} else { -results = {}; -for ( var key in object ) { -if ( object.hasOwnProperty( key ) ) { -var value = callback.call( thisObj || this, object[ key ], key ); -if ( value ) { -fns.push( value ); -if ( value instanceof Promise ) { -value.then( function( key, value ) { -results[ key ] = value; -}.bind( this, key )); -} else { -results[ key ] = value; -} -} -} -} -} -return Promise.all( fns ).then( function() { -return results; -}); -} -function resolveURL( url, path ) { -if ( typeof url !== 'string' || url === '' ) -return ''; -if ( /^(https?:)?\/\//i.test( url ) ) { -return url; -} -if ( /^data:.*,.*$/i.test( url ) ) { -return url; -} -return ( path || '' ) + url; -} -function convertUint8ArrayToString( array ) { -var s = ''; -for ( var i = 0; i < array.length; i ++ ) { -s += String.fromCharCode( array[ i ] ); -} -return s; -} -function replaceTHREEShaderAttributes( shaderText, technique ) { -var attributes = {}; -for ( var attributeId in technique.attributes ) { -var pname = technique.attributes[ attributeId ]; -var param = technique.parameters[ pname ]; -var atype = param.type; -var semantic = param.semantic; -attributes[ attributeId ] = { -type: atype, -semantic: semantic -}; -} -var shaderParams = technique.parameters; -var shaderAttributes = technique.attributes; -var params = {}; -for ( var attributeId in attributes ) { -var pname = shaderAttributes[ attributeId ]; -var shaderParam = shaderParams[ pname ]; -var semantic = shaderParam.semantic; -if ( semantic ) { -params[ attributeId ] = shaderParam; -} -} -for ( var pname in params ) { -var param = params[ pname ]; -var semantic = param.semantic; -var regEx = new RegExp( "\\b" + pname + "\\b", "g" ); -switch ( semantic ) { -case "POSITION": -shaderText = shaderText.replace( regEx, 'position' ); -break; -case "NORMAL": -shaderText = shaderText.replace( regEx, 'normal' ); -break; -case 'TEXCOORD_0': -case 'TEXCOORD0': -case 'TEXCOORD': -shaderText = shaderText.replace( regEx, 'uv' ); -break; -case 'TEXCOORD_1': -shaderText = shaderText.replace( regEx, 'uv2' ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -shaderText = shaderText.replace( regEx, 'color' ); -break; -case "WEIGHT": -shaderText = shaderText.replace( regEx, 'skinWeight' ); -break; -case "JOINT": -shaderText = shaderText.replace( regEx, 'skinIndex' ); -break; -} -} -return shaderText; -} -function createDefaultMaterial() { -return new THREE.MeshPhongMaterial( { -color: 0x00000, -emissive: 0x888888, -specular: 0x000000, -shininess: 0, -transparent: false, -depthTest: true, -side: THREE.FrontSide -} ); -} -function DeferredShaderMaterial( params ) { -this.isDeferredShaderMaterial = true; -this.params = params; -} -DeferredShaderMaterial.prototype.create = function () { -var uniforms = THREE.UniformsUtils.clone( this.params.uniforms ); -for ( var uniformId in this.params.uniforms ) { -var originalUniform = this.params.uniforms[ uniformId ]; -if ( originalUniform.value instanceof THREE.Texture ) { -uniforms[ uniformId ].value = originalUniform.value; -uniforms[ uniformId ].value.needsUpdate = true; -} -uniforms[ uniformId ].semantic = originalUniform.semantic; -uniforms[ uniformId ].node = originalUniform.node; -} -this.params.uniforms = uniforms; -return new THREE.RawShaderMaterial( this.params ); -}; -/* GLTF PARSER */ -function GLTFParser( json, extensions, options ) { -this.json = json || {}; -this.extensions = extensions || {}; -this.options = options || {}; -this.cache = new GLTFRegistry(); -} -GLTFParser.prototype._withDependencies = function ( dependencies ) { -var _dependencies = {}; -for ( var i = 0; i < dependencies.length; i ++ ) { -var dependency = dependencies[ i ]; -var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 ); -var cached = this.cache.get( dependency ); -if ( cached !== undefined ) { -_dependencies[ dependency ] = cached; -} else if ( this[ fnName ] ) { -var fn = this[ fnName ](); -this.cache.add( dependency, fn ); -_dependencies[ dependency ] = fn; -} -} -return _each( _dependencies, function ( dependency ) { -return dependency; -} ); -}; -GLTFParser.prototype.parse = function ( callback ) { -var json = this.json; -this.cache.removeAll(); -this._withDependencies( [ -"scenes", -"cameras", -"animations" -] ).then( function ( dependencies ) { -var scenes = []; -for ( var name in dependencies.scenes ) { -scenes.push( dependencies.scenes[ name ] ); -} -var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ]; -var cameras = []; -for ( var name in dependencies.cameras ) { -var camera = dependencies.cameras[ name ]; -cameras.push( camera ); -} -var animations = []; -for ( var name in dependencies.animations ) { -animations.push( dependencies.animations[ name ] ); -} -callback( scene, scenes, cameras, animations ); -} ); -}; -GLTFParser.prototype.loadShaders = function () { -var json = this.json; -var extensions = this.extensions; -var options = this.options; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.shaders, function ( shader ) { -if ( shader.extensions && shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) { -return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadShader( shader, dependencies.bufferViews ); -} -return new Promise( function ( resolve ) { -var loader = new THREE.FileLoader(); -loader.setResponseType( 'text' ); -loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) { -resolve( shaderText ); -} ); -} ); -} ); -} ); -}; -GLTFParser.prototype.loadBuffers = function () { -var json = this.json; -var extensions = this.extensions; -var options = this.options; -return _each( json.buffers, function ( buffer, name ) { -if ( name === BINARY_EXTENSION_BUFFER_NAME ) { -return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body; -} -if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) { -return new Promise( function ( resolve ) { -var loader = new THREE.FileLoader(); -loader.setResponseType( 'arraybuffer' ); -loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) { -resolve( buffer ); -} ); -} ); -} else { -console.warn( 'THREE.GLTFLoader: ' + buffer.type + ' buffer type is not supported' ); -} -} ); -}; -GLTFParser.prototype.loadBufferViews = function () { -var json = this.json; -return this._withDependencies( [ -"buffers" -] ).then( function ( dependencies ) { -return _each( json.bufferViews, function ( bufferView ) { -var arraybuffer = dependencies.buffers[ bufferView.buffer ]; -var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0; -return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength ); -} ); -} ); -}; -GLTFParser.prototype.loadAccessors = function () { -var json = this.json; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.accessors, function ( accessor ) { -var arraybuffer = dependencies.bufferViews[ accessor.bufferView ]; -var itemSize = WEBGL_TYPE_SIZES[ accessor.type ]; -var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ]; -var elementBytes = TypedArray.BYTES_PER_ELEMENT; -var itemBytes = elementBytes * itemSize; -if ( accessor.byteStride && accessor.byteStride !== itemBytes ) { -var array = new TypedArray( arraybuffer ); -var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes ); -return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes ); -} else { -array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize ); -return new THREE.BufferAttribute( array, itemSize ); -} -} ); -} ); -}; -GLTFParser.prototype.loadTextures = function () { -var json = this.json; -var extensions = this.extensions; -var options = this.options; -return this._withDependencies( [ -"bufferViews" -] ).then( function ( dependencies ) { -return _each( json.textures, function ( texture ) { -if ( texture.source ) { -return new Promise( function ( resolve ) { -var source = json.images[ texture.source ]; -var sourceUri = source.uri; -if ( source.extensions && source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) { -sourceUri = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadTextureSourceUri( source, dependencies.bufferViews ); -} -var textureLoader = THREE.Loader.Handlers.get( sourceUri ); -if ( textureLoader === null ) { -textureLoader = new THREE.TextureLoader(); -} -textureLoader.setCrossOrigin( options.crossOrigin ); -textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) { -_texture.flipY = false; -if ( texture.name !== undefined ) _texture.name = texture.name; -_texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat; -if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) { -console.warn( 'THREE.GLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' + -'internalFormat will be forced to be the same value as format.' ); -} -_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType; -if ( texture.sampler ) { -var sampler = json.samplers[ texture.sampler ]; -_texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter; -_texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipMapLinearFilter; -_texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping; -_texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping; -} -resolve( _texture ); -}, undefined, function () { -resolve(); -} ); -} ); -} -} ); -} ); -}; -GLTFParser.prototype.loadMaterials = function () { -var json = this.json; -return this._withDependencies( [ -"shaders", -"textures" -] ).then( function ( dependencies ) { -return _each( json.materials, function ( material ) { -var materialType; -var materialValues = {}; -var materialParams = {}; -var khr_material; -if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) { -khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]; -} -if ( khr_material ) { -var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ]; -switch ( khr_material.technique ) { -case 'BLINN' : -case 'PHONG' : -materialType = THREE.MeshPhongMaterial; -keys.push( 'diffuse', 'specular', 'shininess' ); -break; -case 'LAMBERT' : -materialType = THREE.MeshLambertMaterial; -keys.push( 'diffuse' ); -break; -case 'CONSTANT' : -default : -materialType = THREE.MeshBasicMaterial; -break; -} -keys.forEach( function( v ) { -if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ]; -} ); -if ( khr_material.doubleSided || materialValues.doubleSided ) { -materialParams.side = THREE.DoubleSide; -} -if ( khr_material.transparent || materialValues.transparent ) { -materialParams.transparent = true; -materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1; -} -} else if ( material.technique === undefined ) { -materialType = THREE.MeshPhongMaterial; -Object.assign( materialValues, material.values ); -} else { -materialType = DeferredShaderMaterial; -var technique = json.techniques[ material.technique ]; -materialParams.uniforms = {}; -var program = json.programs[ technique.program ]; -if ( program ) { -materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ]; -if ( ! materialParams.fragmentShader ) { -console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader ); -materialType = THREE.MeshPhongMaterial; -} -var vertexShader = dependencies.shaders[ program.vertexShader ]; -if ( ! vertexShader ) { -console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader ); -materialType = THREE.MeshPhongMaterial; -} -materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique ); -var uniforms = technique.uniforms; -for ( var uniformId in uniforms ) { -var pname = uniforms[ uniformId ]; -var shaderParam = technique.parameters[ pname ]; -var ptype = shaderParam.type; -if ( WEBGL_TYPE[ ptype ] ) { -var pcount = shaderParam.count; -var value; -if ( material.values !== undefined ) value = material.values[ pname ]; -var uvalue = new WEBGL_TYPE[ ptype ](); -var usemantic = shaderParam.semantic; -var unode = shaderParam.node; -switch ( ptype ) { -case WEBGL_CONSTANTS.FLOAT: -uvalue = shaderParam.value; -if ( pname == "transparency" ) { -materialParams.transparent = true; -} -if ( value !== undefined ) { -uvalue = value; -} -break; -case WEBGL_CONSTANTS.FLOAT_VEC2: -case WEBGL_CONSTANTS.FLOAT_VEC3: -case WEBGL_CONSTANTS.FLOAT_VEC4: -case WEBGL_CONSTANTS.FLOAT_MAT3: -if ( shaderParam && shaderParam.value ) { -uvalue.fromArray( shaderParam.value ); -} -if ( value ) { -uvalue.fromArray( value ); -} -break; -case WEBGL_CONSTANTS.FLOAT_MAT2: -console.warn( "FLOAT_MAT2 is not a supported uniform type" ); -break; -case WEBGL_CONSTANTS.FLOAT_MAT4: -if ( pcount ) { -uvalue = new Array( pcount ); -for ( var mi = 0; mi < pcount; mi ++ ) { -uvalue[ mi ] = new WEBGL_TYPE[ ptype ](); -} -if ( shaderParam && shaderParam.value ) { -var m4v = shaderParam.value; -uvalue.fromArray( m4v ); -} -if ( value ) { -uvalue.fromArray( value ); -} -} else { -if ( shaderParam && shaderParam.value ) { -var m4 = shaderParam.value; -uvalue.fromArray( m4 ); -} -if ( value ) { -uvalue.fromArray( value ); -} -} -break; -case WEBGL_CONSTANTS.SAMPLER_2D: -if ( value !== undefined ) { -uvalue = dependencies.textures[ value ]; -} else if ( shaderParam.value !== undefined ) { -uvalue = dependencies.textures[ shaderParam.value ]; -} else { -uvalue = null; -} -break; -} -materialParams.uniforms[ uniformId ] = { -value: uvalue, -semantic: usemantic, -node: unode -}; -} else { -throw new Error( "Unknown shader uniform param type: " + ptype ); -} -} -var states = technique.states || {}; -var enables = states.enable || []; -var functions = states.functions || {}; -var enableCullFace = false; -var enableDepthTest = false; -var enableBlend = false; -for ( var i = 0, il = enables.length; i < il; i ++ ) { -var enable = enables[ i ]; -switch ( STATES_ENABLES[ enable ] ) { -case 'CULL_FACE': -enableCullFace = true; -break; -case 'DEPTH_TEST': -enableDepthTest = true; -break; -case 'BLEND': -enableBlend = true; -break; -case 'SCISSOR_TEST': -case 'POLYGON_OFFSET_FILL': -case 'SAMPLE_ALPHA_TO_COVERAGE': -break; -default: -throw new Error( "Unknown technique.states.enable: " + enable ); -} -} -if ( enableCullFace ) { -materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide; -} else { -materialParams.side = THREE.DoubleSide; -} -materialParams.depthTest = enableDepthTest; -materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth; -materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true; -materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending; -materialParams.transparent = enableBlend; -var blendEquationSeparate = functions.blendEquationSeparate; -if ( blendEquationSeparate !== undefined ) { -materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ]; -materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ]; -} else { -materialParams.blendEquation = THREE.AddEquation; -materialParams.blendEquationAlpha = THREE.AddEquation; -} -var blendFuncSeparate = functions.blendFuncSeparate; -if ( blendFuncSeparate !== undefined ) { -materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ]; -materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ]; -materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ]; -materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ]; -} else { -materialParams.blendSrc = THREE.OneFactor; -materialParams.blendDst = THREE.ZeroFactor; -materialParams.blendSrcAlpha = THREE.OneFactor; -materialParams.blendDstAlpha = THREE.ZeroFactor; -} -} -} -if ( Array.isArray( materialValues.diffuse ) ) { -materialParams.color = new THREE.Color().fromArray( materialValues.diffuse ); -} else if ( typeof( materialValues.diffuse ) === 'string' ) { -materialParams.map = dependencies.textures[ materialValues.diffuse ]; -} -delete materialParams.diffuse; -if ( typeof( materialValues.reflective ) === 'string' ) { -materialParams.envMap = dependencies.textures[ materialValues.reflective ]; -} -if ( typeof( materialValues.bump ) === 'string' ) { -materialParams.bumpMap = dependencies.textures[ materialValues.bump ]; -} -if ( Array.isArray( materialValues.emission ) ) { -if ( materialType === THREE.MeshBasicMaterial ) { -materialParams.color = new THREE.Color().fromArray( materialValues.emission ); -} else { -materialParams.emissive = new THREE.Color().fromArray( materialValues.emission ); -} -} else if ( typeof( materialValues.emission ) === 'string' ) { -if ( materialType === THREE.MeshBasicMaterial ) { -materialParams.map = dependencies.textures[ materialValues.emission ]; -} else { -materialParams.emissiveMap = dependencies.textures[ materialValues.emission ]; -} -} -if ( Array.isArray( materialValues.specular ) ) { -materialParams.specular = new THREE.Color().fromArray( materialValues.specular ); -} else if ( typeof( materialValues.specular ) === 'string' ) { -materialParams.specularMap = dependencies.textures[ materialValues.specular ]; -} -if ( materialValues.shininess !== undefined ) { -materialParams.shininess = materialValues.shininess; -} -var _material = new materialType( materialParams ); -if ( material.name !== undefined ) _material.name = material.name; -return _material; -} ); -} ); -}; -GLTFParser.prototype.loadMeshes = function () { -var json = this.json; -return this._withDependencies( [ -"accessors", -"materials" -] ).then( function ( dependencies ) { -return _each( json.meshes, function ( mesh ) { -var group = new THREE.Group(); -if ( mesh.name !== undefined ) group.name = mesh.name; -if ( mesh.extras ) group.userData = mesh.extras; -var primitives = mesh.primitives || []; -for ( var name in primitives ) { -var primitive = primitives[ name ]; -if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) { -var geometry = new THREE.BufferGeometry(); -var attributes = primitive.attributes; -for ( var attributeId in attributes ) { -var attributeEntry = attributes[ attributeId ]; -if ( ! attributeEntry ) return; -var bufferAttribute = dependencies.accessors[ attributeEntry ]; -switch ( attributeId ) { -case 'POSITION': -geometry.addAttribute( 'position', bufferAttribute ); -break; -case 'NORMAL': -geometry.addAttribute( 'normal', bufferAttribute ); -break; -case 'TEXCOORD_0': -case 'TEXCOORD0': -case 'TEXCOORD': -geometry.addAttribute( 'uv', bufferAttribute ); -break; -case 'TEXCOORD_1': -geometry.addAttribute( 'uv2', bufferAttribute ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -geometry.addAttribute( 'color', bufferAttribute ); -break; -case 'WEIGHT': -geometry.addAttribute( 'skinWeight', bufferAttribute ); -break; -case 'JOINT': -geometry.addAttribute( 'skinIndex', bufferAttribute ); -break; -} -} -if ( primitive.indices ) { -geometry.setIndex( dependencies.accessors[ primitive.indices ] ); -} -var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial(); -var meshNode = new THREE.Mesh( geometry, material ); -meshNode.castShadow = true; -meshNode.name = ( name === "0" ? group.name : group.name + name ); -if ( primitive.extras ) meshNode.userData = primitive.extras; -group.add( meshNode ); -} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) { -var geometry = new THREE.BufferGeometry(); -var attributes = primitive.attributes; -for ( var attributeId in attributes ) { -var attributeEntry = attributes[ attributeId ]; -if ( ! attributeEntry ) return; -var bufferAttribute = dependencies.accessors[ attributeEntry ]; -switch ( attributeId ) { -case 'POSITION': -geometry.addAttribute( 'position', bufferAttribute ); -break; -case 'COLOR_0': -case 'COLOR0': -case 'COLOR': -geometry.addAttribute( 'color', bufferAttribute ); -break; -} -} -var material = dependencies.materials[ primitive.material ]; -var meshNode; -if ( primitive.indices ) { -geometry.setIndex( dependencies.accessors[ primitive.indices ] ); -meshNode = new THREE.LineSegments( geometry, material ); -} else { -meshNode = new THREE.Line( geometry, material ); -} -meshNode.name = ( name === "0" ? group.name : group.name + name ); -if ( primitive.extras ) meshNode.userData = primitive.extras; -group.add( meshNode ); -} else { -console.warn( "Only triangular and line primitives are supported" ); -} -} -return group; -} ); -} ); -}; -GLTFParser.prototype.loadCameras = function () { -var json = this.json; -return _each( json.cameras, function ( camera ) { -if ( camera.type == "perspective" && camera.perspective ) { -var yfov = camera.perspective.yfov; -var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1; -var xfov = yfov * aspectRatio; -var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 ); -if ( camera.name !== undefined ) _camera.name = camera.name; -if ( camera.extras ) _camera.userData = camera.extras; -return _camera; -} else if ( camera.type == "orthographic" && camera.orthographic ) { -var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar ); -if ( camera.name !== undefined ) _camera.name = camera.name; -if ( camera.extras ) _camera.userData = camera.extras; -return _camera; -} -} ); -}; -GLTFParser.prototype.loadSkins = function () { -var json = this.json; -return this._withDependencies( [ -"accessors" -] ).then( function ( dependencies ) { -return _each( json.skins, function ( skin ) { -var bindShapeMatrix = new THREE.Matrix4(); -if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix ); -var _skin = { -bindShapeMatrix: bindShapeMatrix, -jointNames: skin.jointNames, -inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ] -}; -return _skin; -} ); -} ); -}; -GLTFParser.prototype.loadAnimations = function () { -var json = this.json; -return this._withDependencies( [ -"accessors", -"nodes" -] ).then( function ( dependencies ) { -return _each( json.animations, function ( animation, animationId ) { -var tracks = []; -for ( var channelId in animation.channels ) { -var channel = animation.channels[ channelId ]; -var sampler = animation.samplers[ channel.sampler ]; -if ( sampler ) { -var target = channel.target; -var name = target.id; -var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input; -var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output; -var inputAccessor = dependencies.accessors[ input ]; -var outputAccessor = dependencies.accessors[ output ]; -var node = dependencies.nodes[ name ]; -if ( node ) { -node.updateMatrix(); -node.matrixAutoUpdate = true; -var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation -? THREE.QuaternionKeyframeTrack -: THREE.VectorKeyframeTrack; -var targetName = node.name ? node.name : node.uuid; -var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear; -tracks.push( new TypedKeyframeTrack( -targetName + '.' + PATH_PROPERTIES[ target.path ], -THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ), -THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ), -interpolation -) ); -} -} -} -var name = animation.name !== undefined ? animation.name : "animation_" + animationId; -return new THREE.AnimationClip( name, undefined, tracks ); -} ); -} ); -}; -GLTFParser.prototype.loadNodes = function () { -var json = this.json; -var extensions = this.extensions; -var scope = this; -return _each( json.nodes, function ( node ) { -var matrix = new THREE.Matrix4(); -var _node; -if ( node.jointName ) { -_node = new THREE.Bone(); -_node.name = node.name !== undefined ? node.name : node.jointName; -_node.jointName = node.jointName; -} else { -_node = new THREE.Object3D(); -if ( node.name !== undefined ) _node.name = node.name; -} -if ( node.extras ) _node.userData = node.extras; -if ( node.matrix !== undefined ) { -matrix.fromArray( node.matrix ); -_node.applyMatrix( matrix ); -} else { -if ( node.translation !== undefined ) { -_node.position.fromArray( node.translation ); -} -if ( node.rotation !== undefined ) { -_node.quaternion.fromArray( node.rotation ); -} -if ( node.scale !== undefined ) { -_node.scale.fromArray( node.scale ); -} -} -return _node; -} ).then( function ( __nodes ) { -return scope._withDependencies( [ -"meshes", -"skins", -"cameras" -] ).then( function ( dependencies ) { -return _each( __nodes, function ( _node, nodeId ) { -var node = json.nodes[ nodeId ]; -if ( node.meshes !== undefined ) { -for ( var meshId in node.meshes ) { -var mesh = node.meshes[ meshId ]; -var group = dependencies.meshes[ mesh ]; -if ( group === undefined ) { -console.warn( 'GLTFLoader: Couldn\'t find node "' + mesh + '".' ); -continue; -} -for ( var childrenId in group.children ) { -var child = group.children[ childrenId ]; -var originalMaterial = child.material; -var originalGeometry = child.geometry; -var originalUserData = child.userData; -var originalName = child.name; -var material; -if ( originalMaterial.isDeferredShaderMaterial ) { -originalMaterial = material = originalMaterial.create(); -} else { -material = originalMaterial; -} -switch ( child.type ) { -case 'LineSegments': -child = new THREE.LineSegments( originalGeometry, material ); -break; -case 'LineLoop': -child = new THREE.LineLoop( originalGeometry, material ); -break; -case 'Line': -child = new THREE.Line( originalGeometry, material ); -break; -default: -child = new THREE.Mesh( originalGeometry, material ); -} -child.castShadow = true; -child.userData = originalUserData; -child.name = originalName; -var skinEntry; -if ( node.skin ) { -skinEntry = dependencies.skins[ node.skin ]; -} -if ( skinEntry ) { -var getJointNode = function ( jointId ) { -var keys = Object.keys( __nodes ); -for ( var i = 0, il = keys.length; i < il; i ++ ) { -var n = __nodes[ keys[ i ] ]; -if ( n.jointName === jointId ) return n; -} -return null; -}; -var geometry = originalGeometry; -var material = originalMaterial; -material.skinning = true; -child = new THREE.SkinnedMesh( geometry, material, false ); -child.castShadow = true; -child.userData = originalUserData; -child.name = originalName; -var bones = []; -var boneInverses = []; -for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) { -var jointId = skinEntry.jointNames[ i ]; -var jointNode = getJointNode( jointId ); -if ( jointNode ) { -bones.push( jointNode ); -var m = skinEntry.inverseBindMatrices.array; -var mat = new THREE.Matrix4().fromArray( m, i * 16 ); -boneInverses.push( mat ); -} else { -console.warn( "WARNING: joint: '" + jointId + "' could not be found" ); -} -} -child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix ); -var buildBoneGraph = function ( parentJson, parentObject, property ) { -var children = parentJson[ property ]; -if ( children === undefined ) return; -for ( var i = 0, il = children.length; i < il; i ++ ) { -var nodeId = children[ i ]; -var bone = __nodes[ nodeId ]; -var boneJson = json.nodes[ nodeId ]; -if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) { -parentObject.add( bone ); -buildBoneGraph( boneJson, bone, 'children' ); -} -} -}; -buildBoneGraph( node, child, 'skeletons' ); -} -_node.add( child ); -} -} -} -if ( node.camera !== undefined ) { -var camera = dependencies.cameras[ node.camera ]; -_node.add( camera ); -} -if ( node.extensions -&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] -&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) { -var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights; -var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ]; -_node.add( light ); -} -return _node; -} ); -} ); -} ); -}; -GLTFParser.prototype.loadScenes = function () { -var json = this.json; -function buildNodeHierachy( nodeId, parentObject, allNodes ) { -var _node = allNodes[ nodeId ]; -parentObject.add( _node ); -var node = json.nodes[ nodeId ]; -if ( node.children ) { -var children = node.children; -for ( var i = 0, l = children.length; i < l; i ++ ) { -var child = children[ i ]; -buildNodeHierachy( child, _node, allNodes ); -} -} -} -return this._withDependencies( [ -"nodes" -] ).then( function ( dependencies ) { -return _each( json.scenes, function ( scene ) { -var _scene = new THREE.Scene(); -if ( scene.name !== undefined ) _scene.name = scene.name; -if ( scene.extras ) _scene.userData = scene.extras; -var nodes = scene.nodes || []; -for ( var i = 0, l = nodes.length; i < l; i ++ ) { -var nodeId = nodes[ i ]; -buildNodeHierachy( nodeId, _scene, dependencies.nodes ); -} -_scene.traverse( function ( child ) { -if ( child.material && child.material.isRawShaderMaterial ) { -child.gltfShader = new GLTFShader( child, dependencies.nodes ); -child.onBeforeRender = function(renderer, scene, camera){ -this.gltfShader.update(scene, camera); -}; -} -} ); -return _scene; -} ); -} ); -}; -return GLTFLoader; -} )(); -"use strict"; -var JSONParser = function(scene) -{ -} -JSONParser.prototype.constructor = JSONParser; -/** -* Load X3D JSON into an element. -* jsobj - the JavaScript object to convert to DOM. -*/ -JSONParser.prototype.parseJavaScript = function(jsobj) { -var child = this.CreateElement('scene'); -this.ConvertToX3DOM(jsobj, "", child); -return child; -}; -/** -* Yet another way to set an attribute on an element. does not allow you to -* set JSON schema or encoding. -*/ -JSONParser.prototype.elementSetAttribute = function(element, key, value) { -if (key === 'SON schema') { -} else if (key === 'ncoding') { -} else { -if (typeof element.setAttribute === 'function') { -element.setAttribute(key, value); -} -} -}; -/** -* converts children of object to DOM. -*/ -JSONParser.prototype.ConvertChildren = function(parentkey, object, element) { -var key; -for (key in object) { -if (typeof object[key] === 'object') { -if (isNaN(parseInt(key))) { -this.ConvertObject(key, object, element, parentkey.substr(1)); -} else { -this.ConvertToX3DOM(object[key], key, element, parentkey.substr(1)); -} -} -} -}; -/** -* a method to create and element with tagnam key to DOM in a namespace. If -* containerField is set, then the containerField is set in the elemetn. -*/ -JSONParser.prototype.CreateElement = function(key, containerField) { -var child = document.createElement(key); -if (typeof containerField !== 'undefined') { -this.elementSetAttribute(child, 'containerField', containerField); -} -return child; -}; -/** -* a way to create a CDATA function or script in HTML, by using a DOM parser. -*/ -JSONParser.prototype.CDATACreateFunction = function(document, element, str) { -var y = str.replace(/\\"/g, "\\\"") -.replace(/</g, "<") -.replace(/>/g, ">") -.replace(/&/g, "&"); -do { -str = y; -y = str.replace(/'([^'\r\n]*)\n([^']*)'/g, "'$1\\n$2'"); -if (str !== y) { -console.log("CDATA Replacing",str,"with",y); -} -} while (y != str); -var domParser = new DOMParser(); -var cdataStr = ''; // has to be wrapped into an element -var scriptDoc = domParser .parseFromString (cdataStr, 'application/xml'); -var cdata = scriptDoc .children[0] .childNodes[1]; // space after script is childNode[0] -element .appendChild(cdata); -}; -/** -* convert the object at object[key] to DOM. -*/ -JSONParser.prototype.ConvertObject = function(key, object, element, containerField) { -var child; -if (object !== null && typeof object[key] === 'object') { -if (key.substr(0,1) === '@') { -this.ConvertToX3DOM(object[key], key, element); -} else if (key.substr(0,1) === '-') { -this.ConvertChildren(key, object[key], element); -} else if (key === '#comment') { -for (var c in object[key]) { -child = document.createComment(this.CommentStringToXML(object[key][c])); -element.appendChild(child); -} -} else if (key === '#text') { -child = document.createTextNode(object[key].join("")); -element.appendChild(child); -} else if (key === '#sourceText') { -this.CDATACreateFunction(document, element, object[key].join("\r\n")+"\r\n"); -} else { -if (key === 'connect' || key === 'fieldValue' || key === 'field' || key === 'meta' || key === 'component') { -for (var childkey in object[key]) { // for each field -if (typeof object[key][childkey] === 'object') { -child = this.CreateElement(key, containerField); -this.ConvertToX3DOM(object[key][childkey], childkey, child); -element.appendChild(child); -element.appendChild(document.createTextNode("\n")); -} -} -} else { -child = this.CreateElement(key, containerField); -this.ConvertToX3DOM(object[key], key, child); -element.appendChild(child); -element.appendChild(document.createTextNode("\n")); -} -} -} -}; -/** -* convert a comment string in JavaScript to XML. Pass the string -*/ -JSONParser.prototype.CommentStringToXML = function(str) { -var y = str; -str = str.replace(/\\\\/g, '\\'); -if (y !== str) { -console.log("X3DJSONLD replacing", y, "with", str); -} -return str; -}; -/** -* convert an SFString to XML. -*/ -JSONParser.prototype.SFStringToXML = function(str) { -var y = str; -/* -str = (""+str).replace(/\\\\/g, '\\\\'); -str = str.replace(/\\\\\\\\/g, '\\\\'); -str = str.replace(/(\\+)"/g, '\\"'); -*/ -str = str.replace(/\\/g, '\\\\'); -str = str.replace(/"/g, '\\\"'); -if (y !== str) { -console.log("X3DJSONLD [] replacing", y, "with", str); -} -return str; -}; -/** -* convert a JSON String to XML. -*/ -JSONParser.prototype.JSONStringToXML = function(str) { -var y = str; -str = str.replace(/\\/g, '\\\\'); -str = str.replace(/\n/g, '\\n'); -if (y !== str) { -console.log("X3DJSONLD replacing", y, "with", str); -} -return str; -}; -/** -* main routine for converting a JavaScript object to DOM. -* object is the object to convert. -* parentkey is the key of the object in the parent. -* element is the parent element. -* containerField is a possible containerField. -*/ -JSONParser.prototype.ConvertToX3DOM = function(object, parentkey, element, containerField) { -var key; -var localArray = []; -var isArray = false; -var arrayOfStrings = false; -for (key in object) { -if (isNaN(parseInt(key))) { -isArray = false; -} else { -isArray = true; -} -if (isArray) { -if (typeof object[key] === 'number') { -localArray.push(object[key]); -} else if (typeof object[key] === 'string') { -localArray.push(object[key]); -arrayOfStrings = true; -} else if (typeof object[key] === 'boolean') { -localArray.push(object[key]); -} else if (typeof object[key] === 'object') { -/* -if (object[key] != null && typeof object[key].join === 'function') { -localArray.push(object[key].join(" ")); -} -*/ -this.ConvertToX3DOM(object[key], key, element); -} else if (typeof object[key] === 'undefined') { -} else { -console.error("Unknown type found in array "+typeof object[key]); -} -} else if (typeof object[key] === 'object') { -if (key === 'scene') { -this.ConvertToX3DOM(object[key], key, element); -} else { -this.ConvertObject(key, object, element); -} -} else if (typeof object[key] === 'number') { -this.elementSetAttribute(element, key.substr(1),object[key]); -} else if (typeof object[key] === 'string') { -if (key === '#comment') { -var child = document.createComment(this.CommentStringToXML(object[key])); -element.appendChild(child); -} else if (key === '#text') { -var child = document.createTextNode(object[key]); -element.appendChild(child); -} else { -this.elementSetAttribute(element, key.substr(1), this.JSONStringToXML(object[key])); -} -} else if (typeof object[key] === 'boolean') { -this.elementSetAttribute(element, key.substr(1),object[key]); -} else if (typeof object[key] === 'undefined') { -} else { -console.error("Unknown type found in object "+typeof object[key]); -console.error(object); -} -} -if (isArray) { -if (parentkey.substr(0,1) === '@') { -if (arrayOfStrings) { -arrayOfStrings = false; -for (var str in localArray) { -localArray[str] = this.SFStringToXML(localArray[str]); -} -this.elementSetAttribute(element, parentkey.substr(1),'"'+localArray.join('" "')+'"'); -} else { -this.elementSetAttribute(element, parentkey.substr(1),localArray.join(" ")); -} -} -isArray = false; -} -return element; -}; -/* -* For use with XSeen JavaScript Library -* http://tools.realism.com/... -* -* Licensed under MIT or GNU in the same manner as XSeen -* -* (C)2017 Daly Realiusm, Los Angeles -* -*/ -/* -* Manages all download requests. -* Requests are queued up and processed to the maximum limit (.MaxRequests) -* Use this for processing text (X3D, XML, JSON, HTML) files. -* Not really setup for binary files (.jpg, png, etc.) -* -* Requires jQuery -- should work on removing that... -* -*/ -function LoadManager () { -this.urlQueue = []; -this.urlNext = -1; -this.MaxRequests = 3; -this.totalRequests = 0; -this.totalResponses = 0; -this.requestCount = 0; -var lmThat = this; -this.load = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.loadText = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'text', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.loadHtml = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'html', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.loadXml = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'xml', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.loadJson = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'json', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.loadImage = function (url, success, progress, failed, userdata) { -this.urlQueue.push( {'url':url, 'type':'image', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); -this.loadNextUrl(); -} -this.success = function (response, string, xhr) { -if (typeof(xhr._loadManager.success) !== undefined) { -xhr._loadManager.success (response, xhr._loadManager.userdata, xhr); -} -} -this.failure = function (xhr, errorCode, errorText) { -if (typeof(xhr._loadManager.failure) !== undefined) { -xhr._loadManager.failure (xhr, xhr._loadManager.userdata, errorCode, errorText); -} -} -this.requestComplete = function (event, xhr, settings) { -lmThat.requestCount --; -lmThat.totalResponses++; -lmThat.loadNextUrl(); -} -this.loadNextUrl = function () { -if (this.requestCount >= this.MaxRequests) {return; } -if (this.urlNext >= this.urlQueue.length || this.urlNext < 0) { -this.urlNext = -1; -for (var i=0; i 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -break; -case Consts.CODE_SLASH: -slashes[ slashesPointer++ ] = i; -if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -break; -case Consts.CODE_LF: -if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ); -slashesPointer = 0; -bufferPointer = 0; -break; -case Consts.CODE_CR: -break; -default: -word += String.fromCharCode( code ); -break; -} -} -}; -/** -* Parse the provided text -* @memberOf Parser -* -* @param {string} text OBJ data as string -*/ -Parser.prototype.parseText = function ( text ) { -var length = text.length; -var buffer = new Array( 32 ); -var bufferPointer = 0; -var slashes = new Array( 32 ); -var slashesPointer = 0; -var reachedFaces = false; -var char; -var word = ''; -for ( var i = 0; i < length; i++ ) { -char = text[ i ]; -switch ( char ) { -case Consts.STRING_SPACE: -if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -break; -case Consts.STRING_SLASH: -slashes[ slashesPointer++ ] = i; -if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -break; -case Consts.STRING_LF: -if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; -word = ''; -reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ); -slashesPointer = 0; -bufferPointer = 0; -break; -case Consts.STRING_CR: -break; -default: -word += char; -} -} -}; -Parser.prototype.processLine = function ( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ) { -if ( bufferPointer < 1 ) return reachedFaces; -var bufferLength = bufferPointer - 1; -switch ( buffer[ 0 ] ) { -case Consts.LINE_V: -if ( reachedFaces ) { -this.processCompletedObject( null, this.rawObject.groupName ); -reachedFaces = false; -} -this.rawObject.pushVertex( buffer ); -break; -case Consts.LINE_VT: -this.rawObject.pushUv( buffer ); -break; -case Consts.LINE_VN: -this.rawObject.pushNormal( buffer ); -break; -case Consts.LINE_F: -reachedFaces = true; -/* -* 0: "f vertex/uv/normal ..." -* 1: "f vertex/uv ..." -* 2: "f vertex//normal ..." -* 3: "f vertex ..." -*/ -var haveQuad = bufferLength % 4 === 0; -if ( slashesPointer > 1 && ( slashes[ 1 ] - slashes[ 0 ] ) === 1 ) { -if ( haveQuad ) { -this.rawObject.buildQuadVVn( buffer ); -} else { -this.rawObject.buildFaceVVn( buffer ); -} -} else if ( bufferLength === slashesPointer * 2 ) { -if ( haveQuad ) { -this.rawObject.buildQuadVVt( buffer ); -} else { -this.rawObject.buildFaceVVt( buffer ); -} -} else if ( bufferLength * 2 === slashesPointer * 3 ) { -if ( haveQuad ) { -this.rawObject.buildQuadVVtVn( buffer ); -} else { -this.rawObject.buildFaceVVtVn( buffer ); -} -} else { -if ( haveQuad ) { -this.rawObject.buildQuadV( buffer ); -} else { -this.rawObject.buildFaceV( buffer ); -} -} -break; -case Consts.LINE_L: -if ( bufferLength === slashesPointer * 2 ) { -this.rawObject.buildLineVvt( buffer ); -} else { -this.rawObject.buildLineV( buffer ); -} -break; -case Consts.LINE_S: -this.rawObject.pushSmoothingGroup( buffer[ 1 ] ); -break; -case Consts.LINE_G: -this.processCompletedGroup( buffer[ 1 ] ); -break; -case Consts.LINE_O: -if ( this.rawObject.vertices.length > 0 ) { -this.processCompletedObject( buffer[ 1 ], null ); -reachedFaces = false; -} else { -this.rawObject.pushObject( buffer[ 1 ] ); -} -break; -case Consts.LINE_MTLLIB: -this.rawObject.pushMtllib( buffer[ 1 ] ); -break; -case Consts.LINE_USEMTL: -this.rawObject.pushUsemtl( buffer[ 1 ] ); -break; -default: -break; -} -return reachedFaces; -}; -Parser.prototype.processCompletedObject = function ( objectName, groupName ) { -this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); -this.inputObjectCount++; -this.rawObject = this.rawObject.newInstanceFromObject( objectName, groupName ); -}; -Parser.prototype.processCompletedGroup = function ( groupName ) { -var notEmpty = this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); -if ( notEmpty ) { -this.inputObjectCount ++; -this.rawObject = this.rawObject.newInstanceFromGroup( groupName ); -} else { -this.rawObject.pushGroup( groupName ); -} -}; -Parser.prototype.finalize = function () { -this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); -this.inputObjectCount++; -}; -return Parser; -})(); -/** -* {@link RawObject} is only used by {@link Parser}. -* The user of OBJLoader2 does not need to care about this class. -* It is defined publicly for inclusion in web worker based OBJ loader ({@link THREE.OBJLoader2.WWOBJLoader2}) -*/ -var RawObject = (function () { -function RawObject( objectName, groupName, mtllibName ) { -this.globalVertexOffset = 1; -this.globalUvOffset = 1; -this.globalNormalOffset = 1; -this.vertices = []; -this.normals = []; -this.uvs = []; -this.mtllibName = Validator.verifyInput( mtllibName, 'none' ); -this.objectName = Validator.verifyInput( objectName, 'none' ); -this.groupName = Validator.verifyInput( groupName, 'none' ); -this.activeMtlName = 'none'; -this.activeSmoothingGroup = 1; -this.mtlCount = 0; -this.smoothingGroupCount = 0; -this.rawObjectDescriptions = []; -var index = this.buildIndex( this.activeMtlName, this.activeSmoothingGroup ); -this.rawObjectDescriptionInUse = new RawObjectDescription( this.objectName, this.groupName, this.activeMtlName, this.activeSmoothingGroup ); -this.rawObjectDescriptions[ index ] = this.rawObjectDescriptionInUse; -} -RawObject.prototype.buildIndex = function ( materialName, smoothingGroup) { -return materialName + '|' + smoothingGroup; -}; -RawObject.prototype.newInstanceFromObject = function ( objectName, groupName ) { -var newRawObject = new RawObject( objectName, groupName, this.mtllibName ); -newRawObject.globalVertexOffset = this.globalVertexOffset + this.vertices.length / 3; -newRawObject.globalUvOffset = this.globalUvOffset + this.uvs.length / 2; -newRawObject.globalNormalOffset = this.globalNormalOffset + this.normals.length / 3; -return newRawObject; -}; -RawObject.prototype.newInstanceFromGroup = function ( groupName ) { -var newRawObject = new RawObject( this.objectName, groupName, this.mtllibName ); -newRawObject.vertices = this.vertices; -newRawObject.uvs = this.uvs; -newRawObject.normals = this.normals; -newRawObject.globalVertexOffset = this.globalVertexOffset; -newRawObject.globalUvOffset = this.globalUvOffset; -newRawObject.globalNormalOffset = this.globalNormalOffset; -return newRawObject; -}; -RawObject.prototype.pushVertex = function ( buffer ) { -this.vertices.push( parseFloat( buffer[ 1 ] ) ); -this.vertices.push( parseFloat( buffer[ 2 ] ) ); -this.vertices.push( parseFloat( buffer[ 3 ] ) ); -}; -RawObject.prototype.pushUv = function ( buffer ) { -this.uvs.push( parseFloat( buffer[ 1 ] ) ); -this.uvs.push( parseFloat( buffer[ 2 ] ) ); -}; -RawObject.prototype.pushNormal = function ( buffer ) { -this.normals.push( parseFloat( buffer[ 1 ] ) ); -this.normals.push( parseFloat( buffer[ 2 ] ) ); -this.normals.push( parseFloat( buffer[ 3 ] ) ); -}; -RawObject.prototype.pushObject = function ( objectName ) { -this.objectName = objectName; -}; -RawObject.prototype.pushMtllib = function ( mtllibName ) { -this.mtllibName = mtllibName; -}; -RawObject.prototype.pushGroup = function ( groupName ) { -this.groupName = groupName; -this.verifyIndex(); -}; -RawObject.prototype.pushUsemtl = function ( mtlName ) { -if ( this.activeMtlName === mtlName || ! Validator.isValid( mtlName ) ) return; -this.activeMtlName = mtlName; -this.mtlCount++; -this.verifyIndex(); -}; -RawObject.prototype.pushSmoothingGroup = function ( activeSmoothingGroup ) { -var normalized = activeSmoothingGroup === 'off' ? 0 : activeSmoothingGroup; -if ( this.activeSmoothingGroup === normalized ) return; -this.activeSmoothingGroup = normalized; -this.smoothingGroupCount++; -this.verifyIndex(); -}; -RawObject.prototype.verifyIndex = function () { -var index = this.buildIndex( this.activeMtlName, ( this.activeSmoothingGroup === 0 ) ? 0 : 1 ); -this.rawObjectDescriptionInUse = this.rawObjectDescriptions[ index ]; -if ( ! Validator.isValid( this.rawObjectDescriptionInUse ) ) { -this.rawObjectDescriptionInUse = new RawObjectDescription( this.objectName, this.groupName, this.activeMtlName, this.activeSmoothingGroup ); -this.rawObjectDescriptions[ index ] = this.rawObjectDescriptionInUse; -} -}; -RawObject.prototype.buildQuadVVtVn = function ( indexArray ) { -for ( var i = 0; i < 6; i ++ ) { -this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_3[ i ] ] ); -this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_3[ i ] + 1 ] ); -this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_3[ i ] + 2 ] ); -} -}; -RawObject.prototype.buildQuadVVt = function ( indexArray ) { -for ( var i = 0; i < 6; i ++ ) { -this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] ); -this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] ); -} -}; -RawObject.prototype.buildQuadVVn = function ( indexArray ) { -for ( var i = 0; i < 6; i ++ ) { -this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] ); -this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] ); -} -}; -RawObject.prototype.buildQuadV = function ( indexArray ) { -for ( var i = 0; i < 6; i ++ ) { -this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_1[ i ] ] ); -} -}; -RawObject.prototype.buildFaceVVtVn = function ( indexArray ) { -for ( var i = 1; i < 10; i += 3 ) { -this.attachFaceV_( indexArray[ i ] ); -this.attachFaceVt( indexArray[ i + 1 ] ); -this.attachFaceVn( indexArray[ i + 2 ] ); -} -}; -RawObject.prototype.buildFaceVVt = function ( indexArray ) { -for ( var i = 1; i < 7; i += 2 ) { -this.attachFaceV_( indexArray[ i ] ); -this.attachFaceVt( indexArray[ i + 1 ] ); -} -}; -RawObject.prototype.buildFaceVVn = function ( indexArray ) { -for ( var i = 1; i < 7; i += 2 ) { -this.attachFaceV_( indexArray[ i ] ); -this.attachFaceVn( indexArray[ i + 1 ] ); -} -}; -RawObject.prototype.buildFaceV = function ( indexArray ) { -for ( var i = 1; i < 4; i ++ ) { -this.attachFaceV_( indexArray[ i ] ); -} -}; -RawObject.prototype.attachFaceV_ = function ( faceIndex ) { -var faceIndexInt = parseInt( faceIndex ); -var index = ( faceIndexInt - this.globalVertexOffset ) * 3; -var rodiu = this.rawObjectDescriptionInUse; -rodiu.vertices.push( this.vertices[ index++ ] ); -rodiu.vertices.push( this.vertices[ index++ ] ); -rodiu.vertices.push( this.vertices[ index ] ); -}; -RawObject.prototype.attachFaceVt = function ( faceIndex ) { -var faceIndexInt = parseInt( faceIndex ); -var index = ( faceIndexInt - this.globalUvOffset ) * 2; -var rodiu = this.rawObjectDescriptionInUse; -rodiu.uvs.push( this.uvs[ index++ ] ); -rodiu.uvs.push( this.uvs[ index ] ); -}; -RawObject.prototype.attachFaceVn = function ( faceIndex ) { -var faceIndexInt = parseInt( faceIndex ); -var index = ( faceIndexInt - this.globalNormalOffset ) * 3; -var rodiu = this.rawObjectDescriptionInUse; -rodiu.normals.push( this.normals[ index++ ] ); -rodiu.normals.push( this.normals[ index++ ] ); -rodiu.normals.push( this.normals[ index ] ); -}; -/* -* Support for lines with or without texture. irst element in indexArray is the line identification -* 0: "f vertex/uv vertex/uv ..." -* 1: "f vertex vertex ..." -*/ -RawObject.prototype.buildLineVvt = function ( lineArray ) { -var length = lineArray.length; -for ( var i = 1; i < length; i ++ ) { -this.vertices.push( parseInt( lineArray[ i ] ) ); -this.uvs.push( parseInt( lineArray[ i ] ) ); -} -}; -RawObject.prototype.buildLineV = function ( lineArray ) { -var length = lineArray.length; -for ( var i = 1; i < length; i++ ) { -this.vertices.push( parseInt( lineArray[ i ] ) ); -} -}; -/** -* Clear any empty rawObjectDescription and calculate absolute vertex, normal and uv counts -*/ -RawObject.prototype.finalize = function ( meshCreator, inputObjectCount, debug ) { -var temp = this.rawObjectDescriptions; -this.rawObjectDescriptions = []; -var rawObjectDescription; -var index = 0; -var absoluteVertexCount = 0; -var absoluteNormalCount = 0; -var absoluteUvCount = 0; -for ( var name in temp ) { -rawObjectDescription = temp[ name ]; -if ( rawObjectDescription.vertices.length > 0 ) { -if ( rawObjectDescription.objectName === 'none' ) rawObjectDescription.objectName = rawObjectDescription.groupName; -this.rawObjectDescriptions[ index++ ] = rawObjectDescription; -absoluteVertexCount += rawObjectDescription.vertices.length; -absoluteUvCount += rawObjectDescription.uvs.length; -absoluteNormalCount += rawObjectDescription.normals.length; -} -} -var notEmpty = false; -if ( index > 0 ) { -if ( debug ) this.createReport( inputObjectCount, true ); -meshCreator.buildMesh( -this.rawObjectDescriptions, -inputObjectCount, -absoluteVertexCount, -absoluteNormalCount, -absoluteUvCount -); -notEmpty = true; -} -return notEmpty; -}; -RawObject.prototype.createReport = function ( inputObjectCount, printDirectly ) { -var report = { -name: this.objectName ? this.objectName : 'groups', -mtllibName: this.mtllibName, -vertexCount: this.vertices.length / 3, -normalCount: this.normals.length / 3, -uvCount: this.uvs.length / 2, -smoothingGroupCount: this.smoothingGroupCount, -mtlCount: this.mtlCount, -rawObjectDescriptions: this.rawObjectDescriptions.length -}; -if ( printDirectly ) { -console.log( 'Input Object number: ' + inputObjectCount + ' Object name: ' + report.name ); -console.log( 'Mtllib name: ' + report.mtllibName ); -console.log( 'Vertex count: ' + report.vertexCount ); -console.log( 'Normal count: ' + report.normalCount ); -console.log( 'UV count: ' + report.uvCount ); -console.log( 'SmoothingGroup count: ' + report.smoothingGroupCount ); -console.log( 'Material count: ' + report.mtlCount ); -console.log( 'Real RawObjectDescription count: ' + report.rawObjectDescriptions ); -console.log( '' ); -} -return report; -}; -return RawObject; -})(); -/** -* Descriptive information and data (vertices, normals, uvs) to passed on to mesh building function. -* @class -* -* @param {string} objectName Name of the mesh -* @param {string} groupName Name of the group -* @param {string} materialName Name of the material -* @param {number} smoothingGroup Normalized smoothingGroup (0: THREE.FlatShading, 1: THREE.SmoothShading) -*/ -var RawObjectDescription = (function () { -function RawObjectDescription( objectName, groupName, materialName, smoothingGroup ) { -this.objectName = objectName; -this.groupName = groupName; -this.materialName = materialName; -this.smoothingGroup = smoothingGroup; -this.vertices = []; -this.uvs = []; -this.normals = []; -} -return RawObjectDescription; -})(); -/** -* MeshCreator is used to transform RawObjectDescriptions to THREE.Mesh -* -* @class -*/ -var MeshCreator = (function () { -function MeshCreator() { -this.sceneGraphBaseNode = null; -this.materials = null; -this.debug = false; -this.globalObjectCount = 1; -this.validated = false; -} -MeshCreator.prototype.setSceneGraphBaseNode = function ( sceneGraphBaseNode ) { -this.sceneGraphBaseNode = Validator.verifyInput( sceneGraphBaseNode, this.sceneGraphBaseNode ); -this.sceneGraphBaseNode = Validator.verifyInput( this.sceneGraphBaseNode, new THREE.Group() ); -}; -MeshCreator.prototype.setMaterials = function ( materials ) { -this.materials = Validator.verifyInput( materials, this.materials ); -this.materials = Validator.verifyInput( this.materials, { materials: [] } ); -}; -MeshCreator.prototype.setDebug = function ( debug ) { -if ( debug === true || debug === false ) this.debug = debug; -}; -MeshCreator.prototype.validate = function () { -if ( this.validated ) return; -this.setSceneGraphBaseNode( null ); -this.setMaterials( null ); -this.setDebug( null ); -this.globalObjectCount = 1; -}; -MeshCreator.prototype.finalize = function () { -this.sceneGraphBaseNode = null; -this.materials = null; -this.validated = false; -}; -/** -* This is an internal function, but due to its importance to Parser it is documented. -* RawObjectDescriptions are transformed to THREE.Mesh. -* It is ensured that rawObjectDescriptions only contain objects with vertices (no need to check). -* This method shall be overridden by the web worker implementation -* -* @param {RawObjectDescription[]} rawObjectDescriptions Array of descriptive information and data (vertices, normals, uvs) about the parsed object(s) -* @param {number} inputObjectCount Number of objects already retrieved from OBJ -* @param {number} absoluteVertexCount Sum of all vertices of all rawObjectDescriptions -* @param {number} absoluteNormalCount Sum of all normals of all rawObjectDescriptions -* @param {number} absoluteUvCount Sum of all uvs of all rawObjectDescriptions -*/ -MeshCreator.prototype.buildMesh = function ( rawObjectDescriptions, inputObjectCount, absoluteVertexCount, absoluteNormalCount, absoluteUvCount ) { -if ( this.debug ) console.log( 'MeshCreator.buildRawMeshData:\nInput object no.: ' + inputObjectCount ); -var bufferGeometry = new THREE.BufferGeometry(); -var vertexBA = new THREE.BufferAttribute( new Float32Array( absoluteVertexCount ), 3 ); -bufferGeometry.addAttribute( 'position', vertexBA ); -var normalBA; -if ( absoluteNormalCount > 0 ) { -normalBA = new THREE.BufferAttribute( new Float32Array( absoluteNormalCount ), 3 ); -bufferGeometry.addAttribute( 'normal', normalBA ); -} -var uvBA; -if ( absoluteUvCount > 0 ) { -uvBA = new THREE.BufferAttribute( new Float32Array( absoluteUvCount ), 2 ); -bufferGeometry.addAttribute( 'uv', uvBA ); -} -if ( this.debug ) console.log( 'Creating Multi-Material for object no.: ' + this.globalObjectCount ); -var rawObjectDescription; -var material; -var materialName; -var createMultiMaterial = rawObjectDescriptions.length > 1; -var materials = []; -var materialIndex = 0; -var materialIndexMapping = []; -var selectedMaterialIndex; -var vertexBAOffset = 0; -var vertexGroupOffset = 0; -var vertexLength; -var normalOffset = 0; -var uvOffset = 0; -for ( var oodIndex in rawObjectDescriptions ) { -rawObjectDescription = rawObjectDescriptions[ oodIndex ]; -materialName = rawObjectDescription.materialName; -material = this.materials[ materialName ]; -if ( ! material ) { -material = this.materials[ 'defaultMaterial' ]; -if ( ! material ) { -material = new THREE.MeshStandardMaterial( { color: 0xDCF1FF} ); -material.name = 'defaultMaterial'; -this.materials[ 'defaultMaterial' ] = material; -} -console.warn( 'object_group "' + rawObjectDescription.objectName + '_' + rawObjectDescription.groupName + '" was defined without material! Assigning "defaultMaterial".' ); -} -if ( rawObjectDescription.smoothingGroup === 0 ) { -materialName = material.name + '_flat'; -var materialClone = this.materials[ materialName ]; -if ( ! materialClone ) { -materialClone = material.clone(); -materialClone.name = materialName; -materialClone.shading = THREE.FlatShading; -this.materials[ materialName ] = name; -} -} -vertexLength = rawObjectDescription.vertices.length; -if ( createMultiMaterial ) { -selectedMaterialIndex = materialIndexMapping[ materialName ]; -if ( ! selectedMaterialIndex ) { -selectedMaterialIndex = materialIndex; -materialIndexMapping[ materialName ] = materialIndex; -materials.push( material ); -materialIndex++; -} -bufferGeometry.addGroup( vertexGroupOffset, vertexLength / 3, selectedMaterialIndex ); -vertexGroupOffset += vertexLength / 3; -} -vertexBA.set( rawObjectDescription.vertices, vertexBAOffset ); -vertexBAOffset += vertexLength; -if ( normalBA ) { -normalBA.set( rawObjectDescription.normals, normalOffset ); -normalOffset += rawObjectDescription.normals.length; -} -if ( uvBA ) { -uvBA.set( rawObjectDescription.uvs, uvOffset ); -uvOffset += rawObjectDescription.uvs.length; -} -if ( this.debug ) this.printReport( rawObjectDescription, selectedMaterialIndex ); -} -if ( ! normalBA ) bufferGeometry.computeVertexNormals(); -if ( createMultiMaterial ) material = materials; -var mesh = new THREE.Mesh( bufferGeometry, material ); -this.sceneGraphBaseNode.add( mesh ); -this.globalObjectCount++; -}; -MeshCreator.prototype.printReport = function ( rawObjectDescription, selectedMaterialIndex ) { -console.log( -' Output Object no.: ' + this.globalObjectCount + -'\n objectName: ' + rawObjectDescription.objectName + -'\n groupName: ' + rawObjectDescription.groupName + -'\n materialName: ' + rawObjectDescription.materialName + -'\n materialIndex: ' + selectedMaterialIndex + -'\n smoothingGroup: ' + rawObjectDescription.smoothingGroup + -'\n #vertices: ' + rawObjectDescription.vertices.length / 3 + -'\n #uvs: ' + rawObjectDescription.uvs.length / 2 + -'\n #normals: ' + rawObjectDescription.normals.length / 3 -); -}; -return MeshCreator; -})(); -OBJLoader2.prototype._buildWebWorkerCode = function ( funcBuildObject, funcBuildSingelton ) { -var workerCode = ''; -workerCode += funcBuildObject( 'Consts', Consts ); -workerCode += funcBuildObject( 'Validator', Validator ); -workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser ); -workerCode += funcBuildSingelton( 'RawObject', 'RawObject', RawObject ); -workerCode += funcBuildSingelton( 'RawObjectDescription', 'RawObjectDescription', RawObjectDescription ); -return workerCode; -}; -return OBJLoader2; -})(); -/* -* XSeen JavaScript Library -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -* -* Based on code originally provided by -* Philip Taylor: http://philip.html5.org -*/ -/** -* The Namespace container for x3dom objects. -* @namespace x3dom -* -* Removed THREE loaders -loaders: { -'file' : new THREE.FileLoader(), -'image' : 0, -}, -* */ -var xseen = { -canvases : [], -sceneInfo : [], -nodeDefinitions : {}, -parseTable : {}, -node : {}, -utils : {}, -loadMgr : {}, -loader : { -'Null' : '', -'ColladaLoader' : '', -'GltfLegacy' : '', -'GltfLoader' : '', -'ObjLoader' : '', -'ImageLoader' : '', -'X3dLoader' : '', -}, -loadProgress : function (xhr) { -if (xhr.total != 0) { -console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); -} -}, -loadError : function (xhr, userdata, code, message) { -console.error('An error happened on '+userdata.e.id+'\n'+code+'\n'+message); -}, -loadMime : { -'' : {name: 'Null', loader: 'Null'}, -'dae' : {name: 'Collada', loader: 'ColladaLoader'}, -'glb' : {name: 'glTF Binary', loader: 'GltfLoader'}, -'glbl' : {name: 'glTF Binary', loader: 'GltfLegacy'}, -'gltf' : {name: 'glTF JSON', loader: 'GltfLoader'}, -'obj' : {name: 'OBJ', loader: 'ObjLoader'}, -'png' : {name: 'PNG', loader: 'ImageLoader'}, -'jpg' : {name: 'JPEG', loader: 'ImageLoader'}, -'jpeg' : {name: 'JPEG', loader: 'ImageLoader'}, -'gif' : {name: 'GIF', loader: 'ImageLoader'}, -'x3d' : {name: 'X3D XML', loader: 'X3dLoader'}, -}, -array_to_object : function (a) { -var o = {}; -for(var i=0;i ' + obj.type + ' (' + obj.name + ')'); -for (var i=0; i -var validParams = xseen.array_to_object([ -'showLog', -'showStat', -'showProgress', -'PrimitiveQuality', -'components', -'loadpath', -'disableDoubleClick', -'backend', -'altImg', -'runtimeEnabled', -'keysEnabled', -'showTouchpoints', -'disableTouch', -'maxActiveDownloads' -]); -var components, prefix; -var showLoggingConsole = false; -for (var i=0; i < xseens.length; i++) { -settings.setProperty("showLog", xseens[i].getAttribute("showLog") || 'false'); -settings.setProperty("showLog", xseens[i].getAttribute("showLog") || 'true'); -settings.setProperty("showStat", xseens[i].getAttribute("showStat") || 'false'); -settings.setProperty("showProgress", xseens[i].getAttribute("showProgress") || 'true'); -settings.setProperty("PrimitiveQuality", xseens[i].getAttribute("PrimitiveQuality") || 'High'); -params = xseens[i].getElementsByTagName('PARAM'); -for (var j=0; j < params.length; j++) { -if (params[j].getAttribute('name') in validParams) { -settings.setProperty(params[j].getAttribute('name'), params[j].getAttribute('value')); -} else { -} -} -if (settings.getProperty('showLog') === 'true') { -showLoggingConsole = true; -} -if (typeof X3DOM_SECURITY_OFF != 'undefined' && X3DOM_SECURITY_OFF === true) { -components = settings.getProperty('components', xseens[i].getAttribute("components")); -if (components) { -prefix = settings.getProperty('loadpath', xseens[i].getAttribute("loadpath")); -components = components.trim().split(','); -for (j=0; j < components.length; j++) { -xseen.loadJS(components[j] + ".js", prefix); -} -} -if (xseens[i].getAttribute("src")) { -var _scene = document.createElement("scene"); -var _inl = document.createElement("Inline"); -_inl.setAttribute("url", xseens[i].getAttribute("src")); -_scene.appendChild(_inl); -xseens[i].appendChild(_scene); -} -} -} -if (showLoggingConsole == true) { -xseen.debug.activate(true); -} else { -xseen.debug.activate(false); -} -/* Don't think so -- commented out -xseens = Array.map(xseens, function (n) { -n.hasRuntime = true; -return n; -}); -*/ -if (xseen.versionInfo !== undefined) { -xseen.debug.logInfo("XSeen version " + xseen.versionInfo.version + ", " + -"Date " + xseen.versionInfo.date); -xseen.debug.logInfo(xseen.versionInfo.splashText); -} -var x_element; -var x_canvas; -var altDiv, altP, aLnk, altImg; -var t0, t1; -for (var i=0; i < xseens.length; i++) -{ -x_element = xseens[i]; -x_canvas = new THREE.Scene(); // May need addtl info if multiple: xseen.X3DCanvas(x_element, xseen.canvases.length); -xseen.canvases.push(x_canvas); -t0 = new Date().getTime(); -/* -* Handle opening tag attributes -* divHeight -* divWidth -* turntable Indicates if view automatically rotates (independent of navigation) -*/ -var divWidth = x_element.getAttribute('width'); -var divHeight = x_element.getAttribute('height'); -if (divHeight + divWidth < 100) { -divHeight = 450; -divWidth = 800; -} else if (divHeight < 50) { -divHeight = Math.floor(divWidth/2) + 50; -} else if (divWidth < 50) { -divWidth = divHeight * 2 - 100; -} -var turntable = (x_element.getAttribute('turntable') || '').toLowerCase(); -if (turntable == 'on' || turntable == 'yes' || turntable == 'y' || turntable == '1') { -turntable = true; -} else { -turntable = false; -} -var x_camera = new THREE.PerspectiveCamera( 75, divWidth / divHeight, 0.1, 1000 ); -x_camera.position.x = 0; -x_camera.position.z = 10; -var x_renderer = new THREE.WebGLRenderer(); -x_renderer.setSize (divWidth, divHeight); -x_element.appendChild (x_renderer.domElement); -xseen.sceneInfo.push ({ -'size' : {'width':divWidth, 'height':divHeight}, -'scene' : x_canvas, -'renderer' : x_renderer, -'camera' : [x_camera], -'turntable' : turntable, -'mixers' : [], -'clock' : new THREE.Clock(), -'element' : x_element, -'stacks' : [], -'tmp' : {activeViewpoint:false}, -}); -x_element._xseen = {}; -x_element._xseen.children = []; -x_element._xseen.sceneInfo = xseen.sceneInfo[xseen.sceneInfo.length-1]; -t1 = new Date().getTime() - t0; -xseen.debug.logInfo("Time for setup and init of GL element no. " + i + ": " + t1 + " ms."); -} -var ready = (function(eventType) { -var evt = null; -if (document.createEvent) { -evt = document.createEvent("Events"); -evt.initEvent(eventType, true, true); -document.dispatchEvent(evt); -} else if (document.createEventObject) { -evt = document.createEventObject(); -document.body.fireEvent('on' + eventType, evt); -} -})('load'); -var t=[]; -for (var i=0; i root element that was added after document load. */ -xseen.reload = function() { -onload(); -}; -/* FIX PROBLEM IN CHROME - HACK - searching for better solution !!! */ -if (navigator.userAgent.indexOf("Chrome") != -1) { -document.__getElementsByTagName = document.getElementsByTagName; -document.getElementsByTagName = function(tag) { -var obj = []; -var elems = this.__getElementsByTagName("*"); -if(tag =="*"){ -obj = elems; -} else { -tag = tag.toUpperCase(); -for (var i = 0; i < elems.length; i++) { -var tagName = elems[i].tagName.toUpperCase(); -if (tagName === tag) { -obj.push(elems[i]); -} -} -} -return obj; -}; -document.__getElementById = document.getElementById; -document.getElementById = function(id) { -var obj = this.__getElementById(id); -if (!obj) { -var elems = this.__getElementsByTagName("*"); -for (var i=0; i. + + +=== COPYRIGHT +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +Copyright (C) 2017, Daly Realism for XSeen +Copyright, Fraunhofer for X3DOM +Copyright, Mozilla for A-Frame +Copyright, THREE and Khronos for various parts of THREE.js +Copyright (C) 2017, John Carlson for JSON->XML converter (JSONParser.js) + +=== +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + */ +/** +* @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com +* @author Tony Parisi / http://www.tonyparisi.com/ +*/ +THREE.ColladaLoader = function () { +var COLLADA = null; +var scene = null; +var visualScene; +var kinematicsModel; +var readyCallbackFunc = null; +var sources = {}; +var images = {}; +var animations = {}; +var controllers = {}; +var geometries = {}; +var materials = {}; +var effects = {}; +var cameras = {}; +var lights = {}; +var animData; +var kinematics; +var visualScenes; +var kinematicsModels; +var baseUrl; +var morphs; +var skins; +var flip_uv = true; +var preferredShading = THREE.SmoothShading; +var options = { +centerGeometry: false, +convertUpAxis: false, +subdivideFaces: true, +upAxis: 'Y', +defaultEnvMap: null +}; +var colladaUnit = 1.0; +var colladaUp = 'Y'; +var upConversion = null; +function load ( url, readyCallback, progressCallback, failCallback ) { +var length = 0; +if ( document.implementation && document.implementation.createDocument ) { +var request = new XMLHttpRequest(); +request.onreadystatechange = function() { +if ( request.readyState === 4 ) { +if ( request.status === 0 || request.status === 200 ) { +if ( request.response ) { +readyCallbackFunc = readyCallback; +parse( request.response, undefined, url ); +} else { +if ( failCallback ) { +failCallback( { type: 'error', url: url } ); +} else { +console.error( "ColladaLoader: Empty or non-existing file (" + url + ")" ); +} +} +}else{ +if( failCallback ){ +failCallback( { type: 'error', url: url } ); +}else{ +console.error( 'ColladaLoader: Couldn\'t load "' + url + '" (' + request.status + ')' ); +} +} +} else if ( request.readyState === 3 ) { +if ( progressCallback ) { +if ( length === 0 ) { +length = request.getResponseHeader( "Content-Length" ); +} +progressCallback( { total: length, loaded: request.responseText.length } ); +} +} +}; +request.open( "GET", url, true ); +request.send( null ); +} else { +alert( "Don't know how to parse XML!" ); +} +} +function parse( text, callBack, url ) { +COLLADA = new DOMParser().parseFromString( text, 'text/xml' ); +callBack = callBack || readyCallbackFunc; +if ( url !== undefined ) { +var parts = url.split( '/' ); +parts.pop(); +baseUrl = ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/'; +} +parseAsset(); +setUpConversion(); +images = parseLib( "library_images image", _Image, "image" ); +materials = parseLib( "library_materials material", Material, "material" ); +effects = parseLib( "library_effects effect", Effect, "effect" ); +geometries = parseLib( "library_geometries geometry", Geometry, "geometry" ); +cameras = parseLib( "library_cameras camera", Camera, "camera" ); +lights = parseLib( "library_lights light", Light, "light" ); +controllers = parseLib( "library_controllers controller", Controller, "controller" ); +animations = parseLib( "library_animations animation", Animation, "animation" ); +visualScenes = parseLib( "library_visual_scenes visual_scene", VisualScene, "visual_scene" ); +kinematicsModels = parseLib( "library_kinematics_models kinematics_model", KinematicsModel, "kinematics_model" ); +morphs = []; +skins = []; +visualScene = parseScene(); +scene = new THREE.Group(); +for ( var i = 0; i < visualScene.nodes.length; i ++ ) { +scene.add( createSceneGraph( visualScene.nodes[ i ] ) ); +} +scene.scale.multiplyScalar( colladaUnit ); +createAnimations(); +kinematicsModel = parseKinematicsModel(); +createKinematics(); +var result = { +scene: scene, +morphs: morphs, +skins: skins, +animations: animData, +kinematics: kinematics, +dae: { +images: images, +materials: materials, +cameras: cameras, +lights: lights, +effects: effects, +geometries: geometries, +controllers: controllers, +animations: animations, +visualScenes: visualScenes, +visualScene: visualScene, +scene: visualScene, +kinematicsModels: kinematicsModels, +kinematicsModel: kinematicsModel +} +}; +if ( callBack ) { +callBack( result ); +} +return result; +} +function setPreferredShading ( shading ) { +preferredShading = shading; +} +function parseAsset () { +var elements = COLLADA.querySelectorAll('asset'); +var element = elements[0]; +if ( element && element.childNodes ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'unit': +var meter = child.getAttribute( 'meter' ); +if ( meter ) { +colladaUnit = parseFloat( meter ); +} +break; +case 'up_axis': +colladaUp = child.textContent.charAt(0); +break; +} +} +} +} +function parseLib ( q, classSpec, prefix ) { +var elements = COLLADA.querySelectorAll(q); +var lib = {}; +var i = 0; +var elementsLength = elements.length; +for ( var j = 0; j < elementsLength; j ++ ) { +var element = elements[j]; +var daeElement = ( new classSpec() ).parse( element ); +if ( !daeElement.id || daeElement.id.length === 0 ) daeElement.id = prefix + ( i ++ ); +lib[ daeElement.id ] = daeElement; +} +return lib; +} +function parseScene() { +var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0]; +if ( sceneElement ) { +var url = sceneElement.getAttribute( 'url' ).replace( /^#/, '' ); +return visualScenes[ url.length > 0 ? url : 'visual_scene0' ]; +} else { +return null; +} +} +function parseKinematicsModel() { +var kinematicsModelElement = COLLADA.querySelectorAll('instance_kinematics_model')[0]; +if ( kinematicsModelElement ) { +var url = kinematicsModelElement.getAttribute( 'url' ).replace(/^#/, ''); +return kinematicsModels[ url.length > 0 ? url : 'kinematics_model0' ]; +} else { +return null; +} +} +function createAnimations() { +animData = []; +recurseHierarchy( scene ); +} +function recurseHierarchy( node ) { +var n = visualScene.getChildById( node.colladaId, true ), +newData = null; +if ( n && n.keys ) { +newData = { +fps: 60, +hierarchy: [ { +node: n, +keys: n.keys, +sids: n.sids +} ], +node: node, +name: 'animation_' + node.name, +length: 0 +}; +animData.push(newData); +for ( var i = 0, il = n.keys.length; i < il; i ++ ) { +newData.length = Math.max( newData.length, n.keys[i].time ); +} +} else { +newData = { +hierarchy: [ { +keys: [], +sids: [] +} ] +} +} +for ( var i = 0, il = node.children.length; i < il; i ++ ) { +var d = recurseHierarchy( node.children[i] ); +for ( var j = 0, jl = d.hierarchy.length; j < jl; j ++ ) { +newData.hierarchy.push( { +keys: [], +sids: [] +} ); +} +} +return newData; +} +function calcAnimationBounds () { +var start = 1000000; +var end = -start; +var frames = 0; +var ID; +for ( var id in animations ) { +var animation = animations[ id ]; +ID = ID || animation.id; +for ( var i = 0; i < animation.sampler.length; i ++ ) { +var sampler = animation.sampler[ i ]; +sampler.create(); +start = Math.min( start, sampler.startTime ); +end = Math.max( end, sampler.endTime ); +frames = Math.max( frames, sampler.input.length ); +} +} +return { start:start, end:end, frames:frames,ID:ID }; +} +function createMorph ( geometry, ctrl ) { +var morphCtrl = ctrl instanceof InstanceController ? controllers[ ctrl.url ] : ctrl; +if ( !morphCtrl || !morphCtrl.morph ) { +console.log("could not find morph controller!"); +return; +} +var morph = morphCtrl.morph; +for ( var i = 0; i < morph.targets.length; i ++ ) { +var target_id = morph.targets[ i ]; +var daeGeometry = geometries[ target_id ]; +if ( !daeGeometry.mesh || +!daeGeometry.mesh.primitives || +!daeGeometry.mesh.primitives.length ) { +continue; +} +var target = daeGeometry.mesh.primitives[ 0 ].geometry; +if ( target.vertices.length === geometry.vertices.length ) { +geometry.morphTargets.push( { name: "target_1", vertices: target.vertices } ); +} +} +geometry.morphTargets.push( { name: "target_Z", vertices: geometry.vertices } ); +} +function createSkin ( geometry, ctrl, applyBindShape ) { +var skinCtrl = controllers[ ctrl.url ]; +if ( !skinCtrl || !skinCtrl.skin ) { +console.log( "could not find skin controller!" ); +return; +} +if ( !ctrl.skeleton || !ctrl.skeleton.length ) { +console.log( "could not find the skeleton for the skin!" ); +return; +} +var skin = skinCtrl.skin; +var skeleton = visualScene.getChildById( ctrl.skeleton[ 0 ] ); +var hierarchy = []; +applyBindShape = applyBindShape !== undefined ? applyBindShape : true; +var bones = []; +geometry.skinWeights = []; +geometry.skinIndices = []; +/* +geometry.animation = { +name: 'take_001', +fps: 30, +length: 2, +JIT: true, +hierarchy: hierarchy +}; +*/ +if ( applyBindShape ) { +for ( var i = 0; i < geometry.vertices.length; i ++ ) { +geometry.vertices[ i ].applyMatrix4( skin.bindShapeMatrix ); +} +} +} +function setupSkeleton ( node, bones, frame, parent ) { +node.world = node.world || new THREE.Matrix4(); +node.localworld = node.localworld || new THREE.Matrix4(); +node.world.copy( node.matrix ); +node.localworld.copy( node.matrix ); +if ( node.channels && node.channels.length ) { +var channel = node.channels[ 0 ]; +var m = channel.sampler.output[ frame ]; +if ( m instanceof THREE.Matrix4 ) { +node.world.copy( m ); +node.localworld.copy(m); +if (frame === 0) +node.matrix.copy(m); +} +} +if ( parent ) { +node.world.multiplyMatrices( parent, node.world ); +} +bones.push( node ); +for ( var i = 0; i < node.nodes.length; i ++ ) { +setupSkeleton( node.nodes[ i ], bones, frame, node.world ); +} +} +function setupSkinningMatrices ( bones, skin ) { +for ( var i = 0; i < bones.length; i ++ ) { +var bone = bones[ i ]; +var found = -1; +if ( bone.type != 'JOINT' ) continue; +for ( var j = 0; j < skin.joints.length; j ++ ) { +if ( bone.sid === skin.joints[ j ] ) { +found = j; +break; +} +} +if ( found >= 0 ) { +var inv = skin.invBindMatrices[ found ]; +bone.invBindMatrix = inv; +bone.skinningMatrix = new THREE.Matrix4(); +bone.skinningMatrix.multiplyMatrices(bone.world, inv); // (IBMi * JMi) +bone.animatrix = new THREE.Matrix4(); +bone.animatrix.copy(bone.localworld); +bone.weights = []; +for ( var j = 0; j < skin.weights.length; j ++ ) { +for (var k = 0; k < skin.weights[ j ].length; k ++ ) { +var w = skin.weights[ j ][ k ]; +if ( w.joint === found ) { +bone.weights.push( w ); +} +} +} +} else { +console.warn( "ColladaLoader: Could not find joint '" + bone.sid + "'." ); +bone.skinningMatrix = new THREE.Matrix4(); +bone.weights = []; +} +} +} +function flattenSkeleton(skeleton) { +var list = []; +var walk = function(parentid, node, list) { +var bone = {}; +bone.name = node.sid; +bone.parent = parentid; +bone.matrix = node.matrix; +var data = [ new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3() ]; +bone.matrix.decompose(data[0], data[1], data[2]); +bone.pos = [ data[0].x,data[0].y,data[0].z ]; +bone.scl = [ data[2].x,data[2].y,data[2].z ]; +bone.rotq = [ data[1].x,data[1].y,data[1].z,data[1].w ]; +list.push(bone); +for (var i in node.nodes) { +walk(node.sid, node.nodes[i], list); +} +}; +walk(-1, skeleton, list); +return list; +} +function skinToBindPose(geometry,skeleton,skinController) { +var bones = []; +setupSkeleton( skeleton, bones, -1 ); +setupSkinningMatrices( bones, skinController.skin ); +var v = new THREE.Vector3(); +var skinned = []; +for (var i = 0; i < geometry.vertices.length; i ++) { +skinned.push(new THREE.Vector3()); +} +for ( i = 0; i < bones.length; i ++ ) { +if ( bones[ i ].type != 'JOINT' ) continue; +for ( var j = 0; j < bones[ i ].weights.length; j ++ ) { +var w = bones[ i ].weights[ j ]; +var vidx = w.index; +var weight = w.weight; +var o = geometry.vertices[vidx]; +var s = skinned[vidx]; +v.x = o.x; +v.y = o.y; +v.z = o.z; +v.applyMatrix4( bones[i].skinningMatrix ); +s.x += (v.x * weight); +s.y += (v.y * weight); +s.z += (v.z * weight); +} +} +for (var i = 0; i < geometry.vertices.length; i ++) { +geometry.vertices[i] = skinned[i]; +} +} +function applySkin ( geometry, instanceCtrl, frame ) { +var skinController = controllers[ instanceCtrl.url ]; +frame = frame !== undefined ? frame : 40; +if ( !skinController || !skinController.skin ) { +console.log( 'ColladaLoader: Could not find skin controller.' ); +return; +} +if ( !instanceCtrl.skeleton || !instanceCtrl.skeleton.length ) { +console.log( 'ColladaLoader: Could not find the skeleton for the skin. ' ); +return; +} +var animationBounds = calcAnimationBounds(); +var skeleton = visualScene.getChildById( instanceCtrl.skeleton[0], true ) || visualScene.getChildBySid( instanceCtrl.skeleton[0], true ); +var bonelist = flattenSkeleton(skeleton); +var joints = skinController.skin.joints; +var sortedbones = []; +for (var i = 0; i < joints.length; i ++) { +for (var j = 0; j < bonelist.length; j ++) { +if (bonelist[j].name === joints[i]) { +sortedbones[i] = bonelist[j]; +} +} +} +for (var i = 0; i < sortedbones.length; i ++) { +for (var j = 0; j < sortedbones.length; j ++) { +if (sortedbones[i].parent === sortedbones[j].name) { +sortedbones[i].parent = j; +} +} +} +var i, j, w, vidx, weight; +var v = new THREE.Vector3(), o, s; +for ( i = 0; i < geometry.vertices.length; i ++ ) { +geometry.vertices[i].applyMatrix4( skinController.skin.bindShapeMatrix ); +} +var skinIndices = []; +var skinWeights = []; +var weights = skinController.skin.weights; +for ( var i =0; i < weights.length; i ++ ) { +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); +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); +skinIndices.push(indicies); +skinWeights.push(weight); +} +geometry.skinIndices = skinIndices; +geometry.skinWeights = skinWeights; +geometry.bones = sortedbones; +var animationdata = { "name":animationBounds.ID,"fps":30,"length":animationBounds.frames / 30,"hierarchy":[] }; +for (var j = 0; j < sortedbones.length; j ++) { +animationdata.hierarchy.push({ parent:sortedbones[j].parent, name:sortedbones[j].name, keys:[] }); +} +console.log( 'ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.' ); +skinToBindPose(geometry, skeleton, skinController); +for ( frame = 0; frame < animationBounds.frames; frame ++ ) { +var bones = []; +var skinned = []; +setupSkeleton( skeleton, bones, frame ); +setupSkinningMatrices( bones, skinController.skin ); +for (var i = 0; i < bones.length; i ++) { +for (var j = 0; j < animationdata.hierarchy.length; j ++) { +if (animationdata.hierarchy[j].name === bones[i].sid) { +var key = {}; +key.time = (frame / 30); +key.matrix = bones[i].animatrix; +if (frame === 0) +bones[i].matrix = key.matrix; +var data = [ new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3() ]; +key.matrix.decompose(data[0], data[1], data[2]); +key.pos = [ data[0].x,data[0].y,data[0].z ]; +key.scl = [ data[2].x,data[2].y,data[2].z ]; +key.rot = data[1]; +animationdata.hierarchy[j].keys.push(key); +} +} +} +geometry.animation = animationdata; +} +} +function createKinematics() { +if ( kinematicsModel && kinematicsModel.joints.length === 0 ) { +kinematics = undefined; +return; +} +var jointMap = {}; +var _addToMap = function( jointIndex, parentVisualElement ) { +var parentVisualElementId = parentVisualElement.getAttribute( 'id' ); +var colladaNode = visualScene.getChildById( parentVisualElementId, true ); +var joint = kinematicsModel.joints[ jointIndex ]; +scene.traverse(function( node ) { +if ( node.colladaId == parentVisualElementId ) { +jointMap[ jointIndex ] = { +node: node, +transforms: colladaNode.transforms, +joint: joint, +position: joint.zeroPosition +}; +} +}); +}; +kinematics = { +joints: kinematicsModel && kinematicsModel.joints, +getJointValue: function( jointIndex ) { +var jointData = jointMap[ jointIndex ]; +if ( jointData ) { +return jointData.position; +} else { +console.log( 'getJointValue: joint ' + jointIndex + ' doesn\'t exist' ); +} +}, +setJointValue: function( jointIndex, value ) { +var jointData = jointMap[ jointIndex ]; +if ( jointData ) { +var joint = jointData.joint; +if ( value > joint.limits.max || value < joint.limits.min ) { +console.log( 'setJointValue: joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ')' ); +} else if ( joint.static ) { +console.log( 'setJointValue: joint ' + jointIndex + ' is static' ); +} else { +var threejsNode = jointData.node; +var axis = joint.axis; +var transforms = jointData.transforms; +var matrix = new THREE.Matrix4(); +var m1 = new THREE.Matrix4(); +for (i = 0; i < transforms.length; i ++ ) { +var transform = transforms[ i ]; +if ( transform.sid && transform.sid.indexOf( 'joint' + jointIndex ) !== -1 ) { +switch ( joint.type ) { +case 'revolute': +matrix.multiply( m1.makeRotationAxis( axis, THREE.Math.degToRad(value) ) ); +break; +case 'prismatic': +matrix.multiply( m1.makeTranslation(axis.x * value, axis.y * value, axis.z * value ) ); +break; +default: +console.warn( 'setJointValue: unknown joint type: ' + joint.type ); +break; +} +} else { +switch ( transform.type ) { +case 'matrix': +matrix.multiply( transform.obj ); +break; +case 'translate': +matrix.multiply( m1.makeTranslation( transform.obj.x, transform.obj.y, transform.obj.z ) ); +break; +case 'rotate': +matrix.multiply( m1.makeRotationAxis( transform.obj, transform.angle ) ); +break; +} +} +} +var elementsFloat32Arr = matrix.elements; +var elements = Array.prototype.slice.call( elementsFloat32Arr ); +var elementsRowMajor = [ +elements[ 0 ], +elements[ 4 ], +elements[ 8 ], +elements[ 12 ], +elements[ 1 ], +elements[ 5 ], +elements[ 9 ], +elements[ 13 ], +elements[ 2 ], +elements[ 6 ], +elements[ 10 ], +elements[ 14 ], +elements[ 3 ], +elements[ 7 ], +elements[ 11 ], +elements[ 15 ] +]; +threejsNode.matrix.set.apply( threejsNode.matrix, elementsRowMajor ); +threejsNode.matrix.decompose( threejsNode.position, threejsNode.quaternion, threejsNode.scale ); +jointMap[ jointIndex ].position = value; +} +} else { +console.log( 'setJointValue: joint ' + jointIndex + ' doesn\'t exist' ); +} +} +}; +var element = COLLADA.querySelector('scene instance_kinematics_scene'); +if ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'bind_joint_axis': +var visualTarget = child.getAttribute( 'target' ).split( '/' ).pop(); +var axis = child.querySelector('axis param').textContent; +var jointIndex = parseInt( axis.split( 'joint' ).pop().split( '.' )[0] ); +var visualTargetElement = COLLADA.querySelector( '[sid="' + visualTarget + '"]' ); +if ( visualTargetElement ) { +var parentVisualElement = visualTargetElement.parentElement; +_addToMap(jointIndex, parentVisualElement); +} +break; +default: +break; +} +} +} +} +function createSceneGraph ( node, parent ) { +var obj = new THREE.Object3D(); +var skinned = false; +var skinController; +var morphController; +var i, j; +for ( i = 0; i < node.controllers.length; i ++ ) { +var controller = controllers[ node.controllers[ i ].url ]; +switch ( controller.type ) { +case 'skin': +if ( geometries[ controller.skin.source ] ) { +var inst_geom = new InstanceGeometry(); +inst_geom.url = controller.skin.source; +inst_geom.instance_material = node.controllers[ i ].instance_material; +node.geometries.push( inst_geom ); +skinned = true; +skinController = node.controllers[ i ]; +} else if ( controllers[ controller.skin.source ] ) { +var second = controllers[ controller.skin.source ]; +morphController = second; +if ( second.morph && geometries[ second.morph.source ] ) { +var inst_geom = new InstanceGeometry(); +inst_geom.url = second.morph.source; +inst_geom.instance_material = node.controllers[ i ].instance_material; +node.geometries.push( inst_geom ); +} +} +break; +case 'morph': +if ( geometries[ controller.morph.source ] ) { +var inst_geom = new InstanceGeometry(); +inst_geom.url = controller.morph.source; +inst_geom.instance_material = node.controllers[ i ].instance_material; +node.geometries.push( inst_geom ); +morphController = node.controllers[ i ]; +} +console.log( 'ColladaLoader: Morph-controller partially supported.' ); +default: +break; +} +} +var double_sided_materials = {}; +for ( i = 0; i < node.geometries.length; i ++ ) { +var instance_geometry = node.geometries[i]; +var instance_materials = instance_geometry.instance_material; +var geometry = geometries[ instance_geometry.url ]; +var used_materials = {}; +var used_materials_array = []; +var num_materials = 0; +var first_material; +if ( geometry ) { +if ( !geometry.mesh || !geometry.mesh.primitives ) +continue; +if ( obj.name.length === 0 ) { +obj.name = geometry.id; +} +if ( instance_materials ) { +for ( j = 0; j < instance_materials.length; j ++ ) { +var instance_material = instance_materials[ j ]; +var mat = materials[ instance_material.target ]; +var effect_id = mat.instance_effect.url; +var shader = effects[ effect_id ].shader; +var material3js = shader.material; +if ( geometry.doubleSided ) { +if ( !( instance_material.symbol in double_sided_materials ) ) { +var _copied_material = material3js.clone(); +_copied_material.side = THREE.DoubleSide; +double_sided_materials[ instance_material.symbol ] = _copied_material; +} +material3js = double_sided_materials[ instance_material.symbol ]; +} +material3js.opacity = !material3js.opacity ? 1 : material3js.opacity; +used_materials[ instance_material.symbol ] = num_materials; +used_materials_array.push( material3js ); +first_material = material3js; +first_material.name = mat.name === null || mat.name === '' ? mat.id : mat.name; +num_materials ++; +} +} +var mesh; +var material = first_material || new THREE.MeshLambertMaterial( { color: 0xdddddd, side: geometry.doubleSided ? THREE.DoubleSide : THREE.FrontSide } ); +var geom = geometry.mesh.geometry3js; +if ( num_materials > 1 ) { +material = new THREE.MultiMaterial( used_materials_array ); +for ( j = 0; j < geom.faces.length; j ++ ) { +var face = geom.faces[ j ]; +face.materialIndex = used_materials[ face.daeMaterial ] +} +} +if ( skinController !== undefined ) { +applySkin( geom, skinController ); +if ( geom.morphTargets.length > 0 ) { +material.morphTargets = true; +material.skinning = false; +} else { +material.morphTargets = false; +material.skinning = true; +} +mesh = new THREE.SkinnedMesh( geom, material, false ); +mesh.name = 'skin_' + skins.length; +skins.push( mesh ); +} else if ( morphController !== undefined ) { +createMorph( geom, morphController ); +material.morphTargets = true; +mesh = new THREE.Mesh( geom, material ); +mesh.name = 'morph_' + morphs.length; +morphs.push( mesh ); +} else { +if ( geom.isLineStrip === true ) { +mesh = new THREE.Line( geom ); +} else { +mesh = new THREE.Mesh( geom, material ); +} +} +obj.add(mesh); +} +} +for ( i = 0; i < node.cameras.length; i ++ ) { +var instance_camera = node.cameras[i]; +var cparams = cameras[instance_camera.url]; +var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio), +parseFloat(cparams.znear), parseFloat(cparams.zfar)); +obj.add(cam); +} +for ( i = 0; i < node.lights.length; i ++ ) { +var light = null; +var instance_light = node.lights[i]; +var lparams = lights[instance_light.url]; +if ( lparams && lparams.technique ) { +var color = lparams.color.getHex(); +var intensity = lparams.intensity; +var distance = lparams.distance; +var angle = lparams.falloff_angle; +switch ( lparams.technique ) { +case 'directional': +light = new THREE.DirectionalLight( color, intensity, distance ); +light.position.set(0, 0, 1); +break; +case 'point': +light = new THREE.PointLight( color, intensity, distance ); +break; +case 'spot': +light = new THREE.SpotLight( color, intensity, distance, angle ); +light.position.set(0, 0, 1); +break; +case 'ambient': +light = new THREE.AmbientLight( color ); +break; +} +} +if (light) { +obj.add(light); +} +} +obj.name = node.name || node.id || ""; +obj.colladaId = node.id || ""; +obj.layer = node.layer || ""; +obj.matrix = node.matrix; +obj.matrix.decompose( obj.position, obj.quaternion, obj.scale ); +if ( options.centerGeometry && obj.geometry ) { +var delta = obj.geometry.center(); +delta.multiply( obj.scale ); +delta.applyQuaternion( obj.quaternion ); +obj.position.sub( delta ); +} +for ( i = 0; i < node.nodes.length; i ++ ) { +obj.add( createSceneGraph( node.nodes[i], node ) ); +} +return obj; +} +function getJointId( skin, id ) { +for ( var i = 0; i < skin.joints.length; i ++ ) { +if ( skin.joints[ i ] === id ) { +return i; +} +} +} +function getLibraryNode( id ) { +var nodes = COLLADA.querySelectorAll('library_nodes node'); +for ( var i = 0; i < nodes.length; i++ ) { +var attObj = nodes[i].attributes.getNamedItem('id'); +if ( attObj && attObj.value === id ) { +return nodes[i]; +} +} +return undefined; +} +function getChannelsForNode ( node ) { +var channels = []; +var startTime = 1000000; +var endTime = -1000000; +for ( var id in animations ) { +var animation = animations[id]; +for ( var i = 0; i < animation.channel.length; i ++ ) { +var channel = animation.channel[i]; +var sampler = animation.sampler[i]; +var id = channel.target.split('/')[0]; +if ( id == node.id ) { +sampler.create(); +channel.sampler = sampler; +startTime = Math.min(startTime, sampler.startTime); +endTime = Math.max(endTime, sampler.endTime); +channels.push(channel); +} +} +} +if ( channels.length ) { +node.startTime = startTime; +node.endTime = endTime; +} +return channels; +} +function calcFrameDuration( node ) { +var minT = 10000000; +for ( var i = 0; i < node.channels.length; i ++ ) { +var sampler = node.channels[i].sampler; +for ( var j = 0; j < sampler.input.length - 1; j ++ ) { +var t0 = sampler.input[ j ]; +var t1 = sampler.input[ j + 1 ]; +minT = Math.min( minT, t1 - t0 ); +} +} +return minT; +} +function calcMatrixAt( node, t ) { +var animated = {}; +var i, j; +for ( i = 0; i < node.channels.length; i ++ ) { +var channel = node.channels[ i ]; +animated[ channel.sid ] = channel; +} +var matrix = new THREE.Matrix4(); +for ( i = 0; i < node.transforms.length; i ++ ) { +var transform = node.transforms[ i ]; +var channel = animated[ transform.sid ]; +if ( channel !== undefined ) { +var sampler = channel.sampler; +var value; +for ( j = 0; j < sampler.input.length - 1; j ++ ) { +if ( sampler.input[ j + 1 ] > t ) { +value = sampler.output[ j ]; +break; +} +} +if ( value !== undefined ) { +if ( value instanceof THREE.Matrix4 ) { +matrix.multiplyMatrices( matrix, value ); +} else { +matrix.multiplyMatrices( matrix, transform.matrix ); +} +} else { +matrix.multiplyMatrices( matrix, transform.matrix ); +} +} else { +matrix.multiplyMatrices( matrix, transform.matrix ); +} +} +return matrix; +} +function bakeAnimations ( node ) { +if ( node.channels && node.channels.length ) { +var keys = [], +sids = []; +for ( var i = 0, il = node.channels.length; i < il; i ++ ) { +var channel = node.channels[i], +fullSid = channel.fullSid, +sampler = channel.sampler, +input = sampler.input, +transform = node.getTransformBySid( channel.sid ), +member; +if ( channel.arrIndices ) { +member = []; +for ( var j = 0, jl = channel.arrIndices.length; j < jl; j ++ ) { +member[ j ] = getConvertedIndex( channel.arrIndices[ j ] ); +} +} else { +member = getConvertedMember( channel.member ); +} +if ( transform ) { +if ( sids.indexOf( fullSid ) === -1 ) { +sids.push( fullSid ); +} +for ( var j = 0, jl = input.length; j < jl; j ++ ) { +var time = input[j], +data = sampler.getData( transform.type, j, member ), +key = findKey( keys, time ); +if ( !key ) { +key = new Key( time ); +var timeNdx = findTimeNdx( keys, time ); +keys.splice( timeNdx === -1 ? keys.length : timeNdx, 0, key ); +} +key.addTarget( fullSid, transform, member, data ); +} +} else { +console.log( 'Could not find transform "' + channel.sid + '" in node ' + node.id ); +} +} +for ( var i = 0; i < sids.length; i ++ ) { +var sid = sids[ i ]; +for ( var j = 0; j < keys.length; j ++ ) { +var key = keys[ j ]; +if ( !key.hasTarget( sid ) ) { +interpolateKeys( keys, key, j, sid ); +} +} +} +node.keys = keys; +node.sids = sids; +} +} +function findKey ( keys, time) { +var retVal = null; +for ( var i = 0, il = keys.length; i < il && retVal === null; i ++ ) { +var key = keys[i]; +if ( key.time === time ) { +retVal = key; +} else if ( key.time > time ) { +break; +} +} +return retVal; +} +function findTimeNdx ( keys, time) { +var ndx = -1; +for ( var i = 0, il = keys.length; i < il && ndx === -1; i ++ ) { +var key = keys[i]; +if ( key.time >= time ) { +ndx = i; +} +} +return ndx; +} +function interpolateKeys ( keys, key, ndx, fullSid ) { +var prevKey = getPrevKeyWith( keys, fullSid, ndx ? ndx - 1 : 0 ), +nextKey = getNextKeyWith( keys, fullSid, ndx + 1 ); +if ( prevKey && nextKey ) { +var scale = (key.time - prevKey.time) / (nextKey.time - prevKey.time), +prevTarget = prevKey.getTarget( fullSid ), +nextData = nextKey.getTarget( fullSid ).data, +prevData = prevTarget.data, +data; +if ( prevTarget.type === 'matrix' ) { +data = prevData; +} else if ( prevData.length ) { +data = []; +for ( var i = 0; i < prevData.length; ++ i ) { +data[ i ] = prevData[ i ] + ( nextData[ i ] - prevData[ i ] ) * scale; +} +} else { +data = prevData + ( nextData - prevData ) * scale; +} +key.addTarget( fullSid, prevTarget.transform, prevTarget.member, data ); +} +} +function getNextKeyWith( keys, fullSid, ndx ) { +for ( ; ndx < keys.length; ndx ++ ) { +var key = keys[ ndx ]; +if ( key.hasTarget( fullSid ) ) { +return key; +} +} +return null; +} +function getPrevKeyWith( keys, fullSid, ndx ) { +ndx = ndx >= 0 ? ndx : ndx + keys.length; +for ( ; ndx >= 0; ndx -- ) { +var key = keys[ ndx ]; +if ( key.hasTarget( fullSid ) ) { +return key; +} +} +return null; +} +function _Image() { +this.id = ""; +this.init_from = ""; +} +_Image.prototype.parse = function(element) { +this.id = element.getAttribute('id'); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeName === 'init_from' ) { +this.init_from = child.textContent; +} +} +return this; +}; +function Controller() { +this.id = ""; +this.name = ""; +this.type = ""; +this.skin = null; +this.morph = null; +} +Controller.prototype.parse = function( element ) { +this.id = element.getAttribute('id'); +this.name = element.getAttribute('name'); +this.type = "none"; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'skin': +this.skin = (new Skin()).parse(child); +this.type = child.nodeName; +break; +case 'morph': +this.morph = (new Morph()).parse(child); +this.type = child.nodeName; +break; +default: +break; +} +} +return this; +}; +function Morph() { +this.method = null; +this.source = null; +this.targets = null; +this.weights = null; +} +Morph.prototype.parse = function( element ) { +var sources = {}; +var inputs = []; +var i; +this.method = element.getAttribute( 'method' ); +this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); +for ( i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'source': +var source = ( new Source() ).parse( child ); +sources[ source.id ] = source; +break; +case 'targets': +inputs = this.parseInputs( child ); +break; +default: +console.log( child.nodeName ); +break; +} +} +for ( i = 0; i < inputs.length; i ++ ) { +var input = inputs[ i ]; +var source = sources[ input.source ]; +switch ( input.semantic ) { +case 'MORPH_TARGET': +this.targets = source.read(); +break; +case 'MORPH_WEIGHT': +this.weights = source.read(); +break; +default: +break; +} +} +return this; +}; +Morph.prototype.parseInputs = function(element) { +var inputs = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1) continue; +switch ( child.nodeName ) { +case 'input': +inputs.push( (new Input()).parse(child) ); +break; +default: +break; +} +} +return inputs; +}; +function Skin() { +this.source = ""; +this.bindShapeMatrix = null; +this.invBindMatrices = []; +this.joints = []; +this.weights = []; +} +Skin.prototype.parse = function( element ) { +var sources = {}; +var joints, weights; +this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); +this.invBindMatrices = []; +this.joints = []; +this.weights = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'bind_shape_matrix': +var f = _floats(child.textContent); +this.bindShapeMatrix = getConvertedMat4( f ); +break; +case 'source': +var src = new Source().parse(child); +sources[ src.id ] = src; +break; +case 'joints': +joints = child; +break; +case 'vertex_weights': +weights = child; +break; +default: +console.log( child.nodeName ); +break; +} +} +this.parseJoints( joints, sources ); +this.parseWeights( weights, sources ); +return this; +}; +Skin.prototype.parseJoints = function ( element, sources ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'input': +var input = ( new Input() ).parse( child ); +var source = sources[ input.source ]; +if ( input.semantic === 'JOINT' ) { +this.joints = source.read(); +} else if ( input.semantic === 'INV_BIND_MATRIX' ) { +this.invBindMatrices = source.read(); +} +break; +default: +break; +} +} +}; +Skin.prototype.parseWeights = function ( element, sources ) { +var v, vcount, inputs = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'input': +inputs.push( ( new Input() ).parse( child ) ); +break; +case 'v': +v = _ints( child.textContent ); +break; +case 'vcount': +vcount = _ints( child.textContent ); +break; +default: +break; +} +} +var index = 0; +for ( var i = 0; i < vcount.length; i ++ ) { +var numBones = vcount[i]; +var vertex_weights = []; +for ( var j = 0; j < numBones; j ++ ) { +var influence = {}; +for ( var k = 0; k < inputs.length; k ++ ) { +var input = inputs[ k ]; +var value = v[ index + input.offset ]; +switch ( input.semantic ) { +case 'JOINT': +influence.joint = value;//this.joints[value]; +break; +case 'WEIGHT': +influence.weight = sources[ input.source ].data[ value ]; +break; +default: +break; +} +} +vertex_weights.push( influence ); +index += inputs.length; +} +for ( var j = 0; j < vertex_weights.length; j ++ ) { +vertex_weights[ j ].index = i; +} +this.weights.push( vertex_weights ); +} +}; +function VisualScene () { +this.id = ""; +this.name = ""; +this.nodes = []; +this.scene = new THREE.Group(); +} +VisualScene.prototype.getChildById = function( id, recursive ) { +for ( var i = 0; i < this.nodes.length; i ++ ) { +var node = this.nodes[ i ].getChildById( id, recursive ); +if ( node ) { +return node; +} +} +return null; +}; +VisualScene.prototype.getChildBySid = function( sid, recursive ) { +for ( var i = 0; i < this.nodes.length; i ++ ) { +var node = this.nodes[ i ].getChildBySid( sid, recursive ); +if ( node ) { +return node; +} +} +return null; +}; +VisualScene.prototype.parse = function( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +this.nodes = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'node': +this.nodes.push( ( new Node() ).parse( child ) ); +break; +default: +break; +} +} +return this; +}; +function Node() { +this.id = ""; +this.name = ""; +this.sid = ""; +this.nodes = []; +this.controllers = []; +this.transforms = []; +this.geometries = []; +this.channels = []; +this.matrix = new THREE.Matrix4(); +} +Node.prototype.getChannelForTransform = function( transformSid ) { +for ( var i = 0; i < this.channels.length; i ++ ) { +var channel = this.channels[i]; +var parts = channel.target.split('/'); +var id = parts.shift(); +var sid = parts.shift(); +var dotSyntax = (sid.indexOf(".") >= 0); +var arrSyntax = (sid.indexOf("(") >= 0); +var arrIndices; +var member; +if ( dotSyntax ) { +parts = sid.split("."); +sid = parts.shift(); +member = parts.shift(); +} else if ( arrSyntax ) { +arrIndices = sid.split("("); +sid = arrIndices.shift(); +for ( var j = 0; j < arrIndices.length; j ++ ) { +arrIndices[ j ] = parseInt( arrIndices[ j ].replace( /\)/, '' ) ); +} +} +if ( sid === transformSid ) { +channel.info = { sid: sid, dotSyntax: dotSyntax, arrSyntax: arrSyntax, arrIndices: arrIndices }; +return channel; +} +} +return null; +}; +Node.prototype.getChildById = function ( id, recursive ) { +if ( this.id === id ) { +return this; +} +if ( recursive ) { +for ( var i = 0; i < this.nodes.length; i ++ ) { +var n = this.nodes[ i ].getChildById( id, recursive ); +if ( n ) { +return n; +} +} +} +return null; +}; +Node.prototype.getChildBySid = function ( sid, recursive ) { +if ( this.sid === sid ) { +return this; +} +if ( recursive ) { +for ( var i = 0; i < this.nodes.length; i ++ ) { +var n = this.nodes[ i ].getChildBySid( sid, recursive ); +if ( n ) { +return n; +} +} +} +return null; +}; +Node.prototype.getTransformBySid = function ( sid ) { +for ( var i = 0; i < this.transforms.length; i ++ ) { +if ( this.transforms[ i ].sid === sid ) return this.transforms[ i ]; +} +return null; +}; +Node.prototype.parse = function( element ) { +var url; +this.id = element.getAttribute('id'); +this.sid = element.getAttribute('sid'); +this.name = element.getAttribute('name'); +this.type = element.getAttribute('type'); +this.layer = element.getAttribute('layer'); +this.type = this.type === 'JOINT' ? this.type : 'NODE'; +this.nodes = []; +this.transforms = []; +this.geometries = []; +this.cameras = []; +this.lights = []; +this.controllers = []; +this.matrix = new THREE.Matrix4(); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'node': +this.nodes.push( ( new Node() ).parse( child ) ); +break; +case 'instance_camera': +this.cameras.push( ( new InstanceCamera() ).parse( child ) ); +break; +case 'instance_controller': +this.controllers.push( ( new InstanceController() ).parse( child ) ); +break; +case 'instance_geometry': +this.geometries.push( ( new InstanceGeometry() ).parse( child ) ); +break; +case 'instance_light': +this.lights.push( ( new InstanceLight() ).parse( child ) ); +break; +case 'instance_node': +url = child.getAttribute( 'url' ).replace( /^#/, '' ); +var iNode = getLibraryNode( url ); +if ( iNode ) { +this.nodes.push( ( new Node() ).parse( iNode )) ; +} +break; +case 'rotate': +case 'translate': +case 'scale': +case 'matrix': +case 'lookat': +case 'skew': +this.transforms.push( ( new Transform() ).parse( child ) ); +break; +case 'extra': +break; +default: +console.log( child.nodeName ); +break; +} +} +this.channels = getChannelsForNode( this ); +bakeAnimations( this ); +this.updateMatrix(); +return this; +}; +Node.prototype.updateMatrix = function () { +this.matrix.identity(); +for ( var i = 0; i < this.transforms.length; i ++ ) { +this.transforms[ i ].apply( this.matrix ); +} +}; +function Transform () { +this.sid = ""; +this.type = ""; +this.data = []; +this.obj = null; +} +Transform.prototype.parse = function ( element ) { +this.sid = element.getAttribute( 'sid' ); +this.type = element.nodeName; +this.data = _floats( element.textContent ); +this.convert(); +return this; +}; +Transform.prototype.convert = function () { +switch ( this.type ) { +case 'matrix': +this.obj = getConvertedMat4( this.data ); +break; +case 'rotate': +this.angle = THREE.Math.degToRad( this.data[3] ); +case 'translate': +fixCoords( this.data, -1 ); +this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] ); +break; +case 'scale': +fixCoords( this.data, 1 ); +this.obj = new THREE.Vector3( this.data[ 0 ], this.data[ 1 ], this.data[ 2 ] ); +break; +default: +console.log( 'Can not convert Transform of type ' + this.type ); +break; +} +}; +Transform.prototype.apply = function () { +var m1 = new THREE.Matrix4(); +return function ( matrix ) { +switch ( this.type ) { +case 'matrix': +matrix.multiply( this.obj ); +break; +case 'translate': +matrix.multiply( m1.makeTranslation( this.obj.x, this.obj.y, this.obj.z ) ); +break; +case 'rotate': +matrix.multiply( m1.makeRotationAxis( this.obj, this.angle ) ); +break; +case 'scale': +matrix.scale( this.obj ); +break; +} +}; +}(); +Transform.prototype.update = function ( data, member ) { +var members = [ 'X', 'Y', 'Z', 'ANGLE' ]; +switch ( this.type ) { +case 'matrix': +if ( ! member ) { +this.obj.copy( data ); +} else if ( member.length === 1 ) { +switch ( member[ 0 ] ) { +case 0: +this.obj.n11 = data[ 0 ]; +this.obj.n21 = data[ 1 ]; +this.obj.n31 = data[ 2 ]; +this.obj.n41 = data[ 3 ]; +break; +case 1: +this.obj.n12 = data[ 0 ]; +this.obj.n22 = data[ 1 ]; +this.obj.n32 = data[ 2 ]; +this.obj.n42 = data[ 3 ]; +break; +case 2: +this.obj.n13 = data[ 0 ]; +this.obj.n23 = data[ 1 ]; +this.obj.n33 = data[ 2 ]; +this.obj.n43 = data[ 3 ]; +break; +case 3: +this.obj.n14 = data[ 0 ]; +this.obj.n24 = data[ 1 ]; +this.obj.n34 = data[ 2 ]; +this.obj.n44 = data[ 3 ]; +break; +} +} else if ( member.length === 2 ) { +var propName = 'n' + ( member[ 0 ] + 1 ) + ( member[ 1 ] + 1 ); +this.obj[ propName ] = data; +} else { +console.log('Incorrect addressing of matrix in transform.'); +} +break; +case 'translate': +case 'scale': +if ( Object.prototype.toString.call( member ) === '[object Array]' ) { +member = members[ member[ 0 ] ]; +} +switch ( member ) { +case 'X': +this.obj.x = data; +break; +case 'Y': +this.obj.y = data; +break; +case 'Z': +this.obj.z = data; +break; +default: +this.obj.x = data[ 0 ]; +this.obj.y = data[ 1 ]; +this.obj.z = data[ 2 ]; +break; +} +break; +case 'rotate': +if ( Object.prototype.toString.call( member ) === '[object Array]' ) { +member = members[ member[ 0 ] ]; +} +switch ( member ) { +case 'X': +this.obj.x = data; +break; +case 'Y': +this.obj.y = data; +break; +case 'Z': +this.obj.z = data; +break; +case 'ANGLE': +this.angle = THREE.Math.degToRad( data ); +break; +default: +this.obj.x = data[ 0 ]; +this.obj.y = data[ 1 ]; +this.obj.z = data[ 2 ]; +this.angle = THREE.Math.degToRad( data[ 3 ] ); +break; +} +break; +} +}; +function InstanceController() { +this.url = ""; +this.skeleton = []; +this.instance_material = []; +} +InstanceController.prototype.parse = function ( element ) { +this.url = element.getAttribute('url').replace(/^#/, ''); +this.skeleton = []; +this.instance_material = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType !== 1 ) continue; +switch ( child.nodeName ) { +case 'skeleton': +this.skeleton.push( child.textContent.replace(/^#/, '') ); +break; +case 'bind_material': +var instances = child.querySelectorAll('instance_material'); +for ( var j = 0; j < instances.length; j ++ ) { +var instance = instances[j]; +this.instance_material.push( (new InstanceMaterial()).parse(instance) ); +} +break; +case 'extra': +break; +default: +break; +} +} +return this; +}; +function InstanceMaterial () { +this.symbol = ""; +this.target = ""; +} +InstanceMaterial.prototype.parse = function ( element ) { +this.symbol = element.getAttribute('symbol'); +this.target = element.getAttribute('target').replace(/^#/, ''); +return this; +}; +function InstanceGeometry() { +this.url = ""; +this.instance_material = []; +} +InstanceGeometry.prototype.parse = function ( element ) { +this.url = element.getAttribute('url').replace(/^#/, ''); +this.instance_material = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1 ) continue; +if ( child.nodeName === 'bind_material' ) { +var instances = child.querySelectorAll('instance_material'); +for ( var j = 0; j < instances.length; j ++ ) { +var instance = instances[j]; +this.instance_material.push( (new InstanceMaterial()).parse(instance) ); +} +break; +} +} +return this; +}; +function Geometry() { +this.id = ""; +this.mesh = null; +} +Geometry.prototype.parse = function ( element ) { +this.id = element.getAttribute('id'); +extractDoubleSided( this, element ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +switch ( child.nodeName ) { +case 'mesh': +this.mesh = (new Mesh(this)).parse(child); +break; +case 'extra': +break; +default: +break; +} +} +return this; +}; +function Mesh( geometry ) { +this.geometry = geometry.id; +this.primitives = []; +this.vertices = null; +this.geometry3js = null; +} +Mesh.prototype.parse = function ( element ) { +this.primitives = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'source': +_source( child ); +break; +case 'vertices': +this.vertices = ( new Vertices() ).parse( child ); +break; +case 'linestrips': +this.primitives.push( ( new LineStrips().parse( child ) ) ); +break; +case 'triangles': +this.primitives.push( ( new Triangles().parse( child ) ) ); +break; +case 'polygons': +this.primitives.push( ( new Polygons().parse( child ) ) ); +break; +case 'polylist': +this.primitives.push( ( new Polylist().parse( child ) ) ); +break; +default: +break; +} +} +this.geometry3js = new THREE.Geometry(); +if ( this.vertices === null ) { +return this; +} +var vertexData = sources[ this.vertices.input['POSITION'].source ].data; +for ( var i = 0; i < vertexData.length; i += 3 ) { +this.geometry3js.vertices.push( getConvertedVec3( vertexData, i ).clone() ); +} +for ( var i = 0; i < this.primitives.length; i ++ ) { +var primitive = this.primitives[ i ]; +primitive.setVertices( this.vertices ); +this.handlePrimitive( primitive, this.geometry3js ); +} +if ( this.geometry3js.calcNormals ) { +this.geometry3js.computeVertexNormals(); +delete this.geometry3js.calcNormals; +} +return this; +}; +Mesh.prototype.handlePrimitive = function ( primitive, geom ) { +if ( primitive instanceof LineStrips ) { +geom.isLineStrip = true; +return; +} +var j, k, pList = primitive.p, inputs = primitive.inputs; +var input, index, idx32; +var source, numParams; +var vcIndex = 0, vcount = 3, maxOffset = 0; +var texture_sets = []; +for ( j = 0; j < inputs.length; j ++ ) { +input = inputs[ j ]; +var offset = input.offset + 1; +maxOffset = (maxOffset < offset) ? offset : maxOffset; +switch ( input.semantic ) { +case 'TEXCOORD': +texture_sets.push( input.set ); +break; +} +} +for ( var pCount = 0; pCount < pList.length; ++ pCount ) { +var p = pList[ pCount ], i = 0; +while ( i < p.length ) { +var vs = []; +var ns = []; +var ts = null; +var cs = []; +if ( primitive.vcount ) { +vcount = primitive.vcount.length ? primitive.vcount[ vcIndex ++ ] : primitive.vcount; +} else { +vcount = p.length / maxOffset; +} +for ( j = 0; j < vcount; j ++ ) { +for ( k = 0; k < inputs.length; k ++ ) { +input = inputs[ k ]; +source = sources[ input.source ]; +index = p[ i + ( j * maxOffset ) + input.offset ]; +numParams = source.accessor.params.length; +idx32 = index * numParams; +switch ( input.semantic ) { +case 'VERTEX': +vs.push( index ); +break; +case 'NORMAL': +ns.push( getConvertedVec3( source.data, idx32 ) ); +break; +case 'TEXCOORD': +ts = ts || { }; +if ( ts[ input.set ] === undefined ) ts[ input.set ] = []; +ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], source.data[ idx32 + 1 ] ) ); +break; +case 'COLOR': +cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) ); +break; +default: +break; +} +} +} +if ( ns.length === 0 ) { +input = this.vertices.input.NORMAL; +if ( input ) { +source = sources[ input.source ]; +numParams = source.accessor.params.length; +for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { +ns.push( getConvertedVec3( source.data, vs[ ndx ] * numParams ) ); +} +} else { +geom.calcNormals = true; +} +} +if ( !ts ) { +ts = { }; +input = this.vertices.input.TEXCOORD; +if ( input ) { +texture_sets.push( input.set ); +source = sources[ input.source ]; +numParams = source.accessor.params.length; +for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { +idx32 = vs[ ndx ] * numParams; +if ( ts[ input.set ] === undefined ) ts[ input.set ] = [ ]; +ts[ input.set ].push( new THREE.Vector2( source.data[ idx32 ], 1.0 - source.data[ idx32 + 1 ] ) ); +} +} +} +if ( cs.length === 0 ) { +input = this.vertices.input.COLOR; +if ( input ) { +source = sources[ input.source ]; +numParams = source.accessor.params.length; +for ( var ndx = 0, len = vs.length; ndx < len; ndx ++ ) { +idx32 = vs[ ndx ] * numParams; +cs.push( new THREE.Color().setRGB( source.data[ idx32 ], source.data[ idx32 + 1 ], source.data[ idx32 + 2 ] ) ); +} +} +} +var face = null, faces = [], uv, uvArr; +if ( vcount === 3 ) { +faces.push( new THREE.Face3( vs[0], vs[1], vs[2], ns, cs.length ? cs : new THREE.Color() ) ); +} else if ( vcount === 4 ) { +faces.push( new THREE.Face3( vs[0], vs[1], vs[3], ns.length ? [ ns[0].clone(), ns[1].clone(), ns[3].clone() ] : [], cs.length ? [ cs[0], cs[1], cs[3] ] : new THREE.Color() ) ); +faces.push( new THREE.Face3( vs[1], vs[2], vs[3], ns.length ? [ ns[1].clone(), ns[2].clone(), ns[3].clone() ] : [], cs.length ? [ cs[1], cs[2], cs[3] ] : new THREE.Color() ) ); +} else if ( vcount > 4 && options.subdivideFaces ) { +var clr = cs.length ? cs : new THREE.Color(), +vec1, vec2, vec3, v1, v2, norm; +for ( k = 1; k < vcount - 1; ) { +faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], ns.length ? [ ns[0].clone(), ns[k ++].clone(), ns[k].clone() ] : [], clr ) ); +} +} +if ( faces.length ) { +for ( var ndx = 0, len = faces.length; ndx < len; ndx ++ ) { +face = faces[ndx]; +face.daeMaterial = primitive.material; +geom.faces.push( face ); +for ( k = 0; k < texture_sets.length; k ++ ) { +uv = ts[ texture_sets[k] ]; +if ( vcount > 4 ) { +uvArr = [ uv[0], uv[ndx + 1], uv[ndx + 2] ]; +} else if ( vcount === 4 ) { +if ( ndx === 0 ) { +uvArr = [ uv[0], uv[1], uv[3] ]; +} else { +uvArr = [ uv[1].clone(), uv[2], uv[3].clone() ]; +} +} else { +uvArr = [ uv[0], uv[1], uv[2] ]; +} +if ( geom.faceVertexUvs[k] === undefined ) { +geom.faceVertexUvs[k] = []; +} +geom.faceVertexUvs[k].push( uvArr ); +} +} +} else { +console.log( 'dropped face with vcount ' + vcount + ' for geometry with id: ' + geom.id ); +} +i += maxOffset * vcount; +} +} +}; +function Polygons () { +this.material = ""; +this.count = 0; +this.inputs = []; +this.vcount = null; +this.p = []; +this.geometry = new THREE.Geometry(); +} +Polygons.prototype.setVertices = function ( vertices ) { +for ( var i = 0; i < this.inputs.length; i ++ ) { +if ( this.inputs[ i ].source === vertices.id ) { +this.inputs[ i ].source = vertices.input[ 'POSITION' ].source; +} +} +}; +Polygons.prototype.parse = function ( element ) { +this.material = element.getAttribute( 'material' ); +this.count = _attr_as_int( element, 'count', 0 ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'input': +this.inputs.push( ( new Input() ).parse( element.childNodes[ i ] ) ); +break; +case 'vcount': +this.vcount = _ints( child.textContent ); +break; +case 'p': +this.p.push( _ints( child.textContent ) ); +break; +case 'ph': +console.warn( 'polygon holes not yet supported!' ); +break; +default: +break; +} +} +return this; +}; +function Polylist () { +Polygons.call( this ); +this.vcount = []; +} +Polylist.prototype = Object.create( Polygons.prototype ); +Polylist.prototype.constructor = Polylist; +function LineStrips() { +Polygons.call( this ); +this.vcount = 1; +} +LineStrips.prototype = Object.create( Polygons.prototype ); +LineStrips.prototype.constructor = LineStrips; +function Triangles () { +Polygons.call( this ); +this.vcount = 3; +} +Triangles.prototype = Object.create( Polygons.prototype ); +Triangles.prototype.constructor = Triangles; +function Accessor() { +this.source = ""; +this.count = 0; +this.stride = 0; +this.params = []; +} +Accessor.prototype.parse = function ( element ) { +this.params = []; +this.source = element.getAttribute( 'source' ); +this.count = _attr_as_int( element, 'count', 0 ); +this.stride = _attr_as_int( element, 'stride', 0 ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeName === 'param' ) { +var param = {}; +param[ 'name' ] = child.getAttribute( 'name' ); +param[ 'type' ] = child.getAttribute( 'type' ); +this.params.push( param ); +} +} +return this; +}; +function Vertices() { +this.input = {}; +} +Vertices.prototype.parse = function ( element ) { +this.id = element.getAttribute('id'); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +if ( element.childNodes[i].nodeName === 'input' ) { +var input = ( new Input() ).parse( element.childNodes[ i ] ); +this.input[ input.semantic ] = input; +} +} +return this; +}; +function Input () { +this.semantic = ""; +this.offset = 0; +this.source = ""; +this.set = 0; +} +Input.prototype.parse = function ( element ) { +this.semantic = element.getAttribute('semantic'); +this.source = element.getAttribute('source').replace(/^#/, ''); +this.set = _attr_as_int(element, 'set', -1); +this.offset = _attr_as_int(element, 'offset', 0); +if ( this.semantic === 'TEXCOORD' && this.set < 0 ) { +this.set = 0; +} +return this; +}; +function Source ( id ) { +this.id = id; +this.type = null; +} +Source.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +switch ( child.nodeName ) { +case 'bool_array': +this.data = _bools( child.textContent ); +this.type = child.nodeName; +break; +case 'float_array': +this.data = _floats( child.textContent ); +this.type = child.nodeName; +break; +case 'int_array': +this.data = _ints( child.textContent ); +this.type = child.nodeName; +break; +case 'IDREF_array': +case 'Name_array': +this.data = _strings( child.textContent ); +this.type = child.nodeName; +break; +case 'technique_common': +for ( var j = 0; j < child.childNodes.length; j ++ ) { +if ( child.childNodes[ j ].nodeName === 'accessor' ) { +this.accessor = ( new Accessor() ).parse( child.childNodes[ j ] ); +break; +} +} +break; +default: +break; +} +} +return this; +}; +Source.prototype.read = function () { +var result = []; +var param = this.accessor.params[ 0 ]; +switch ( param.type ) { +case 'IDREF': +case 'Name': case 'name': +case 'float': +return this.data; +case 'float4x4': +for ( var j = 0; j < this.data.length; j += 16 ) { +var s = this.data.slice( j, j + 16 ); +var m = getConvertedMat4( s ); +result.push( m ); +} +break; +default: +console.log( 'ColladaLoader: Source: Read dont know how to read ' + param.type + '.' ); +break; +} +return result; +}; +function Material () { +this.id = ""; +this.name = ""; +this.instance_effect = null; +} +Material.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +if ( element.childNodes[ i ].nodeName === 'instance_effect' ) { +this.instance_effect = ( new InstanceEffect() ).parse( element.childNodes[ i ] ); +break; +} +} +return this; +}; +function ColorOrTexture () { +this.color = new THREE.Color(); +this.color.setRGB( Math.random(), Math.random(), Math.random() ); +this.color.a = 1.0; +this.texture = null; +this.texcoord = null; +this.texOpts = null; +} +ColorOrTexture.prototype.isColor = function () { +return ( this.texture === null ); +}; +ColorOrTexture.prototype.isTexture = function () { +return ( this.texture != null ); +}; +ColorOrTexture.prototype.parse = function ( element ) { +if (element.nodeName === 'transparent') { +this.opaque = element.getAttribute('opaque'); +} +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'color': +var rgba = _floats( child.textContent ); +this.color = new THREE.Color(); +this.color.setRGB( rgba[0], rgba[1], rgba[2] ); +this.color.a = rgba[3]; +break; +case 'texture': +this.texture = child.getAttribute('texture'); +this.texcoord = child.getAttribute('texcoord'); +this.texOpts = { +offsetU: 0, +offsetV: 0, +repeatU: 1, +repeatV: 1, +wrapU: 1, +wrapV: 1 +}; +this.parseTexture( child ); +break; +default: +break; +} +} +return this; +}; +ColorOrTexture.prototype.parseTexture = function ( element ) { +if ( ! element.childNodes ) return this; +if ( element.childNodes[1] && element.childNodes[1].nodeName === 'extra' ) { +element = element.childNodes[1]; +if ( element.childNodes[1] && element.childNodes[1].nodeName === 'technique' ) { +element = element.childNodes[1]; +} +} +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'offsetU': +case 'offsetV': +case 'repeatU': +case 'repeatV': +this.texOpts[ child.nodeName ] = parseFloat( child.textContent ); +break; +case 'wrapU': +case 'wrapV': +if ( child.textContent.toUpperCase() === 'TRUE' ) { +this.texOpts[ child.nodeName ] = 1; +} else { +this.texOpts[ child.nodeName ] = parseInt( child.textContent ); +} +break; +default: +this.texOpts[ child.nodeName ] = child.textContent; +break; +} +} +return this; +}; +function Shader ( type, effect ) { +this.type = type; +this.effect = effect; +this.material = null; +} +Shader.prototype.parse = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'emission': +case 'diffuse': +case 'specular': +case 'transparent': +this[ child.nodeName ] = ( new ColorOrTexture() ).parse( child ); +break; +case 'bump': +var bumpType = child.getAttribute( 'bumptype' ); +if ( bumpType ) { +if ( bumpType.toLowerCase() === "heightfield" ) { +this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); +} else if ( bumpType.toLowerCase() === "normalmap" ) { +this[ 'normal' ] = ( new ColorOrTexture() ).parse( child ); +} else { +console.error( "Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType + ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'" ); +this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); +} +} else { +console.warn( "Shader.prototype.parse: Attribute 'bumptype' missing from bump node - defaulting to 'HEIGHTFIELD'" ); +this[ 'bump' ] = ( new ColorOrTexture() ).parse( child ); +} +break; +case 'shininess': +case 'reflectivity': +case 'index_of_refraction': +case 'transparency': +var f = child.querySelectorAll('float'); +if ( f.length > 0 ) +this[ child.nodeName ] = parseFloat( f[ 0 ].textContent ); +break; +default: +break; +} +} +this.create(); +return this; +}; +Shader.prototype.create = function() { +var props = {}; +var transparent = false; +if (this['transparency'] !== undefined && this['transparent'] !== undefined) { +var transparentColor = this['transparent']; +var transparencyLevel = (this.transparent.color.r + this.transparent.color.g + this.transparent.color.b) / 3 * this.transparency; +if (transparencyLevel > 0) { +transparent = true; +props[ 'transparent' ] = true; +props[ 'opacity' ] = 1 - transparencyLevel; +} +} +var keys = { +'diffuse':'map', +'ambient':'lightMap', +'specular':'specularMap', +'emission':'emissionMap', +'bump':'bumpMap', +'normal':'normalMap' +}; +for ( var prop in this ) { +switch ( prop ) { +case 'ambient': +case 'emission': +case 'diffuse': +case 'specular': +case 'bump': +case 'normal': +var cot = this[ prop ]; +if ( cot instanceof ColorOrTexture ) { +if ( cot.isTexture() ) { +var samplerId = cot.texture; +var sampler = this.effect.sampler[samplerId]; +if ( sampler !== undefined && sampler.source !== undefined ) { +var surface = this.effect.surface[sampler.source]; +if ( surface !== undefined ) { +var image = images[ surface.init_from ]; +if ( image ) { +var url = baseUrl + image.init_from; +var texture; +var loader = THREE.Loader.Handlers.get( url ); +if ( loader !== null ) { +texture = loader.load( url ); +} else { +texture = new THREE.Texture(); +loadTextureImage( texture, url ); +} +if ( sampler.wrap_s === "MIRROR" ) { +texture.wrapS = THREE.MirroredRepeatWrapping; +} else if ( sampler.wrap_s === "WRAP" || cot.texOpts.wrapU ) { +texture.wrapS = THREE.RepeatWrapping; +} else { +texture.wrapS = THREE.ClampToEdgeWrapping; +} +if ( sampler.wrap_t === "MIRROR" ) { +texture.wrapT = THREE.MirroredRepeatWrapping; +} else if ( sampler.wrap_t === "WRAP" || cot.texOpts.wrapV ) { +texture.wrapT = THREE.RepeatWrapping; +} else { +texture.wrapT = THREE.ClampToEdgeWrapping; +} +texture.offset.x = cot.texOpts.offsetU; +texture.offset.y = cot.texOpts.offsetV; +texture.repeat.x = cot.texOpts.repeatU; +texture.repeat.y = cot.texOpts.repeatV; +props[keys[prop]] = texture; +if (prop === 'emission') props['emissive'] = 0xffffff; +} +} +} +} else if ( prop === 'diffuse' || !transparent ) { +if ( prop === 'emission' ) { +props[ 'emissive' ] = cot.color.getHex(); +} else { +props[ prop ] = cot.color.getHex(); +} +} +} +break; +case 'shininess': +props[ prop ] = this[ prop ]; +break; +case 'reflectivity': +props[ prop ] = this[ prop ]; +if ( props[ prop ] > 0.0 ) props['envMap'] = options.defaultEnvMap; +props['combine'] = THREE.MixOperation; //mix regular shading with reflective component +break; +case 'index_of_refraction': +props[ 'refractionRatio' ] = this[ prop ]; //TODO: "index_of_refraction" becomes "refractionRatio" in shader, but I'm not sure if the two are actually comparable +if ( this[ prop ] !== 1.0 ) props['envMap'] = options.defaultEnvMap; +break; +case 'transparency': +break; +default: +break; +} +} +props[ 'shading' ] = preferredShading; +props[ 'side' ] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide; +if ( props.diffuse !== undefined ) { +props.color = props.diffuse; +delete props.diffuse; +} +switch ( this.type ) { +case 'constant': +if (props.emissive != undefined) props.color = props.emissive; +this.material = new THREE.MeshBasicMaterial( props ); +break; +case 'phong': +case 'blinn': +this.material = new THREE.MeshPhongMaterial( props ); +break; +case 'lambert': +default: +this.material = new THREE.MeshLambertMaterial( props ); +break; +} +return this.material; +}; +function Surface ( effect ) { +this.effect = effect; +this.init_from = null; +this.format = null; +} +Surface.prototype.parse = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'init_from': +this.init_from = child.textContent; +break; +case 'format': +this.format = child.textContent; +break; +default: +console.log( "unhandled Surface prop: " + child.nodeName ); +break; +} +} +return this; +}; +function Sampler2D ( effect ) { +this.effect = effect; +this.source = null; +this.wrap_s = null; +this.wrap_t = null; +this.minfilter = null; +this.magfilter = null; +this.mipfilter = null; +} +Sampler2D.prototype.parse = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'source': +this.source = child.textContent; +break; +case 'minfilter': +this.minfilter = child.textContent; +break; +case 'magfilter': +this.magfilter = child.textContent; +break; +case 'mipfilter': +this.mipfilter = child.textContent; +break; +case 'wrap_s': +this.wrap_s = child.textContent; +break; +case 'wrap_t': +this.wrap_t = child.textContent; +break; +default: +console.log( "unhandled Sampler2D prop: " + child.nodeName ); +break; +} +} +return this; +}; +function Effect () { +this.id = ""; +this.name = ""; +this.shader = null; +this.surface = {}; +this.sampler = {}; +} +Effect.prototype.create = function () { +if ( this.shader === null ) { +return null; +} +}; +Effect.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +extractDoubleSided( this, element ); +this.shader = null; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'profile_COMMON': +this.parseTechnique( this.parseProfileCOMMON( child ) ); +break; +default: +break; +} +} +return this; +}; +Effect.prototype.parseNewparam = function ( element ) { +var sid = element.getAttribute( 'sid' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'surface': +this.surface[sid] = ( new Surface( this ) ).parse( child ); +break; +case 'sampler2D': +this.sampler[sid] = ( new Sampler2D( this ) ).parse( child ); +break; +case 'extra': +break; +default: +console.log( child.nodeName ); +break; +} +} +}; +Effect.prototype.parseProfileCOMMON = function ( element ) { +var technique; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'profile_COMMON': +this.parseProfileCOMMON( child ); +break; +case 'technique': +technique = child; +break; +case 'newparam': +this.parseNewparam( child ); +break; +case 'image': +var _image = ( new _Image() ).parse( child ); +images[ _image.id ] = _image; +break; +case 'extra': +break; +default: +console.log( child.nodeName ); +break; +} +} +return technique; +}; +Effect.prototype.parseTechnique = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'constant': +case 'lambert': +case 'blinn': +case 'phong': +this.shader = ( new Shader( child.nodeName, this ) ).parse( child ); +break; +case 'extra': +this.parseExtra(child); +break; +default: +break; +} +} +}; +Effect.prototype.parseExtra = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'technique': +this.parseExtraTechnique( child ); +break; +default: +break; +} +} +}; +Effect.prototype.parseExtraTechnique = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[i]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'bump': +this.shader.parse( element ); +break; +default: +break; +} +} +}; +function InstanceEffect () { +this.url = ""; +} +InstanceEffect.prototype.parse = function ( element ) { +this.url = element.getAttribute( 'url' ).replace( /^#/, '' ); +return this; +}; +function Animation() { +this.id = ""; +this.name = ""; +this.source = {}; +this.sampler = []; +this.channel = []; +} +Animation.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +this.source = {}; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'animation': +var anim = ( new Animation() ).parse( child ); +for ( var src in anim.source ) { +this.source[ src ] = anim.source[ src ]; +} +for ( var j = 0; j < anim.channel.length; j ++ ) { +this.channel.push( anim.channel[ j ] ); +this.sampler.push( anim.sampler[ j ] ); +} +break; +case 'source': +var src = ( new Source() ).parse( child ); +this.source[ src.id ] = src; +break; +case 'sampler': +this.sampler.push( ( new Sampler( this ) ).parse( child ) ); +break; +case 'channel': +this.channel.push( ( new Channel( this ) ).parse( child ) ); +break; +default: +break; +} +} +return this; +}; +function Channel( animation ) { +this.animation = animation; +this.source = ""; +this.target = ""; +this.fullSid = null; +this.sid = null; +this.dotSyntax = null; +this.arrSyntax = null; +this.arrIndices = null; +this.member = null; +} +Channel.prototype.parse = function ( element ) { +this.source = element.getAttribute( 'source' ).replace( /^#/, '' ); +this.target = element.getAttribute( 'target' ); +var parts = this.target.split( '/' ); +var id = parts.shift(); +var sid = parts.shift(); +var dotSyntax = ( sid.indexOf(".") >= 0 ); +var arrSyntax = ( sid.indexOf("(") >= 0 ); +if ( dotSyntax ) { +parts = sid.split("."); +this.sid = parts.shift(); +this.member = parts.shift(); +} else if ( arrSyntax ) { +var arrIndices = sid.split("("); +this.sid = arrIndices.shift(); +for (var j = 0; j < arrIndices.length; j ++ ) { +arrIndices[j] = parseInt( arrIndices[j].replace(/\)/, '') ); +} +this.arrIndices = arrIndices; +} else { +this.sid = sid; +} +this.fullSid = sid; +this.dotSyntax = dotSyntax; +this.arrSyntax = arrSyntax; +return this; +}; +function Sampler ( animation ) { +this.id = ""; +this.animation = animation; +this.inputs = []; +this.input = null; +this.output = null; +this.strideOut = null; +this.interpolation = null; +this.startTime = null; +this.endTime = null; +this.duration = 0; +} +Sampler.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.inputs = []; +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'input': +this.inputs.push( (new Input()).parse( child ) ); +break; +default: +break; +} +} +return this; +}; +Sampler.prototype.create = function () { +for ( var i = 0; i < this.inputs.length; i ++ ) { +var input = this.inputs[ i ]; +var source = this.animation.source[ input.source ]; +switch ( input.semantic ) { +case 'INPUT': +this.input = source.read(); +break; +case 'OUTPUT': +this.output = source.read(); +this.strideOut = source.accessor.stride; +break; +case 'INTERPOLATION': +this.interpolation = source.read(); +break; +case 'IN_TANGENT': +break; +case 'OUT_TANGENT': +break; +default: +console.log(input.semantic); +break; +} +} +this.startTime = 0; +this.endTime = 0; +this.duration = 0; +if ( this.input.length ) { +this.startTime = 100000000; +this.endTime = -100000000; +for ( var i = 0; i < this.input.length; i ++ ) { +this.startTime = Math.min( this.startTime, this.input[ i ] ); +this.endTime = Math.max( this.endTime, this.input[ i ] ); +} +this.duration = this.endTime - this.startTime; +} +}; +Sampler.prototype.getData = function ( type, ndx, member ) { +var data; +if ( type === 'matrix' && this.strideOut === 16 ) { +data = this.output[ ndx ]; +} else if ( this.strideOut > 1 ) { +data = []; +ndx *= this.strideOut; +for ( var i = 0; i < this.strideOut; ++ i ) { +data[ i ] = this.output[ ndx + i ]; +} +if ( this.strideOut === 3 ) { +switch ( type ) { +case 'rotate': +case 'translate': +fixCoords( data, -1 ); +break; +case 'scale': +fixCoords( data, 1 ); +break; +} +} else if ( this.strideOut === 4 && type === 'matrix' ) { +fixCoords( data, -1 ); +} +} else { +data = this.output[ ndx ]; +if ( member && type === 'translate' ) { +data = getConvertedTranslation( member, data ); +} +} +return data; +}; +function Key ( time ) { +this.targets = []; +this.time = time; +} +Key.prototype.addTarget = function ( fullSid, transform, member, data ) { +this.targets.push( { +sid: fullSid, +member: member, +transform: transform, +data: data +} ); +}; +Key.prototype.apply = function ( opt_sid ) { +for ( var i = 0; i < this.targets.length; ++ i ) { +var target = this.targets[ i ]; +if ( !opt_sid || target.sid === opt_sid ) { +target.transform.update( target.data, target.member ); +} +} +}; +Key.prototype.getTarget = function ( fullSid ) { +for ( var i = 0; i < this.targets.length; ++ i ) { +if ( this.targets[ i ].sid === fullSid ) { +return this.targets[ i ]; +} +} +return null; +}; +Key.prototype.hasTarget = function ( fullSid ) { +for ( var i = 0; i < this.targets.length; ++ i ) { +if ( this.targets[ i ].sid === fullSid ) { +return true; +} +} +return false; +}; +Key.prototype.interpolate = function ( nextKey, time ) { +for ( var i = 0, l = this.targets.length; i < l; i ++ ) { +var target = this.targets[ i ], +nextTarget = nextKey.getTarget( target.sid ), +data; +if ( target.transform.type !== 'matrix' && nextTarget ) { +var scale = ( time - this.time ) / ( nextKey.time - this.time ), +nextData = nextTarget.data, +prevData = target.data; +if ( scale < 0 ) scale = 0; +if ( scale > 1 ) scale = 1; +if ( prevData.length ) { +data = []; +for ( var j = 0; j < prevData.length; ++ j ) { +data[ j ] = prevData[ j ] + ( nextData[ j ] - prevData[ j ] ) * scale; +} +} else { +data = prevData + ( nextData - prevData ) * scale; +} +} else { +data = target.data; +} +target.transform.update( data, target.member ); +} +}; +function Camera() { +this.id = ""; +this.name = ""; +this.technique = ""; +} +Camera.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'optics': +this.parseOptics( child ); +break; +default: +break; +} +} +return this; +}; +Camera.prototype.parseOptics = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +if ( element.childNodes[ i ].nodeName === 'technique_common' ) { +var technique = element.childNodes[ i ]; +for ( var j = 0; j < technique.childNodes.length; j ++ ) { +this.technique = technique.childNodes[ j ].nodeName; +if ( this.technique === 'perspective' ) { +var perspective = technique.childNodes[ j ]; +for ( var k = 0; k < perspective.childNodes.length; k ++ ) { +var param = perspective.childNodes[ k ]; +switch ( param.nodeName ) { +case 'yfov': +this.yfov = param.textContent; +break; +case 'xfov': +this.xfov = param.textContent; +break; +case 'znear': +this.znear = param.textContent; +break; +case 'zfar': +this.zfar = param.textContent; +break; +case 'aspect_ratio': +this.aspect_ratio = param.textContent; +break; +} +} +} else if ( this.technique === 'orthographic' ) { +var orthographic = technique.childNodes[ j ]; +for ( var k = 0; k < orthographic.childNodes.length; k ++ ) { +var param = orthographic.childNodes[ k ]; +switch ( param.nodeName ) { +case 'xmag': +this.xmag = param.textContent; +break; +case 'ymag': +this.ymag = param.textContent; +break; +case 'znear': +this.znear = param.textContent; +break; +case 'zfar': +this.zfar = param.textContent; +break; +case 'aspect_ratio': +this.aspect_ratio = param.textContent; +break; +} +} +} +} +} +} +return this; +}; +function InstanceCamera() { +this.url = ""; +} +InstanceCamera.prototype.parse = function ( element ) { +this.url = element.getAttribute('url').replace(/^#/, ''); +return this; +}; +function Light() { +this.id = ""; +this.name = ""; +this.technique = ""; +} +Light.prototype.parse = function ( element ) { +this.id = element.getAttribute( 'id' ); +this.name = element.getAttribute( 'name' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'technique_common': +this.parseCommon( child ); +break; +case 'technique': +this.parseTechnique( child ); +break; +default: +break; +} +} +return this; +}; +Light.prototype.parseCommon = function ( element ) { +for ( var i = 0; i < element.childNodes.length; i ++ ) { +switch ( element.childNodes[ i ].nodeName ) { +case 'directional': +case 'point': +case 'spot': +case 'ambient': +this.technique = element.childNodes[ i ].nodeName; +var light = element.childNodes[ i ]; +for ( var j = 0; j < light.childNodes.length; j ++ ) { +var child = light.childNodes[j]; +switch ( child.nodeName ) { +case 'color': +var rgba = _floats( child.textContent ); +this.color = new THREE.Color(0); +this.color.setRGB( rgba[0], rgba[1], rgba[2] ); +this.color.a = rgba[3]; +break; +case 'falloff_angle': +this.falloff_angle = parseFloat( child.textContent ); +break; +case 'quadratic_attenuation': +var f = parseFloat( child.textContent ); +this.distance = f ? Math.sqrt( 1 / f ) : 0; +} +} +} +} +return this; +}; +Light.prototype.parseTechnique = function ( element ) { +this.profile = element.getAttribute( 'profile' ); +for ( var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +switch ( child.nodeName ) { +case 'intensity': +this.intensity = parseFloat(child.textContent); +break; +} +} +return this; +}; +function InstanceLight() { +this.url = ""; +} +InstanceLight.prototype.parse = function ( element ) { +this.url = element.getAttribute('url').replace(/^#/, ''); +return this; +}; +function KinematicsModel( ) { +this.id = ''; +this.name = ''; +this.joints = []; +this.links = []; +} +KinematicsModel.prototype.parse = function( element ) { +this.id = element.getAttribute('id'); +this.name = element.getAttribute('name'); +this.joints = []; +this.links = []; +for (var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'technique_common': +this.parseCommon(child); +break; +default: +break; +} +} +return this; +}; +KinematicsModel.prototype.parseCommon = function( element ) { +for (var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( element.childNodes[ i ].nodeName ) { +case 'joint': +this.joints.push( (new Joint()).parse(child) ); +break; +case 'link': +this.links.push( (new Link()).parse(child) ); +break; +default: +break; +} +} +return this; +}; +function Joint( ) { +this.sid = ''; +this.name = ''; +this.axis = new THREE.Vector3(); +this.limits = { +min: 0, +max: 0 +}; +this.type = ''; +this.static = false; +this.zeroPosition = 0.0; +this.middlePosition = 0.0; +} +Joint.prototype.parse = function( element ) { +this.sid = element.getAttribute('sid'); +this.name = element.getAttribute('name'); +this.axis = new THREE.Vector3(); +this.limits = { +min: 0, +max: 0 +}; +this.type = ''; +this.static = false; +this.zeroPosition = 0.0; +this.middlePosition = 0.0; +var axisElement = element.querySelector('axis'); +var _axis = _floats(axisElement.textContent); +this.axis = getConvertedVec3(_axis, 0); +var min = element.querySelector('limits min') ? parseFloat(element.querySelector('limits min').textContent) : -360; +var max = element.querySelector('limits max') ? parseFloat(element.querySelector('limits max').textContent) : 360; +this.limits = { +min: min, +max: max +}; +var jointTypes = [ 'prismatic', 'revolute' ]; +for (var i = 0; i < jointTypes.length; i ++ ) { +var type = jointTypes[ i ]; +var jointElement = element.querySelector(type); +if ( jointElement ) { +this.type = type; +} +} +if ( this.limits.min >= this.limits.max ) { +this.static = true; +} +this.middlePosition = (this.limits.min + this.limits.max) / 2.0; +return this; +}; +function Link( ) { +this.sid = ''; +this.name = ''; +this.transforms = []; +this.attachments = []; +} +Link.prototype.parse = function( element ) { +this.sid = element.getAttribute('sid'); +this.name = element.getAttribute('name'); +this.transforms = []; +this.attachments = []; +for (var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'attachment_full': +this.attachments.push( (new Attachment()).parse(child) ); +break; +case 'rotate': +case 'translate': +case 'matrix': +this.transforms.push( (new Transform()).parse(child) ); +break; +default: +break; +} +} +return this; +}; +function Attachment( ) { +this.joint = ''; +this.transforms = []; +this.links = []; +} +Attachment.prototype.parse = function( element ) { +this.joint = element.getAttribute('joint').split('/').pop(); +this.links = []; +for (var i = 0; i < element.childNodes.length; i ++ ) { +var child = element.childNodes[ i ]; +if ( child.nodeType != 1 ) continue; +switch ( child.nodeName ) { +case 'link': +this.links.push( (new Link()).parse(child) ); +break; +case 'rotate': +case 'translate': +case 'matrix': +this.transforms.push( (new Transform()).parse(child) ); +break; +default: +break; +} +} +return this; +}; +function _source( element ) { +var id = element.getAttribute( 'id' ); +if ( sources[ id ] != undefined ) { +return sources[ id ]; +} +sources[ id ] = ( new Source(id )).parse( element ); +return sources[ id ]; +} +function _nsResolver( nsPrefix ) { +if ( nsPrefix === "dae" ) { +return "http://www.collada.org/2005/11/COLLADASchema"; +} +return null; +} +function _bools( str ) { +var raw = _strings( str ); +var data = []; +for ( var i = 0, l = raw.length; i < l; i ++ ) { +data.push( (raw[i] === 'true' || raw[i] === '1') ? true : false ); +} +return data; +} +function _floats( str ) { +var raw = _strings(str); +var data = []; +for ( var i = 0, l = raw.length; i < l; i ++ ) { +data.push( parseFloat( raw[ i ] ) ); +} +return data; +} +function _ints( str ) { +var raw = _strings( str ); +var data = []; +for ( var i = 0, l = raw.length; i < l; i ++ ) { +data.push( parseInt( raw[ i ], 10 ) ); +} +return data; +} +function _strings( str ) { +return ( str.length > 0 ) ? _trimString( str ).split( /\s+/ ) : []; +} +function _trimString( str ) { +return str.replace( /^\s+/, "" ).replace( /\s+$/, "" ); +} +function _attr_as_float( element, name, defaultValue ) { +if ( element.hasAttribute( name ) ) { +return parseFloat( element.getAttribute( name ) ); +} else { +return defaultValue; +} +} +function _attr_as_int( element, name, defaultValue ) { +if ( element.hasAttribute( name ) ) { +return parseInt( element.getAttribute( name ), 10) ; +} else { +return defaultValue; +} +} +function _attr_as_string( element, name, defaultValue ) { +if ( element.hasAttribute( name ) ) { +return element.getAttribute( name ); +} else { +return defaultValue; +} +} +function _format_float( f, num ) { +if ( f === undefined ) { +var s = '0.'; +while ( s.length < num + 2 ) { +s += '0'; +} +return s; +} +num = num || 2; +var parts = f.toString().split( '.' ); +parts[ 1 ] = parts.length > 1 ? parts[ 1 ].substr( 0, num ) : "0"; +while ( parts[ 1 ].length < num ) { +parts[ 1 ] += '0'; +} +return parts.join( '.' ); +} +function loadTextureImage ( texture, url ) { +var loader = new THREE.ImageLoader(); +loader.load( url, function ( image ) { +texture.image = image; +texture.needsUpdate = true; +} ); +} +function extractDoubleSided( obj, element ) { +obj.doubleSided = false; +var node = element.querySelectorAll('extra double_sided')[0]; +if ( node ) { +if ( node && parseInt( node.textContent, 10 ) === 1 ) { +obj.doubleSided = true; +} +} +} +function setUpConversion() { +if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { +upConversion = null; +} else { +switch ( colladaUp ) { +case 'X': +upConversion = options.upAxis === 'Y' ? 'XtoY' : 'XtoZ'; +break; +case 'Y': +upConversion = options.upAxis === 'X' ? 'YtoX' : 'YtoZ'; +break; +case 'Z': +upConversion = options.upAxis === 'X' ? 'ZtoX' : 'ZtoY'; +break; +} +} +} +function fixCoords( data, sign ) { +if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { +return; +} +switch ( upConversion ) { +case 'XtoY': +var tmp = data[ 0 ]; +data[ 0 ] = sign * data[ 1 ]; +data[ 1 ] = tmp; +break; +case 'XtoZ': +var tmp = data[ 2 ]; +data[ 2 ] = data[ 1 ]; +data[ 1 ] = data[ 0 ]; +data[ 0 ] = tmp; +break; +case 'YtoX': +var tmp = data[ 0 ]; +data[ 0 ] = data[ 1 ]; +data[ 1 ] = sign * tmp; +break; +case 'YtoZ': +var tmp = data[ 1 ]; +data[ 1 ] = sign * data[ 2 ]; +data[ 2 ] = tmp; +break; +case 'ZtoX': +var tmp = data[ 0 ]; +data[ 0 ] = data[ 1 ]; +data[ 1 ] = data[ 2 ]; +data[ 2 ] = tmp; +break; +case 'ZtoY': +var tmp = data[ 1 ]; +data[ 1 ] = data[ 2 ]; +data[ 2 ] = sign * tmp; +break; +} +} +function getConvertedTranslation( axis, data ) { +if ( options.convertUpAxis !== true || colladaUp === options.upAxis ) { +return data; +} +switch ( axis ) { +case 'X': +data = upConversion === 'XtoY' ? data * -1 : data; +break; +case 'Y': +data = upConversion === 'YtoZ' || upConversion === 'YtoX' ? data * -1 : data; +break; +case 'Z': +data = upConversion === 'ZtoY' ? data * -1 : data ; +break; +default: +break; +} +return data; +} +function getConvertedVec3( data, offset ) { +var arr = [ data[ offset ], data[ offset + 1 ], data[ offset + 2 ] ]; +fixCoords( arr, -1 ); +return new THREE.Vector3( arr[ 0 ], arr[ 1 ], arr[ 2 ] ); +} +function getConvertedMat4( data ) { +if ( options.convertUpAxis ) { +var arr = [ data[ 0 ], data[ 4 ], data[ 8 ] ]; +fixCoords( arr, -1 ); +data[ 0 ] = arr[ 0 ]; +data[ 4 ] = arr[ 1 ]; +data[ 8 ] = arr[ 2 ]; +arr = [ data[ 1 ], data[ 5 ], data[ 9 ] ]; +fixCoords( arr, -1 ); +data[ 1 ] = arr[ 0 ]; +data[ 5 ] = arr[ 1 ]; +data[ 9 ] = arr[ 2 ]; +arr = [ data[ 2 ], data[ 6 ], data[ 10 ] ]; +fixCoords( arr, -1 ); +data[ 2 ] = arr[ 0 ]; +data[ 6 ] = arr[ 1 ]; +data[ 10 ] = arr[ 2 ]; +arr = [ data[ 0 ], data[ 1 ], data[ 2 ] ]; +fixCoords( arr, -1 ); +data[ 0 ] = arr[ 0 ]; +data[ 1 ] = arr[ 1 ]; +data[ 2 ] = arr[ 2 ]; +arr = [ data[ 4 ], data[ 5 ], data[ 6 ] ]; +fixCoords( arr, -1 ); +data[ 4 ] = arr[ 0 ]; +data[ 5 ] = arr[ 1 ]; +data[ 6 ] = arr[ 2 ]; +arr = [ data[ 8 ], data[ 9 ], data[ 10 ] ]; +fixCoords( arr, -1 ); +data[ 8 ] = arr[ 0 ]; +data[ 9 ] = arr[ 1 ]; +data[ 10 ] = arr[ 2 ]; +arr = [ data[ 3 ], data[ 7 ], data[ 11 ] ]; +fixCoords( arr, -1 ); +data[ 3 ] = arr[ 0 ]; +data[ 7 ] = arr[ 1 ]; +data[ 11 ] = arr[ 2 ]; +} +return new THREE.Matrix4().set( +data[0], data[1], data[2], data[3], +data[4], data[5], data[6], data[7], +data[8], data[9], data[10], data[11], +data[12], data[13], data[14], data[15] +); +} +function getConvertedIndex( index ) { +if ( index > -1 && index < 3 ) { +var members = [ 'X', 'Y', 'Z' ], +indices = { X: 0, Y: 1, Z: 2 }; +index = getConvertedMember( members[ index ] ); +index = indices[ index ]; +} +return index; +} +function getConvertedMember( member ) { +if ( options.convertUpAxis ) { +switch ( member ) { +case 'X': +switch ( upConversion ) { +case 'XtoY': +case 'XtoZ': +case 'YtoX': +member = 'Y'; +break; +case 'ZtoX': +member = 'Z'; +break; +} +break; +case 'Y': +switch ( upConversion ) { +case 'XtoY': +case 'YtoX': +case 'ZtoX': +member = 'X'; +break; +case 'XtoZ': +case 'YtoZ': +case 'ZtoY': +member = 'Z'; +break; +} +break; +case 'Z': +switch ( upConversion ) { +case 'XtoZ': +member = 'X'; +break; +case 'YtoZ': +case 'ZtoX': +case 'ZtoY': +member = 'Y'; +break; +} +break; +} +} +return member; +} +return { +load: load, +parse: parse, +setPreferredShading: setPreferredShading, +applySkin: applySkin, +geometries : geometries, +options: options +}; +}; +/** +* @author Rich Tibbett / https://github.com/richtr +* @author mrdoob / http://mrdoob.com/ +* @author Tony Parisi / http://www.tonyparisi.com/ +* @author Takahiro / https://github.com/takahirox +* @author Don McCurdy / https://www.donmccurdy.com +*/ +THREE.GLTF2Loader = ( function () { +function GLTF2Loader( manager ) { +this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; +} +GLTF2Loader.prototype = { +constructor: GLTF2Loader, +load: function ( url, onLoad, onProgress, onError ) { +var scope = this; +var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url ); +var loader = new THREE.FileLoader( scope.manager ); +loader.setResponseType( 'arraybuffer' ); +loader.load( url, function ( data ) { +scope.parse( data, onLoad, path ); +}, onProgress, onError ); +}, +setCrossOrigin: function ( value ) { +this.crossOrigin = value; +}, +setPath: function ( value ) { +this.path = value; +}, +parse: function ( data, callback, path ) { +var content; +var extensions = {}; +var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) ); +if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) { +extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); +content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; +} else { +content = convertUint8ArrayToString( new Uint8Array( data ) ); +} +var json = JSON.parse( content ); +if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) { +extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json ); +} +console.time( 'GLTF2Loader' ); +var parser = new GLTFParser( json, extensions, { +path: path || this.path, +crossOrigin: this.crossOrigin +} ); +parser.parse( function ( scene, scenes, cameras, animations ) { +console.timeEnd( 'GLTF2Loader' ); +var glTF = { +"scene": scene, +"scenes": scenes, +"cameras": cameras, +"animations": animations +}; +callback( glTF ); +} ); +} +}; +/* GLTFREGISTRY */ +function GLTFRegistry() { +var objects = {}; +return { +get: function ( key ) { +return objects[ key ]; +}, +add: function ( key, object ) { +objects[ key ] = object; +}, +remove: function ( key ) { +delete objects[ key ]; +}, +removeAll: function () { +objects = {}; +}, +update: function ( scene, camera ) { +for ( var name in objects ) { +var object = objects[ name ]; +if ( object.update ) { +object.update( scene, camera ); +} +} +} +}; +} +/* GLTFSHADER */ +function GLTFShader( targetNode, allNodes ) { +var boundUniforms = {}; +var uniforms = targetNode.material.uniforms; +for ( var uniformId in uniforms ) { +var uniform = uniforms[ uniformId ]; +if ( uniform.semantic ) { +var sourceNodeRef = uniform.node; +var sourceNode = targetNode; +if ( sourceNodeRef ) { +sourceNode = allNodes[ sourceNodeRef ]; +} +boundUniforms[ uniformId ] = { +semantic: uniform.semantic, +sourceNode: sourceNode, +targetNode: targetNode, +uniform: uniform +}; +} +} +this.boundUniforms = boundUniforms; +this._m4 = new THREE.Matrix4(); +} +GLTFShader.prototype.update = function ( scene, camera ) { +var boundUniforms = this.boundUniforms; +for ( var name in boundUniforms ) { +var boundUniform = boundUniforms[ name ]; +switch ( boundUniform.semantic ) { +case "MODELVIEW": +var m4 = boundUniform.uniform.value; +m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); +break; +case "MODELVIEWINVERSETRANSPOSE": +var m3 = boundUniform.uniform.value; +this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); +m3.getNormalMatrix( this._m4 ); +break; +case "PROJECTION": +var m4 = boundUniform.uniform.value; +m4.copy( camera.projectionMatrix ); +break; +case "JOINTMATRIX": +var m4v = boundUniform.uniform.value; +for ( var mi = 0; mi < m4v.length; mi ++ ) { +m4v[ mi ] +.getInverse( boundUniform.sourceNode.matrixWorld ) +.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld ) +.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] ) +.multiply( boundUniform.targetNode.bindMatrix ); +} +break; +default : +console.warn( "Unhandled shader semantic: " + boundUniform.semantic ); +break; +} +} +}; +/*********************************/ +/********** EXTENSIONS ***********/ +/*********************************/ +var EXTENSIONS = { +KHR_BINARY_GLTF: 'KHR_binary_glTF', +KHR_MATERIALS_COMMON: 'KHR_materials_common' +}; +/* MATERIALS COMMON EXTENSION */ +function GLTFMaterialsCommonExtension( json ) { +this.name = EXTENSIONS.KHR_MATERIALS_COMMON; +this.lights = {}; +var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {}; +var lights = extension.lights || {}; +for ( var lightId in lights ) { +var light = lights[ lightId ]; +var lightNode; +var lightParams = light[ light.type ]; +var color = new THREE.Color().fromArray( lightParams.color ); +switch ( light.type ) { +case "directional": +lightNode = new THREE.DirectionalLight( color ); +lightNode.position.set( 0, 0, 1 ); +break; +case "point": +lightNode = new THREE.PointLight( color ); +break; +case "spot": +lightNode = new THREE.SpotLight( color ); +lightNode.position.set( 0, 0, 1 ); +break; +case "ambient": +lightNode = new THREE.AmbientLight( color ); +break; +} +if ( lightNode ) { +this.lights[ lightId ] = lightNode; +} +} +} +/* BINARY EXTENSION */ +var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF'; +var BINARY_EXTENSION_HEADER_MAGIC = 'glTF'; +var BINARY_EXTENSION_HEADER_LENGTH = 12; +var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 }; +function GLTFBinaryExtension( data ) { +this.name = EXTENSIONS.KHR_BINARY_GLTF; +this.content = null; +this.body = null; +var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); +this.header = { +magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ), +version: headerView.getUint32( 4, true ), +length: headerView.getUint32( 8, true ) +}; +if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) { +throw new Error( 'GLTF2Loader: Unsupported glTF-Binary header.' ); +} else if ( this.header.version < 2.0 ) { +throw new Error( 'GLTF2Loader: Legacy binary file detected. Use GLTFLoader instead.' ); +} +var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH ); +var chunkIndex = 0; +while ( chunkIndex < chunkView.byteLength ) { +var chunkLength = chunkView.getUint32( chunkIndex, true ); +chunkIndex += 4; +var chunkType = chunkView.getUint32( chunkIndex, true ); +chunkIndex += 4; +if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) { +var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength ); +this.content = convertUint8ArrayToString( contentArray ); +} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) { +var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex; +this.body = data.slice( byteOffset, byteOffset + chunkLength ); +} +chunkIndex += chunkLength; +} +if ( this.content === null ) { +throw new Error( 'GLTF2Loader: JSON content not found.' ); +} +} +/*********************************/ +/********** INTERNALS ************/ +/*********************************/ +/* CONSTANTS */ +var WEBGL_CONSTANTS = { +FLOAT: 5126, +FLOAT_MAT3: 35675, +FLOAT_MAT4: 35676, +FLOAT_VEC2: 35664, +FLOAT_VEC3: 35665, +FLOAT_VEC4: 35666, +LINEAR: 9729, +REPEAT: 10497, +SAMPLER_2D: 35678, +TRIANGLES: 4, +LINES: 1, +UNSIGNED_BYTE: 5121, +UNSIGNED_SHORT: 5123, +VERTEX_SHADER: 35633, +FRAGMENT_SHADER: 35632 +}; +var WEBGL_TYPE = { +5126: Number, +35675: THREE.Matrix3, +35676: THREE.Matrix4, +35664: THREE.Vector2, +35665: THREE.Vector3, +35666: THREE.Vector4, +35678: THREE.Texture +}; +var WEBGL_COMPONENT_TYPES = { +5120: Int8Array, +5121: Uint8Array, +5122: Int16Array, +5123: Uint16Array, +5125: Uint32Array, +5126: Float32Array +}; +var WEBGL_FILTERS = { +9728: THREE.NearestFilter, +9729: THREE.LinearFilter, +9984: THREE.NearestMipMapNearestFilter, +9985: THREE.LinearMipMapNearestFilter, +9986: THREE.NearestMipMapLinearFilter, +9987: THREE.LinearMipMapLinearFilter +}; +var WEBGL_WRAPPINGS = { +33071: THREE.ClampToEdgeWrapping, +33648: THREE.MirroredRepeatWrapping, +10497: THREE.RepeatWrapping +}; +var WEBGL_TEXTURE_FORMATS = { +6406: THREE.AlphaFormat, +6407: THREE.RGBFormat, +6408: THREE.RGBAFormat, +6409: THREE.LuminanceFormat, +6410: THREE.LuminanceAlphaFormat +}; +var WEBGL_TEXTURE_DATATYPES = { +5121: THREE.UnsignedByteType, +32819: THREE.UnsignedShort4444Type, +32820: THREE.UnsignedShort5551Type, +33635: THREE.UnsignedShort565Type +}; +var WEBGL_SIDES = { +1028: THREE.BackSide, // Culling front +1029: THREE.FrontSide // Culling back +}; +var WEBGL_DEPTH_FUNCS = { +512: THREE.NeverDepth, +513: THREE.LessDepth, +514: THREE.EqualDepth, +515: THREE.LessEqualDepth, +516: THREE.GreaterEqualDepth, +517: THREE.NotEqualDepth, +518: THREE.GreaterEqualDepth, +519: THREE.AlwaysDepth +}; +var WEBGL_BLEND_EQUATIONS = { +32774: THREE.AddEquation, +32778: THREE.SubtractEquation, +32779: THREE.ReverseSubtractEquation +}; +var WEBGL_BLEND_FUNCS = { +0: THREE.ZeroFactor, +1: THREE.OneFactor, +768: THREE.SrcColorFactor, +769: THREE.OneMinusSrcColorFactor, +770: THREE.SrcAlphaFactor, +771: THREE.OneMinusSrcAlphaFactor, +772: THREE.DstAlphaFactor, +773: THREE.OneMinusDstAlphaFactor, +774: THREE.DstColorFactor, +775: THREE.OneMinusDstColorFactor, +776: THREE.SrcAlphaSaturateFactor +}; +var WEBGL_TYPE_SIZES = { +'SCALAR': 1, +'VEC2': 2, +'VEC3': 3, +'VEC4': 4, +'MAT2': 4, +'MAT3': 9, +'MAT4': 16 +}; +var PATH_PROPERTIES = { +scale: 'scale', +translation: 'position', +rotation: 'quaternion' +}; +var INTERPOLATION = { +LINEAR: THREE.InterpolateLinear, +STEP: THREE.InterpolateDiscrete +}; +var STATES_ENABLES = { +2884: 'CULL_FACE', +2929: 'DEPTH_TEST', +3042: 'BLEND', +3089: 'SCISSOR_TEST', +32823: 'POLYGON_OFFSET_FILL', +32926: 'SAMPLE_ALPHA_TO_COVERAGE' +}; +/* UTILITY FUNCTIONS */ +function _each( object, callback, thisObj ) { +if ( !object ) { +return Promise.resolve(); +} +var results; +var fns = []; +if ( Object.prototype.toString.call( object ) === '[object Array]' ) { +results = []; +var length = object.length; +for ( var idx = 0; idx < length; idx ++ ) { +var value = callback.call( thisObj || this, object[ idx ], idx ); +if ( value ) { +fns.push( value ); +if ( value instanceof Promise ) { +value.then( function( key, value ) { +results[ key ] = value; +}.bind( this, idx )); +} else { +results[ idx ] = value; +} +} +} +} else { +results = {}; +for ( var key in object ) { +if ( object.hasOwnProperty( key ) ) { +var value = callback.call( thisObj || this, object[ key ], key ); +if ( value ) { +fns.push( value ); +if ( value instanceof Promise ) { +value.then( function( key, value ) { +results[ key ] = value; +}.bind( this, key )); +} else { +results[ key ] = value; +} +} +} +} +} +return Promise.all( fns ).then( function() { +return results; +}); +} +function resolveURL( url, path ) { +if ( typeof url !== 'string' || url === '' ) +return ''; +if ( /^(https?:)?\/\//i.test( url ) ) { +return url; +} +if ( /^data:.*,.*$/i.test( url ) ) { +return url; +} +if ( /^blob:.*$/i.test( url ) ) { +return url; +} +return ( path || '' ) + url; +} +function convertUint8ArrayToString( array ) { +var s = ''; +for ( var i = 0; i < array.length; i ++ ) { +s += String.fromCharCode( array[ i ] ); +} +return s; +} +function replaceTHREEShaderAttributes( shaderText, technique ) { +var attributes = {}; +for ( var attributeId in technique.attributes ) { +var pname = technique.attributes[ attributeId ]; +var param = technique.parameters[ pname ]; +var atype = param.type; +var semantic = param.semantic; +attributes[ attributeId ] = { +type: atype, +semantic: semantic +}; +} +var shaderParams = technique.parameters; +var shaderAttributes = technique.attributes; +var params = {}; +for ( var attributeId in attributes ) { +var pname = shaderAttributes[ attributeId ]; +var shaderParam = shaderParams[ pname ]; +var semantic = shaderParam.semantic; +if ( semantic ) { +params[ attributeId ] = shaderParam; +} +} +for ( var pname in params ) { +var param = params[ pname ]; +var semantic = param.semantic; +var regEx = new RegExp( "\\b" + pname + "\\b", "g" ); +switch ( semantic ) { +case 'POSITION': +shaderText = shaderText.replace( regEx, 'position' ); +break; +case 'NORMAL': +shaderText = shaderText.replace( regEx, 'normal' ); +break; +case 'TEXCOORD_0': +case 'TEXCOORD0': +case 'TEXCOORD': +shaderText = shaderText.replace( regEx, 'uv' ); +break; +case 'TEXCOORD_1': +shaderText = shaderText.replace( regEx, 'uv2' ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +shaderText = shaderText.replace( regEx, 'color' ); +break; +case 'WEIGHTS_0': +case 'WEIGHT': // WEIGHT semantic deprecated. +shaderText = shaderText.replace( regEx, 'skinWeight' ); +break; +case 'JOINTS_0': +case 'JOINT': // JOINT semantic deprecated. +shaderText = shaderText.replace( regEx, 'skinIndex' ); +break; +} +} +return shaderText; +} +function createDefaultMaterial() { +return new THREE.MeshPhongMaterial( { +color: 0x00000, +emissive: 0x888888, +specular: 0x000000, +shininess: 0, +transparent: false, +depthTest: true, +side: THREE.FrontSide +} ); +} +function DeferredShaderMaterial( params ) { +this.isDeferredShaderMaterial = true; +this.params = params; +} +DeferredShaderMaterial.prototype.create = function () { +var uniforms = THREE.UniformsUtils.clone( this.params.uniforms ); +for ( var uniformId in this.params.uniforms ) { +var originalUniform = this.params.uniforms[ uniformId ]; +if ( originalUniform.value instanceof THREE.Texture ) { +uniforms[ uniformId ].value = originalUniform.value; +uniforms[ uniformId ].value.needsUpdate = true; +} +uniforms[ uniformId ].semantic = originalUniform.semantic; +uniforms[ uniformId ].node = originalUniform.node; +} +this.params.uniforms = uniforms; +return new THREE.RawShaderMaterial( this.params ); +}; +/* GLTF PARSER */ +function GLTFParser( json, extensions, options ) { +this.json = json || {}; +this.extensions = extensions || {}; +this.options = options || {}; +this.cache = new GLTFRegistry(); +} +GLTFParser.prototype._withDependencies = function ( dependencies ) { +var _dependencies = {}; +for ( var i = 0; i < dependencies.length; i ++ ) { +var dependency = dependencies[ i ]; +var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 ); +var cached = this.cache.get( dependency ); +if ( cached !== undefined ) { +_dependencies[ dependency ] = cached; +} else if ( this[ fnName ] ) { +var fn = this[ fnName ](); +this.cache.add( dependency, fn ); +_dependencies[ dependency ] = fn; +} +} +return _each( _dependencies, function ( dependency ) { +return dependency; +} ); +}; +GLTFParser.prototype.parse = function ( callback ) { +var json = this.json; +this.cache.removeAll(); +this._withDependencies( [ +"scenes", +"cameras", +"animations" +] ).then( function ( dependencies ) { +var scenes = []; +for ( var name in dependencies.scenes ) { +scenes.push( dependencies.scenes[ name ] ); +} +var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ]; +var cameras = []; +for ( var name in dependencies.cameras ) { +var camera = dependencies.cameras[ name ]; +cameras.push( camera ); +} +var animations = []; +for ( var name in dependencies.animations ) { +animations.push( dependencies.animations[ name ] ); +} +callback( scene, scenes, cameras, animations ); +} ); +}; +GLTFParser.prototype.loadShaders = function () { +var json = this.json; +var options = this.options; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.shaders, function ( shader ) { +if ( shader.bufferView !== undefined ) { +var bufferView = dependencies.bufferViews[ shader.bufferView ]; +var array = new Uint8Array( bufferView ); +return convertUint8ArrayToString( array ); +} +return new Promise( function ( resolve ) { +var loader = new THREE.FileLoader(); +loader.setResponseType( 'text' ); +loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) { +resolve( shaderText ); +} ); +} ); +} ); +} ); +}; +GLTFParser.prototype.loadBuffers = function () { +var json = this.json; +var extensions = this.extensions; +var options = this.options; +return _each( json.buffers, function ( buffer, name ) { +if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) { +if ( buffer.uri === undefined && name === 0 ) { +return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body; +} +return new Promise( function ( resolve ) { +var loader = new THREE.FileLoader(); +loader.setResponseType( 'arraybuffer' ); +loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) { +resolve( buffer ); +} ); +} ); +} else { +console.warn( 'THREE.GLTF2Loader: ' + buffer.type + ' buffer type is not supported' ); +} +} ); +}; +GLTFParser.prototype.loadBufferViews = function () { +var json = this.json; +return this._withDependencies( [ +"buffers" +] ).then( function ( dependencies ) { +return _each( json.bufferViews, function ( bufferView ) { +var arraybuffer = dependencies.buffers[ bufferView.buffer ]; +var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0; +return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength ); +} ); +} ); +}; +GLTFParser.prototype.loadAccessors = function () { +var json = this.json; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.accessors, function ( accessor ) { +var arraybuffer = dependencies.bufferViews[ accessor.bufferView ]; +var itemSize = WEBGL_TYPE_SIZES[ accessor.type ]; +var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ]; +var elementBytes = TypedArray.BYTES_PER_ELEMENT; +var itemBytes = elementBytes * itemSize; +var array; +if ( accessor.byteStride && accessor.byteStride !== itemBytes ) { +array = new TypedArray( arraybuffer ); +var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes ); +return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes ); +} else { +array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize ); +return new THREE.BufferAttribute( array, itemSize ); +} +} ); +} ); +}; +GLTFParser.prototype.loadTextures = function () { +var json = this.json; +var options = this.options; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.textures, function ( texture ) { +if ( texture.source !== undefined ) { +return new Promise( function ( resolve ) { +var source = json.images[ texture.source ]; +var sourceUri = source.uri; +var urlCreator; +if ( source.bufferView !== undefined ) { +var bufferView = dependencies.bufferViews[ source.bufferView ]; +var blob = new Blob( [ bufferView ], { type: source.mimeType } ); +urlCreator = window.URL || window.webkitURL; +sourceUri = urlCreator.createObjectURL( blob ); +} +var textureLoader = THREE.Loader.Handlers.get( sourceUri ); +if ( textureLoader === null ) { +textureLoader = new THREE.TextureLoader(); +} +textureLoader.setCrossOrigin( options.crossOrigin ); +textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) { +if ( urlCreator !== undefined ) { +urlCreator.revokeObjectURL( sourceUri ); +} +_texture.flipY = false; +if ( texture.name !== undefined ) _texture.name = texture.name; +_texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat; +if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) { +console.warn( 'THREE.GLTF2Loader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' + +'internalFormat will be forced to be the same value as format.' ); +} +_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType; +if ( texture.sampler !== undefined ) { +var sampler = json.samplers[ texture.sampler ]; +_texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter; +_texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipMapLinearFilter; +_texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping; +_texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping; +} +resolve( _texture ); +}, undefined, function () { +resolve(); +} ); +} ); +} +} ); +} ); +}; +GLTFParser.prototype.loadMaterials = function () { +var json = this.json; +return this._withDependencies( [ +"shaders", +"textures" +] ).then( function ( dependencies ) { +return _each( json.materials, function ( material ) { +var materialType; +var materialValues = {}; +var materialParams = {}; +var khr_material; +if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) { +khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]; +} +if ( khr_material ) { +var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ]; +switch ( khr_material.technique ) { +case 'BLINN' : +case 'PHONG' : +materialType = THREE.MeshPhongMaterial; +keys.push( 'diffuse', 'specular', 'shininess' ); +break; +case 'LAMBERT' : +materialType = THREE.MeshLambertMaterial; +keys.push( 'diffuse' ); +break; +case 'CONSTANT' : +default : +materialType = THREE.MeshBasicMaterial; +break; +} +keys.forEach( function( v ) { +if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ]; +} ); +if ( khr_material.doubleSided || materialValues.doubleSided ) { +materialParams.side = THREE.DoubleSide; +} +if ( khr_material.transparent || materialValues.transparent ) { +materialParams.transparent = true; +materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1; +} +} else if ( material.technique === undefined ) { +if ( material.pbrMetallicRoughness !== undefined ) { +materialType = THREE.MeshStandardMaterial; +if ( material.pbrMetallicRoughness !== undefined ) { +var metallicRoughness = material.pbrMetallicRoughness; +materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 ); +materialParams.opacity = 1.0; +if ( Array.isArray( metallicRoughness.baseColorFactor ) ) { +var array = metallicRoughness.baseColorFactor; +materialParams.color.fromArray( array ); +materialParams.opacity = array[ 3 ]; +} +if ( metallicRoughness.baseColorTexture !== undefined ) { +materialParams.map = dependencies.textures[ metallicRoughness.baseColorTexture.index ]; +} +if ( materialParams.opacity < 1.0 || +( materialParams.map !== undefined && +( materialParams.map.format === THREE.AlphaFormat || +materialParams.map.format === THREE.RGBAFormat || +materialParams.map.format === THREE.LuminanceAlphaFormat ) ) ) { +materialParams.transparent = true; +} +materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0; +materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0; +if ( metallicRoughness.metallicRoughnessTexture !== undefined ) { +var textureIndex = metallicRoughness.metallicRoughnessTexture.index; +materialParams.metalnessMap = dependencies.textures[ textureIndex ]; +materialParams.roughnessMap = dependencies.textures[ textureIndex ]; +} +} +} else { +materialType = THREE.MeshPhongMaterial; +} +if ( material.normalTexture !== undefined ) { +materialParams.normalMap = dependencies.textures[ material.normalTexture.index ]; +} +if ( material.occlusionTexture !== undefined ) { +materialParams.aoMap = dependencies.textures[ material.occlusionTexture.index ]; +} +if ( material.emissiveTexture !== undefined ) { +materialParams.emissiveMap = dependencies.textures[ material.emissiveTexture.index ]; +} +materialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 ); +if ( material.emissiveFactor !== undefined ) { +materialParams.emissive.fromArray( material.emissiveFactor ); +} +Object.assign( materialValues, material.values ); +} else { +materialType = DeferredShaderMaterial; +var technique = json.techniques[ material.technique ]; +materialParams.uniforms = {}; +var program = json.programs[ technique.program ]; +if ( program ) { +materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ]; +if ( ! materialParams.fragmentShader ) { +console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader ); +materialType = THREE.MeshPhongMaterial; +} +var vertexShader = dependencies.shaders[ program.vertexShader ]; +if ( ! vertexShader ) { +console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader ); +materialType = THREE.MeshPhongMaterial; +} +materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique ); +var uniforms = technique.uniforms; +for ( var uniformId in uniforms ) { +var pname = uniforms[ uniformId ]; +var shaderParam = technique.parameters[ pname ]; +var ptype = shaderParam.type; +if ( WEBGL_TYPE[ ptype ] ) { +var pcount = shaderParam.count; +var value; +if ( material.values !== undefined ) value = material.values[ pname ]; +var uvalue = new WEBGL_TYPE[ ptype ](); +var usemantic = shaderParam.semantic; +var unode = shaderParam.node; +switch ( ptype ) { +case WEBGL_CONSTANTS.FLOAT: +uvalue = shaderParam.value; +if ( pname == "transparency" ) { +materialParams.transparent = true; +} +if ( value !== undefined ) { +uvalue = value; +} +break; +case WEBGL_CONSTANTS.FLOAT_VEC2: +case WEBGL_CONSTANTS.FLOAT_VEC3: +case WEBGL_CONSTANTS.FLOAT_VEC4: +case WEBGL_CONSTANTS.FLOAT_MAT3: +if ( shaderParam && shaderParam.value ) { +uvalue.fromArray( shaderParam.value ); +} +if ( value ) { +uvalue.fromArray( value ); +} +break; +case WEBGL_CONSTANTS.FLOAT_MAT2: +console.warn( "FLOAT_MAT2 is not a supported uniform type" ); +break; +case WEBGL_CONSTANTS.FLOAT_MAT4: +if ( pcount ) { +uvalue = new Array( pcount ); +for ( var mi = 0; mi < pcount; mi ++ ) { +uvalue[ mi ] = new WEBGL_TYPE[ ptype ](); +} +if ( shaderParam && shaderParam.value ) { +var m4v = shaderParam.value; +uvalue.fromArray( m4v ); +} +if ( value ) { +uvalue.fromArray( value ); +} +} else { +if ( shaderParam && shaderParam.value ) { +var m4 = shaderParam.value; +uvalue.fromArray( m4 ); +} +if ( value ) { +uvalue.fromArray( value ); +} +} +break; +case WEBGL_CONSTANTS.SAMPLER_2D: +if ( value !== undefined ) { +uvalue = dependencies.textures[ value ]; +} else if ( shaderParam.value !== undefined ) { +uvalue = dependencies.textures[ shaderParam.value ]; +} else { +uvalue = null; +} +break; +} +materialParams.uniforms[ uniformId ] = { +value: uvalue, +semantic: usemantic, +node: unode +}; +} else { +throw new Error( "Unknown shader uniform param type: " + ptype ); +} +} +var states = technique.states || {}; +var enables = states.enable || []; +var functions = states.functions || {}; +var enableCullFace = false; +var enableDepthTest = false; +var enableBlend = false; +for ( var i = 0, il = enables.length; i < il; i ++ ) { +var enable = enables[ i ]; +switch ( STATES_ENABLES[ enable ] ) { +case 'CULL_FACE': +enableCullFace = true; +break; +case 'DEPTH_TEST': +enableDepthTest = true; +break; +case 'BLEND': +enableBlend = true; +break; +case 'SCISSOR_TEST': +case 'POLYGON_OFFSET_FILL': +case 'SAMPLE_ALPHA_TO_COVERAGE': +break; +default: +throw new Error( "Unknown technique.states.enable: " + enable ); +} +} +if ( enableCullFace ) { +materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide; +} else { +materialParams.side = THREE.DoubleSide; +} +materialParams.depthTest = enableDepthTest; +materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth; +materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true; +materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending; +materialParams.transparent = enableBlend; +var blendEquationSeparate = functions.blendEquationSeparate; +if ( blendEquationSeparate !== undefined ) { +materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ]; +materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ]; +} else { +materialParams.blendEquation = THREE.AddEquation; +materialParams.blendEquationAlpha = THREE.AddEquation; +} +var blendFuncSeparate = functions.blendFuncSeparate; +if ( blendFuncSeparate !== undefined ) { +materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ]; +materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ]; +materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ]; +materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ]; +} else { +materialParams.blendSrc = THREE.OneFactor; +materialParams.blendDst = THREE.ZeroFactor; +materialParams.blendSrcAlpha = THREE.OneFactor; +materialParams.blendDstAlpha = THREE.ZeroFactor; +} +} +} +if ( Array.isArray( materialValues.diffuse ) ) { +materialParams.color = new THREE.Color().fromArray( materialValues.diffuse ); +} else if ( typeof( materialValues.diffuse ) === 'string' ) { +materialParams.map = dependencies.textures[ materialValues.diffuse ]; +} +delete materialParams.diffuse; +if ( typeof( materialValues.reflective ) === 'string' ) { +materialParams.envMap = dependencies.textures[ materialValues.reflective ]; +} +if ( typeof( materialValues.bump ) === 'string' ) { +materialParams.bumpMap = dependencies.textures[ materialValues.bump ]; +} +if ( Array.isArray( materialValues.emission ) ) { +if ( materialType === THREE.MeshBasicMaterial ) { +materialParams.color = new THREE.Color().fromArray( materialValues.emission ); +} else { +materialParams.emissive = new THREE.Color().fromArray( materialValues.emission ); +} +} else if ( typeof( materialValues.emission ) === 'string' ) { +if ( materialType === THREE.MeshBasicMaterial ) { +materialParams.map = dependencies.textures[ materialValues.emission ]; +} else { +materialParams.emissiveMap = dependencies.textures[ materialValues.emission ]; +} +} +if ( Array.isArray( materialValues.specular ) ) { +materialParams.specular = new THREE.Color().fromArray( materialValues.specular ); +} else if ( typeof( materialValues.specular ) === 'string' ) { +materialParams.specularMap = dependencies.textures[ materialValues.specular ]; +} +if ( materialValues.shininess !== undefined ) { +materialParams.shininess = materialValues.shininess; +} +var _material = new materialType( materialParams ); +if ( material.name !== undefined ) _material.name = material.name; +return _material; +} ); +} ); +}; +GLTFParser.prototype.loadMeshes = function () { +var json = this.json; +return this._withDependencies( [ +"accessors", +"materials" +] ).then( function ( dependencies ) { +return _each( json.meshes, function ( mesh ) { +var group = new THREE.Group(); +if ( mesh.name !== undefined ) group.name = mesh.name; +if ( mesh.extras ) group.userData = mesh.extras; +var primitives = mesh.primitives || []; +for ( var name in primitives ) { +var primitive = primitives[ name ]; +var material = primitive.material !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial(); +var geometry; +var meshNode; +if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) { +geometry = new THREE.BufferGeometry(); +var attributes = primitive.attributes; +for ( var attributeId in attributes ) { +var attributeEntry = attributes[ attributeId ]; +if ( attributeEntry === undefined ) return; +var bufferAttribute = dependencies.accessors[ attributeEntry ]; +switch ( attributeId ) { +case 'POSITION': +geometry.addAttribute( 'position', bufferAttribute ); +break; +case 'NORMAL': +geometry.addAttribute( 'normal', bufferAttribute ); +break; +case 'TEXCOORD_0': +case 'TEXCOORD0': +case 'TEXCOORD': +geometry.addAttribute( 'uv', bufferAttribute ); +break; +case 'TEXCOORD_1': +geometry.addAttribute( 'uv2', bufferAttribute ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +geometry.addAttribute( 'color', bufferAttribute ); +break; +case 'WEIGHTS_0': +case 'WEIGHT': // WEIGHT semantic deprecated. +geometry.addAttribute( 'skinWeight', bufferAttribute ); +break; +case 'JOINTS_0': +case 'JOINT': // JOINT semantic deprecated. +geometry.addAttribute( 'skinIndex', bufferAttribute ); +break; +} +} +if ( primitive.indices !== undefined ) { +geometry.setIndex( dependencies.accessors[ primitive.indices ] ); +} +meshNode = new THREE.Mesh( geometry, material ); +meshNode.castShadow = true; +} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) { +geometry = new THREE.BufferGeometry(); +var attributes = primitive.attributes; +for ( var attributeId in attributes ) { +var attributeEntry = attributes[ attributeId ]; +if ( ! attributeEntry ) return; +var bufferAttribute = dependencies.accessors[ attributeEntry ]; +switch ( attributeId ) { +case 'POSITION': +geometry.addAttribute( 'position', bufferAttribute ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +geometry.addAttribute( 'color', bufferAttribute ); +break; +} +} +if ( primitive.indices !== undefined ) { +geometry.setIndex( dependencies.accessors[ primitive.indices ] ); +meshNode = new THREE.LineSegments( geometry, material ); +} else { +meshNode = new THREE.Line( geometry, material ); +} +} else { +throw new Error( "Only triangular and line primitives are supported" ); +} +if ( geometry.attributes.color !== undefined ) { +material.vertexColors = THREE.VertexColors; +material.needsUpdate = true; +} +meshNode.name = ( name === "0" ? group.name : group.name + name ); +if ( primitive.extras ) meshNode.userData = primitive.extras; +group.add( meshNode ); +} +return group; +} ); +} ); +}; +GLTFParser.prototype.loadCameras = function () { +var json = this.json; +return _each( json.cameras, function ( camera ) { +if ( camera.type == "perspective" && camera.perspective ) { +var yfov = camera.perspective.yfov; +var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1; +var xfov = yfov * aspectRatio; +var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 ); +if ( camera.name !== undefined ) _camera.name = camera.name; +if ( camera.extras ) _camera.userData = camera.extras; +return _camera; +} else if ( camera.type == "orthographic" && camera.orthographic ) { +var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar ); +if ( camera.name !== undefined ) _camera.name = camera.name; +if ( camera.extras ) _camera.userData = camera.extras; +return _camera; +} +} ); +}; +GLTFParser.prototype.loadSkins = function () { +var json = this.json; +return this._withDependencies( [ +"accessors" +] ).then( function ( dependencies ) { +return _each( json.skins, function ( skin ) { +var bindShapeMatrix = new THREE.Matrix4(); +if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix ); +var _skin = { +bindShapeMatrix: bindShapeMatrix, +jointNames: skin.jointNames, +inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ] +}; +return _skin; +} ); +} ); +}; +GLTFParser.prototype.loadAnimations = function () { +var json = this.json; +return this._withDependencies( [ +"accessors", +"nodes" +] ).then( function ( dependencies ) { +return _each( json.animations, function ( animation, animationId ) { +var tracks = []; +for ( var channelId in animation.channels ) { +var channel = animation.channels[ channelId ]; +var sampler = animation.samplers[ channel.sampler ]; +if ( sampler ) { +var target = channel.target; +var name = target.node || target.id; // NOTE: target.id is deprecated. +var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input; +var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output; +var inputAccessor = dependencies.accessors[ input ]; +var outputAccessor = dependencies.accessors[ output ]; +var node = dependencies.nodes[ name ]; +if ( node ) { +node.updateMatrix(); +node.matrixAutoUpdate = true; +var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation +? THREE.QuaternionKeyframeTrack +: THREE.VectorKeyframeTrack; +var targetName = node.name ? node.name : node.uuid; +var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear; +tracks.push( new TypedKeyframeTrack( +targetName + '.' + PATH_PROPERTIES[ target.path ], +THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ), +THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ), +interpolation +) ); +} +} +} +var name = animation.name !== undefined ? animation.name : "animation_" + animationId; +return new THREE.AnimationClip( name, undefined, tracks ); +} ); +} ); +}; +GLTFParser.prototype.loadNodes = function () { +var json = this.json; +var extensions = this.extensions; +var scope = this; +return _each( json.nodes, function ( node ) { +var matrix = new THREE.Matrix4(); +var _node; +if ( node.jointName ) { +_node = new THREE.Bone(); +_node.name = node.name !== undefined ? node.name : node.jointName; +_node.jointName = node.jointName; +} else { +_node = new THREE.Object3D(); +if ( node.name !== undefined ) _node.name = node.name; +} +if ( node.extras ) _node.userData = node.extras; +if ( node.matrix !== undefined ) { +matrix.fromArray( node.matrix ); +_node.applyMatrix( matrix ); +} else { +if ( node.translation !== undefined ) { +_node.position.fromArray( node.translation ); +} +if ( node.rotation !== undefined ) { +_node.quaternion.fromArray( node.rotation ); +} +if ( node.scale !== undefined ) { +_node.scale.fromArray( node.scale ); +} +} +return _node; +} ).then( function ( __nodes ) { +return scope._withDependencies( [ +"meshes", +"skins", +"cameras" +] ).then( function ( dependencies ) { +return _each( __nodes, function ( _node, nodeId ) { +var node = json.nodes[ nodeId ]; +var meshes; +if ( node.mesh !== undefined) { +meshes = [ node.mesh ]; +} else if ( node.meshes !== undefined ) { +console.warn( 'GLTF2Loader: Legacy glTF file detected. Nodes may have no more than 1 mesh.' ); +meshes = node.meshes; +} +if ( meshes !== undefined ) { +for ( var meshId in meshes ) { +var mesh = meshes[ meshId ]; +var group = dependencies.meshes[ mesh ]; +if ( group === undefined ) { +console.warn( 'GLTF2Loader: Couldn\'t find node "' + mesh + '".' ); +continue; +} +for ( var childrenId in group.children ) { +var child = group.children[ childrenId ]; +var originalMaterial = child.material; +var originalGeometry = child.geometry; +var originalUserData = child.userData; +var originalName = child.name; +var material; +if ( originalMaterial.isDeferredShaderMaterial ) { +originalMaterial = material = originalMaterial.create(); +} else { +material = originalMaterial; +} +switch ( child.type ) { +case 'LineSegments': +child = new THREE.LineSegments( originalGeometry, material ); +break; +case 'LineLoop': +child = new THREE.LineLoop( originalGeometry, material ); +break; +case 'Line': +child = new THREE.Line( originalGeometry, material ); +break; +default: +child = new THREE.Mesh( originalGeometry, material ); +} +child.castShadow = true; +child.userData = originalUserData; +child.name = originalName; +var skinEntry; +if ( node.skin !== undefined ) { +skinEntry = dependencies.skins[ node.skin ]; +} +if ( skinEntry ) { +var getJointNode = function ( jointId ) { +var keys = Object.keys( __nodes ); +for ( var i = 0, il = keys.length; i < il; i ++ ) { +var n = __nodes[ keys[ i ] ]; +if ( n.jointName === jointId ) return n; +} +return null; +}; +var geometry = originalGeometry; +var material = originalMaterial; +material.skinning = true; +child = new THREE.SkinnedMesh( geometry, material, false ); +child.castShadow = true; +child.userData = originalUserData; +child.name = originalName; +var bones = []; +var boneInverses = []; +for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) { +var jointId = skinEntry.jointNames[ i ]; +var jointNode = getJointNode( jointId ); +if ( jointNode ) { +bones.push( jointNode ); +var m = skinEntry.inverseBindMatrices.array; +var mat = new THREE.Matrix4().fromArray( m, i * 16 ); +boneInverses.push( mat ); +} else { +console.warn( "WARNING: joint: '" + jointId + "' could not be found" ); +} +} +child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix ); +var buildBoneGraph = function ( parentJson, parentObject, property ) { +var children = parentJson[ property ]; +if ( children === undefined ) return; +for ( var i = 0, il = children.length; i < il; i ++ ) { +var nodeId = children[ i ]; +var bone = __nodes[ nodeId ]; +var boneJson = json.nodes[ nodeId ]; +if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) { +parentObject.add( bone ); +buildBoneGraph( boneJson, bone, 'children' ); +} +} +}; +buildBoneGraph( node, child, 'skeletons' ); +} +_node.add( child ); +} +} +} +if ( node.camera !== undefined ) { +var camera = dependencies.cameras[ node.camera ]; +_node.add( camera ); +} +if ( node.extensions +&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] +&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) { +var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights; +var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ]; +_node.add( light ); +} +return _node; +} ); +} ); +} ); +}; +GLTFParser.prototype.loadScenes = function () { +var json = this.json; +function buildNodeHierachy( nodeId, parentObject, allNodes ) { +var _node = allNodes[ nodeId ]; +parentObject.add( _node ); +var node = json.nodes[ nodeId ]; +if ( node.children ) { +var children = node.children; +for ( var i = 0, l = children.length; i < l; i ++ ) { +var child = children[ i ]; +buildNodeHierachy( child, _node, allNodes ); +} +} +} +return this._withDependencies( [ +"nodes" +] ).then( function ( dependencies ) { +return _each( json.scenes, function ( scene ) { +var _scene = new THREE.Scene(); +if ( scene.name !== undefined ) _scene.name = scene.name; +if ( scene.extras ) _scene.userData = scene.extras; +var nodes = scene.nodes || []; +for ( var i = 0, l = nodes.length; i < l; i ++ ) { +var nodeId = nodes[ i ]; +buildNodeHierachy( nodeId, _scene, dependencies.nodes ); +} +_scene.traverse( function ( child ) { +if ( child.material && child.material.isRawShaderMaterial ) { +child.gltfShader = new GLTFShader( child, dependencies.nodes ); +child.onBeforeRender = function(renderer, scene, camera){ +this.gltfShader.update(scene, camera); +}; +} +} ); +return _scene; +} ); +} ); +}; +return GLTF2Loader; +} )(); +/** +* @author Rich Tibbett / https://github.com/richtr +* @author mrdoob / http://mrdoob.com/ +* @author Tony Parisi / http://www.tonyparisi.com/ +* @author Takahiro / https://github.com/takahirox +*/ +THREE.GLTFLoader = ( function () { +function GLTFLoader( manager ) { +this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; +} +GLTFLoader.prototype = { +constructor: GLTFLoader, +load: function ( url, onLoad, onProgress, onError ) { +var scope = this; +var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url ); +var loader = new THREE.FileLoader( scope.manager ); +loader.setResponseType( 'arraybuffer' ); +loader.load( url, function ( data ) { +scope.parse( data, onLoad, path ); +}, onProgress, onError ); +}, +setCrossOrigin: function ( value ) { +this.crossOrigin = value; +}, +setPath: function ( value ) { +this.path = value; +}, +parse: function ( data, callback, path ) { +var content; +var extensions = {}; +var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) ); +if ( magic === BINARY_EXTENSION_HEADER_DEFAULTS.magic ) { +extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data ); +content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content; +} else { +content = convertUint8ArrayToString( new Uint8Array( data ) ); +} +var json = JSON.parse( content ); +if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) { +extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json ); +} +console.time( 'GLTFLoader' ); +var parser = new GLTFParser( json, extensions, { +path: path || this.path, +crossOrigin: this.crossOrigin +} ); +parser.parse( function ( scene, scenes, cameras, animations ) { +console.timeEnd( 'GLTFLoader' ); +var glTF = { +"scene": scene, +"scenes": scenes, +"cameras": cameras, +"animations": animations +}; +callback( glTF ); +} ); +} +}; +/* GLTFREGISTRY */ +function GLTFRegistry() { +var objects = {}; +return { +get: function ( key ) { +return objects[ key ]; +}, +add: function ( key, object ) { +objects[ key ] = object; +}, +remove: function ( key ) { +delete objects[ key ]; +}, +removeAll: function () { +objects = {}; +}, +update: function ( scene, camera ) { +for ( var name in objects ) { +var object = objects[ name ]; +if ( object.update ) { +object.update( scene, camera ); +} +} +} +}; +} +/* GLTFSHADERS */ +GLTFLoader.Shaders = { +update: function () { +console.warn( 'THREE.GLTFLoader.Shaders has been deprecated, and now updates automatically.' ); +} +}; +/* GLTFSHADER */ +function GLTFShader( targetNode, allNodes ) { +var boundUniforms = {}; +var uniforms = targetNode.material.uniforms; +for ( var uniformId in uniforms ) { +var uniform = uniforms[ uniformId ]; +if ( uniform.semantic ) { +var sourceNodeRef = uniform.node; +var sourceNode = targetNode; +if ( sourceNodeRef ) { +sourceNode = allNodes[ sourceNodeRef ]; +} +boundUniforms[ uniformId ] = { +semantic: uniform.semantic, +sourceNode: sourceNode, +targetNode: targetNode, +uniform: uniform +}; +} +} +this.boundUniforms = boundUniforms; +this._m4 = new THREE.Matrix4(); +} +GLTFShader.prototype.update = function ( scene, camera ) { +var boundUniforms = this.boundUniforms; +for ( var name in boundUniforms ) { +var boundUniform = boundUniforms[ name ]; +switch ( boundUniform.semantic ) { +case "MODELVIEW": +var m4 = boundUniform.uniform.value; +m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); +break; +case "MODELVIEWINVERSETRANSPOSE": +var m3 = boundUniform.uniform.value; +this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld ); +m3.getNormalMatrix( this._m4 ); +break; +case "PROJECTION": +var m4 = boundUniform.uniform.value; +m4.copy( camera.projectionMatrix ); +break; +case "JOINTMATRIX": +var m4v = boundUniform.uniform.value; +for ( var mi = 0; mi < m4v.length; mi ++ ) { +m4v[ mi ] +.getInverse( boundUniform.sourceNode.matrixWorld ) +.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld ) +.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] ) +.multiply( boundUniform.targetNode.bindMatrix ); +} +break; +default : +console.warn( "Unhandled shader semantic: " + boundUniform.semantic ); +break; +} +} +}; +/* ANIMATION */ +GLTFLoader.Animations = { +update: function () { +console.warn( 'THREE.GLTFLoader.Animation has been deprecated. Use THREE.AnimationMixer instead.' ); +} +}; +/*********************************/ +/********** EXTENSIONS ***********/ +/*********************************/ +var EXTENSIONS = { +KHR_BINARY_GLTF: 'KHR_binary_glTF', +KHR_MATERIALS_COMMON: 'KHR_materials_common' +}; +/* MATERIALS COMMON EXTENSION */ +function GLTFMaterialsCommonExtension( json ) { +this.name = EXTENSIONS.KHR_MATERIALS_COMMON; +this.lights = {}; +var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {}; +var lights = extension.lights || {}; +for ( var lightId in lights ) { +var light = lights[ lightId ]; +var lightNode; +var lightParams = light[ light.type ]; +var color = new THREE.Color().fromArray( lightParams.color ); +switch ( light.type ) { +case "directional": +lightNode = new THREE.DirectionalLight( color ); +lightNode.position.set( 0, 0, 1 ); +break; +case "point": +lightNode = new THREE.PointLight( color ); +break; +case "spot": +lightNode = new THREE.SpotLight( color ); +lightNode.position.set( 0, 0, 1 ); +break; +case "ambient": +lightNode = new THREE.AmbientLight( color ); +break; +} +if ( lightNode ) { +this.lights[ lightId ] = lightNode; +} +} +} +/* BINARY EXTENSION */ +var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF'; +var BINARY_EXTENSION_HEADER_DEFAULTS = { magic: 'glTF', version: 1, contentFormat: 0 }; +var BINARY_EXTENSION_HEADER_LENGTH = 20; +function GLTFBinaryExtension( data ) { +this.name = EXTENSIONS.KHR_BINARY_GLTF; +var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH ); +var header = { +magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ), +version: headerView.getUint32( 4, true ), +length: headerView.getUint32( 8, true ), +contentLength: headerView.getUint32( 12, true ), +contentFormat: headerView.getUint32( 16, true ) +}; +for ( var key in BINARY_EXTENSION_HEADER_DEFAULTS ) { +var value = BINARY_EXTENSION_HEADER_DEFAULTS[ key ]; +if ( header[ key ] !== value ) { +throw new Error( 'Unsupported glTF-Binary header: Expected "%s" to be "%s".', key, value ); +} +} +var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH, header.contentLength ); +this.header = header; +this.content = convertUint8ArrayToString( contentArray ); +this.body = data.slice( BINARY_EXTENSION_HEADER_LENGTH + header.contentLength, header.length ); +} +GLTFBinaryExtension.prototype.loadShader = function ( shader, bufferViews ) { +var bufferView = bufferViews[ shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].bufferView ]; +var array = new Uint8Array( bufferView ); +return convertUint8ArrayToString( array ); +}; +GLTFBinaryExtension.prototype.loadTextureSourceUri = function ( source, bufferViews ) { +var metadata = source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ]; +var bufferView = bufferViews[ metadata.bufferView ]; +var stringData = convertUint8ArrayToString( new Uint8Array( bufferView ) ); +return 'data:' + metadata.mimeType + ';base64,' + btoa( stringData ); +}; +/*********************************/ +/********** INTERNALS ************/ +/*********************************/ +/* CONSTANTS */ +var WEBGL_CONSTANTS = { +FLOAT: 5126, +FLOAT_MAT3: 35675, +FLOAT_MAT4: 35676, +FLOAT_VEC2: 35664, +FLOAT_VEC3: 35665, +FLOAT_VEC4: 35666, +LINEAR: 9729, +REPEAT: 10497, +SAMPLER_2D: 35678, +TRIANGLES: 4, +LINES: 1, +UNSIGNED_BYTE: 5121, +UNSIGNED_SHORT: 5123, +VERTEX_SHADER: 35633, +FRAGMENT_SHADER: 35632 +}; +var WEBGL_TYPE = { +5126: Number, +35675: THREE.Matrix3, +35676: THREE.Matrix4, +35664: THREE.Vector2, +35665: THREE.Vector3, +35666: THREE.Vector4, +35678: THREE.Texture +}; +var WEBGL_COMPONENT_TYPES = { +5120: Int8Array, +5121: Uint8Array, +5122: Int16Array, +5123: Uint16Array, +5125: Uint32Array, +5126: Float32Array +}; +var WEBGL_FILTERS = { +9728: THREE.NearestFilter, +9729: THREE.LinearFilter, +9984: THREE.NearestMipMapNearestFilter, +9985: THREE.LinearMipMapNearestFilter, +9986: THREE.NearestMipMapLinearFilter, +9987: THREE.LinearMipMapLinearFilter +}; +var WEBGL_WRAPPINGS = { +33071: THREE.ClampToEdgeWrapping, +33648: THREE.MirroredRepeatWrapping, +10497: THREE.RepeatWrapping +}; +var WEBGL_TEXTURE_FORMATS = { +6406: THREE.AlphaFormat, +6407: THREE.RGBFormat, +6408: THREE.RGBAFormat, +6409: THREE.LuminanceFormat, +6410: THREE.LuminanceAlphaFormat +}; +var WEBGL_TEXTURE_DATATYPES = { +5121: THREE.UnsignedByteType, +32819: THREE.UnsignedShort4444Type, +32820: THREE.UnsignedShort5551Type, +33635: THREE.UnsignedShort565Type +}; +var WEBGL_SIDES = { +1028: THREE.BackSide, // Culling front +1029: THREE.FrontSide // Culling back +}; +var WEBGL_DEPTH_FUNCS = { +512: THREE.NeverDepth, +513: THREE.LessDepth, +514: THREE.EqualDepth, +515: THREE.LessEqualDepth, +516: THREE.GreaterEqualDepth, +517: THREE.NotEqualDepth, +518: THREE.GreaterEqualDepth, +519: THREE.AlwaysDepth +}; +var WEBGL_BLEND_EQUATIONS = { +32774: THREE.AddEquation, +32778: THREE.SubtractEquation, +32779: THREE.ReverseSubtractEquation +}; +var WEBGL_BLEND_FUNCS = { +0: THREE.ZeroFactor, +1: THREE.OneFactor, +768: THREE.SrcColorFactor, +769: THREE.OneMinusSrcColorFactor, +770: THREE.SrcAlphaFactor, +771: THREE.OneMinusSrcAlphaFactor, +772: THREE.DstAlphaFactor, +773: THREE.OneMinusDstAlphaFactor, +774: THREE.DstColorFactor, +775: THREE.OneMinusDstColorFactor, +776: THREE.SrcAlphaSaturateFactor +}; +var WEBGL_TYPE_SIZES = { +'SCALAR': 1, +'VEC2': 2, +'VEC3': 3, +'VEC4': 4, +'MAT2': 4, +'MAT3': 9, +'MAT4': 16 +}; +var PATH_PROPERTIES = { +scale: 'scale', +translation: 'position', +rotation: 'quaternion' +}; +var INTERPOLATION = { +LINEAR: THREE.InterpolateLinear, +STEP: THREE.InterpolateDiscrete +}; +var STATES_ENABLES = { +2884: 'CULL_FACE', +2929: 'DEPTH_TEST', +3042: 'BLEND', +3089: 'SCISSOR_TEST', +32823: 'POLYGON_OFFSET_FILL', +32926: 'SAMPLE_ALPHA_TO_COVERAGE' +}; +/* UTILITY FUNCTIONS */ +function _each( object, callback, thisObj ) { +if ( !object ) { +return Promise.resolve(); +} +var results; +var fns = []; +if ( Object.prototype.toString.call( object ) === '[object Array]' ) { +results = []; +var length = object.length; +for ( var idx = 0; idx < length; idx ++ ) { +var value = callback.call( thisObj || this, object[ idx ], idx ); +if ( value ) { +fns.push( value ); +if ( value instanceof Promise ) { +value.then( function( key, value ) { +results[ key ] = value; +}.bind( this, idx )); +} else { +results[ idx ] = value; +} +} +} +} else { +results = {}; +for ( var key in object ) { +if ( object.hasOwnProperty( key ) ) { +var value = callback.call( thisObj || this, object[ key ], key ); +if ( value ) { +fns.push( value ); +if ( value instanceof Promise ) { +value.then( function( key, value ) { +results[ key ] = value; +}.bind( this, key )); +} else { +results[ key ] = value; +} +} +} +} +} +return Promise.all( fns ).then( function() { +return results; +}); +} +function resolveURL( url, path ) { +if ( typeof url !== 'string' || url === '' ) +return ''; +if ( /^(https?:)?\/\//i.test( url ) ) { +return url; +} +if ( /^data:.*,.*$/i.test( url ) ) { +return url; +} +return ( path || '' ) + url; +} +function convertUint8ArrayToString( array ) { +var s = ''; +for ( var i = 0; i < array.length; i ++ ) { +s += String.fromCharCode( array[ i ] ); +} +return s; +} +function replaceTHREEShaderAttributes( shaderText, technique ) { +var attributes = {}; +for ( var attributeId in technique.attributes ) { +var pname = technique.attributes[ attributeId ]; +var param = technique.parameters[ pname ]; +var atype = param.type; +var semantic = param.semantic; +attributes[ attributeId ] = { +type: atype, +semantic: semantic +}; +} +var shaderParams = technique.parameters; +var shaderAttributes = technique.attributes; +var params = {}; +for ( var attributeId in attributes ) { +var pname = shaderAttributes[ attributeId ]; +var shaderParam = shaderParams[ pname ]; +var semantic = shaderParam.semantic; +if ( semantic ) { +params[ attributeId ] = shaderParam; +} +} +for ( var pname in params ) { +var param = params[ pname ]; +var semantic = param.semantic; +var regEx = new RegExp( "\\b" + pname + "\\b", "g" ); +switch ( semantic ) { +case "POSITION": +shaderText = shaderText.replace( regEx, 'position' ); +break; +case "NORMAL": +shaderText = shaderText.replace( regEx, 'normal' ); +break; +case 'TEXCOORD_0': +case 'TEXCOORD0': +case 'TEXCOORD': +shaderText = shaderText.replace( regEx, 'uv' ); +break; +case 'TEXCOORD_1': +shaderText = shaderText.replace( regEx, 'uv2' ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +shaderText = shaderText.replace( regEx, 'color' ); +break; +case "WEIGHT": +shaderText = shaderText.replace( regEx, 'skinWeight' ); +break; +case "JOINT": +shaderText = shaderText.replace( regEx, 'skinIndex' ); +break; +} +} +return shaderText; +} +function createDefaultMaterial() { +return new THREE.MeshPhongMaterial( { +color: 0x00000, +emissive: 0x888888, +specular: 0x000000, +shininess: 0, +transparent: false, +depthTest: true, +side: THREE.FrontSide +} ); +} +function DeferredShaderMaterial( params ) { +this.isDeferredShaderMaterial = true; +this.params = params; +} +DeferredShaderMaterial.prototype.create = function () { +var uniforms = THREE.UniformsUtils.clone( this.params.uniforms ); +for ( var uniformId in this.params.uniforms ) { +var originalUniform = this.params.uniforms[ uniformId ]; +if ( originalUniform.value instanceof THREE.Texture ) { +uniforms[ uniformId ].value = originalUniform.value; +uniforms[ uniformId ].value.needsUpdate = true; +} +uniforms[ uniformId ].semantic = originalUniform.semantic; +uniforms[ uniformId ].node = originalUniform.node; +} +this.params.uniforms = uniforms; +return new THREE.RawShaderMaterial( this.params ); +}; +/* GLTF PARSER */ +function GLTFParser( json, extensions, options ) { +this.json = json || {}; +this.extensions = extensions || {}; +this.options = options || {}; +this.cache = new GLTFRegistry(); +} +GLTFParser.prototype._withDependencies = function ( dependencies ) { +var _dependencies = {}; +for ( var i = 0; i < dependencies.length; i ++ ) { +var dependency = dependencies[ i ]; +var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 ); +var cached = this.cache.get( dependency ); +if ( cached !== undefined ) { +_dependencies[ dependency ] = cached; +} else if ( this[ fnName ] ) { +var fn = this[ fnName ](); +this.cache.add( dependency, fn ); +_dependencies[ dependency ] = fn; +} +} +return _each( _dependencies, function ( dependency ) { +return dependency; +} ); +}; +GLTFParser.prototype.parse = function ( callback ) { +var json = this.json; +this.cache.removeAll(); +this._withDependencies( [ +"scenes", +"cameras", +"animations" +] ).then( function ( dependencies ) { +var scenes = []; +for ( var name in dependencies.scenes ) { +scenes.push( dependencies.scenes[ name ] ); +} +var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ]; +var cameras = []; +for ( var name in dependencies.cameras ) { +var camera = dependencies.cameras[ name ]; +cameras.push( camera ); +} +var animations = []; +for ( var name in dependencies.animations ) { +animations.push( dependencies.animations[ name ] ); +} +callback( scene, scenes, cameras, animations ); +} ); +}; +GLTFParser.prototype.loadShaders = function () { +var json = this.json; +var extensions = this.extensions; +var options = this.options; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.shaders, function ( shader ) { +if ( shader.extensions && shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) { +return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadShader( shader, dependencies.bufferViews ); +} +return new Promise( function ( resolve ) { +var loader = new THREE.FileLoader(); +loader.setResponseType( 'text' ); +loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) { +resolve( shaderText ); +} ); +} ); +} ); +} ); +}; +GLTFParser.prototype.loadBuffers = function () { +var json = this.json; +var extensions = this.extensions; +var options = this.options; +return _each( json.buffers, function ( buffer, name ) { +if ( name === BINARY_EXTENSION_BUFFER_NAME ) { +return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body; +} +if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) { +return new Promise( function ( resolve ) { +var loader = new THREE.FileLoader(); +loader.setResponseType( 'arraybuffer' ); +loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) { +resolve( buffer ); +} ); +} ); +} else { +console.warn( 'THREE.GLTFLoader: ' + buffer.type + ' buffer type is not supported' ); +} +} ); +}; +GLTFParser.prototype.loadBufferViews = function () { +var json = this.json; +return this._withDependencies( [ +"buffers" +] ).then( function ( dependencies ) { +return _each( json.bufferViews, function ( bufferView ) { +var arraybuffer = dependencies.buffers[ bufferView.buffer ]; +var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0; +return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength ); +} ); +} ); +}; +GLTFParser.prototype.loadAccessors = function () { +var json = this.json; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.accessors, function ( accessor ) { +var arraybuffer = dependencies.bufferViews[ accessor.bufferView ]; +var itemSize = WEBGL_TYPE_SIZES[ accessor.type ]; +var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ]; +var elementBytes = TypedArray.BYTES_PER_ELEMENT; +var itemBytes = elementBytes * itemSize; +if ( accessor.byteStride && accessor.byteStride !== itemBytes ) { +var array = new TypedArray( arraybuffer ); +var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes ); +return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes ); +} else { +array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize ); +return new THREE.BufferAttribute( array, itemSize ); +} +} ); +} ); +}; +GLTFParser.prototype.loadTextures = function () { +var json = this.json; +var extensions = this.extensions; +var options = this.options; +return this._withDependencies( [ +"bufferViews" +] ).then( function ( dependencies ) { +return _each( json.textures, function ( texture ) { +if ( texture.source ) { +return new Promise( function ( resolve ) { +var source = json.images[ texture.source ]; +var sourceUri = source.uri; +if ( source.extensions && source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) { +sourceUri = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadTextureSourceUri( source, dependencies.bufferViews ); +} +var textureLoader = THREE.Loader.Handlers.get( sourceUri ); +if ( textureLoader === null ) { +textureLoader = new THREE.TextureLoader(); +} +textureLoader.setCrossOrigin( options.crossOrigin ); +textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) { +_texture.flipY = false; +if ( texture.name !== undefined ) _texture.name = texture.name; +_texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat; +if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) { +console.warn( 'THREE.GLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' + +'internalFormat will be forced to be the same value as format.' ); +} +_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType; +if ( texture.sampler ) { +var sampler = json.samplers[ texture.sampler ]; +_texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter; +_texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipMapLinearFilter; +_texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping; +_texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping; +} +resolve( _texture ); +}, undefined, function () { +resolve(); +} ); +} ); +} +} ); +} ); +}; +GLTFParser.prototype.loadMaterials = function () { +var json = this.json; +return this._withDependencies( [ +"shaders", +"textures" +] ).then( function ( dependencies ) { +return _each( json.materials, function ( material ) { +var materialType; +var materialValues = {}; +var materialParams = {}; +var khr_material; +if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) { +khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]; +} +if ( khr_material ) { +var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ]; +switch ( khr_material.technique ) { +case 'BLINN' : +case 'PHONG' : +materialType = THREE.MeshPhongMaterial; +keys.push( 'diffuse', 'specular', 'shininess' ); +break; +case 'LAMBERT' : +materialType = THREE.MeshLambertMaterial; +keys.push( 'diffuse' ); +break; +case 'CONSTANT' : +default : +materialType = THREE.MeshBasicMaterial; +break; +} +keys.forEach( function( v ) { +if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ]; +} ); +if ( khr_material.doubleSided || materialValues.doubleSided ) { +materialParams.side = THREE.DoubleSide; +} +if ( khr_material.transparent || materialValues.transparent ) { +materialParams.transparent = true; +materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1; +} +} else if ( material.technique === undefined ) { +materialType = THREE.MeshPhongMaterial; +Object.assign( materialValues, material.values ); +} else { +materialType = DeferredShaderMaterial; +var technique = json.techniques[ material.technique ]; +materialParams.uniforms = {}; +var program = json.programs[ technique.program ]; +if ( program ) { +materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ]; +if ( ! materialParams.fragmentShader ) { +console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader ); +materialType = THREE.MeshPhongMaterial; +} +var vertexShader = dependencies.shaders[ program.vertexShader ]; +if ( ! vertexShader ) { +console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader ); +materialType = THREE.MeshPhongMaterial; +} +materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique ); +var uniforms = technique.uniforms; +for ( var uniformId in uniforms ) { +var pname = uniforms[ uniformId ]; +var shaderParam = technique.parameters[ pname ]; +var ptype = shaderParam.type; +if ( WEBGL_TYPE[ ptype ] ) { +var pcount = shaderParam.count; +var value; +if ( material.values !== undefined ) value = material.values[ pname ]; +var uvalue = new WEBGL_TYPE[ ptype ](); +var usemantic = shaderParam.semantic; +var unode = shaderParam.node; +switch ( ptype ) { +case WEBGL_CONSTANTS.FLOAT: +uvalue = shaderParam.value; +if ( pname == "transparency" ) { +materialParams.transparent = true; +} +if ( value !== undefined ) { +uvalue = value; +} +break; +case WEBGL_CONSTANTS.FLOAT_VEC2: +case WEBGL_CONSTANTS.FLOAT_VEC3: +case WEBGL_CONSTANTS.FLOAT_VEC4: +case WEBGL_CONSTANTS.FLOAT_MAT3: +if ( shaderParam && shaderParam.value ) { +uvalue.fromArray( shaderParam.value ); +} +if ( value ) { +uvalue.fromArray( value ); +} +break; +case WEBGL_CONSTANTS.FLOAT_MAT2: +console.warn( "FLOAT_MAT2 is not a supported uniform type" ); +break; +case WEBGL_CONSTANTS.FLOAT_MAT4: +if ( pcount ) { +uvalue = new Array( pcount ); +for ( var mi = 0; mi < pcount; mi ++ ) { +uvalue[ mi ] = new WEBGL_TYPE[ ptype ](); +} +if ( shaderParam && shaderParam.value ) { +var m4v = shaderParam.value; +uvalue.fromArray( m4v ); +} +if ( value ) { +uvalue.fromArray( value ); +} +} else { +if ( shaderParam && shaderParam.value ) { +var m4 = shaderParam.value; +uvalue.fromArray( m4 ); +} +if ( value ) { +uvalue.fromArray( value ); +} +} +break; +case WEBGL_CONSTANTS.SAMPLER_2D: +if ( value !== undefined ) { +uvalue = dependencies.textures[ value ]; +} else if ( shaderParam.value !== undefined ) { +uvalue = dependencies.textures[ shaderParam.value ]; +} else { +uvalue = null; +} +break; +} +materialParams.uniforms[ uniformId ] = { +value: uvalue, +semantic: usemantic, +node: unode +}; +} else { +throw new Error( "Unknown shader uniform param type: " + ptype ); +} +} +var states = technique.states || {}; +var enables = states.enable || []; +var functions = states.functions || {}; +var enableCullFace = false; +var enableDepthTest = false; +var enableBlend = false; +for ( var i = 0, il = enables.length; i < il; i ++ ) { +var enable = enables[ i ]; +switch ( STATES_ENABLES[ enable ] ) { +case 'CULL_FACE': +enableCullFace = true; +break; +case 'DEPTH_TEST': +enableDepthTest = true; +break; +case 'BLEND': +enableBlend = true; +break; +case 'SCISSOR_TEST': +case 'POLYGON_OFFSET_FILL': +case 'SAMPLE_ALPHA_TO_COVERAGE': +break; +default: +throw new Error( "Unknown technique.states.enable: " + enable ); +} +} +if ( enableCullFace ) { +materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide; +} else { +materialParams.side = THREE.DoubleSide; +} +materialParams.depthTest = enableDepthTest; +materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth; +materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true; +materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending; +materialParams.transparent = enableBlend; +var blendEquationSeparate = functions.blendEquationSeparate; +if ( blendEquationSeparate !== undefined ) { +materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ]; +materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ]; +} else { +materialParams.blendEquation = THREE.AddEquation; +materialParams.blendEquationAlpha = THREE.AddEquation; +} +var blendFuncSeparate = functions.blendFuncSeparate; +if ( blendFuncSeparate !== undefined ) { +materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ]; +materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ]; +materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ]; +materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ]; +} else { +materialParams.blendSrc = THREE.OneFactor; +materialParams.blendDst = THREE.ZeroFactor; +materialParams.blendSrcAlpha = THREE.OneFactor; +materialParams.blendDstAlpha = THREE.ZeroFactor; +} +} +} +if ( Array.isArray( materialValues.diffuse ) ) { +materialParams.color = new THREE.Color().fromArray( materialValues.diffuse ); +} else if ( typeof( materialValues.diffuse ) === 'string' ) { +materialParams.map = dependencies.textures[ materialValues.diffuse ]; +} +delete materialParams.diffuse; +if ( typeof( materialValues.reflective ) === 'string' ) { +materialParams.envMap = dependencies.textures[ materialValues.reflective ]; +} +if ( typeof( materialValues.bump ) === 'string' ) { +materialParams.bumpMap = dependencies.textures[ materialValues.bump ]; +} +if ( Array.isArray( materialValues.emission ) ) { +if ( materialType === THREE.MeshBasicMaterial ) { +materialParams.color = new THREE.Color().fromArray( materialValues.emission ); +} else { +materialParams.emissive = new THREE.Color().fromArray( materialValues.emission ); +} +} else if ( typeof( materialValues.emission ) === 'string' ) { +if ( materialType === THREE.MeshBasicMaterial ) { +materialParams.map = dependencies.textures[ materialValues.emission ]; +} else { +materialParams.emissiveMap = dependencies.textures[ materialValues.emission ]; +} +} +if ( Array.isArray( materialValues.specular ) ) { +materialParams.specular = new THREE.Color().fromArray( materialValues.specular ); +} else if ( typeof( materialValues.specular ) === 'string' ) { +materialParams.specularMap = dependencies.textures[ materialValues.specular ]; +} +if ( materialValues.shininess !== undefined ) { +materialParams.shininess = materialValues.shininess; +} +var _material = new materialType( materialParams ); +if ( material.name !== undefined ) _material.name = material.name; +return _material; +} ); +} ); +}; +GLTFParser.prototype.loadMeshes = function () { +var json = this.json; +return this._withDependencies( [ +"accessors", +"materials" +] ).then( function ( dependencies ) { +return _each( json.meshes, function ( mesh ) { +var group = new THREE.Group(); +if ( mesh.name !== undefined ) group.name = mesh.name; +if ( mesh.extras ) group.userData = mesh.extras; +var primitives = mesh.primitives || []; +for ( var name in primitives ) { +var primitive = primitives[ name ]; +if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) { +var geometry = new THREE.BufferGeometry(); +var attributes = primitive.attributes; +for ( var attributeId in attributes ) { +var attributeEntry = attributes[ attributeId ]; +if ( ! attributeEntry ) return; +var bufferAttribute = dependencies.accessors[ attributeEntry ]; +switch ( attributeId ) { +case 'POSITION': +geometry.addAttribute( 'position', bufferAttribute ); +break; +case 'NORMAL': +geometry.addAttribute( 'normal', bufferAttribute ); +break; +case 'TEXCOORD_0': +case 'TEXCOORD0': +case 'TEXCOORD': +geometry.addAttribute( 'uv', bufferAttribute ); +break; +case 'TEXCOORD_1': +geometry.addAttribute( 'uv2', bufferAttribute ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +geometry.addAttribute( 'color', bufferAttribute ); +break; +case 'WEIGHT': +geometry.addAttribute( 'skinWeight', bufferAttribute ); +break; +case 'JOINT': +geometry.addAttribute( 'skinIndex', bufferAttribute ); +break; +} +} +if ( primitive.indices ) { +geometry.setIndex( dependencies.accessors[ primitive.indices ] ); +} +var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial(); +var meshNode = new THREE.Mesh( geometry, material ); +meshNode.castShadow = true; +meshNode.name = ( name === "0" ? group.name : group.name + name ); +if ( primitive.extras ) meshNode.userData = primitive.extras; +group.add( meshNode ); +} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) { +var geometry = new THREE.BufferGeometry(); +var attributes = primitive.attributes; +for ( var attributeId in attributes ) { +var attributeEntry = attributes[ attributeId ]; +if ( ! attributeEntry ) return; +var bufferAttribute = dependencies.accessors[ attributeEntry ]; +switch ( attributeId ) { +case 'POSITION': +geometry.addAttribute( 'position', bufferAttribute ); +break; +case 'COLOR_0': +case 'COLOR0': +case 'COLOR': +geometry.addAttribute( 'color', bufferAttribute ); +break; +} +} +var material = dependencies.materials[ primitive.material ]; +var meshNode; +if ( primitive.indices ) { +geometry.setIndex( dependencies.accessors[ primitive.indices ] ); +meshNode = new THREE.LineSegments( geometry, material ); +} else { +meshNode = new THREE.Line( geometry, material ); +} +meshNode.name = ( name === "0" ? group.name : group.name + name ); +if ( primitive.extras ) meshNode.userData = primitive.extras; +group.add( meshNode ); +} else { +console.warn( "Only triangular and line primitives are supported" ); +} +} +return group; +} ); +} ); +}; +GLTFParser.prototype.loadCameras = function () { +var json = this.json; +return _each( json.cameras, function ( camera ) { +if ( camera.type == "perspective" && camera.perspective ) { +var yfov = camera.perspective.yfov; +var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1; +var xfov = yfov * aspectRatio; +var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 ); +if ( camera.name !== undefined ) _camera.name = camera.name; +if ( camera.extras ) _camera.userData = camera.extras; +return _camera; +} else if ( camera.type == "orthographic" && camera.orthographic ) { +var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar ); +if ( camera.name !== undefined ) _camera.name = camera.name; +if ( camera.extras ) _camera.userData = camera.extras; +return _camera; +} +} ); +}; +GLTFParser.prototype.loadSkins = function () { +var json = this.json; +return this._withDependencies( [ +"accessors" +] ).then( function ( dependencies ) { +return _each( json.skins, function ( skin ) { +var bindShapeMatrix = new THREE.Matrix4(); +if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix ); +var _skin = { +bindShapeMatrix: bindShapeMatrix, +jointNames: skin.jointNames, +inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ] +}; +return _skin; +} ); +} ); +}; +GLTFParser.prototype.loadAnimations = function () { +var json = this.json; +return this._withDependencies( [ +"accessors", +"nodes" +] ).then( function ( dependencies ) { +return _each( json.animations, function ( animation, animationId ) { +var tracks = []; +for ( var channelId in animation.channels ) { +var channel = animation.channels[ channelId ]; +var sampler = animation.samplers[ channel.sampler ]; +if ( sampler ) { +var target = channel.target; +var name = target.id; +var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input; +var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output; +var inputAccessor = dependencies.accessors[ input ]; +var outputAccessor = dependencies.accessors[ output ]; +var node = dependencies.nodes[ name ]; +if ( node ) { +node.updateMatrix(); +node.matrixAutoUpdate = true; +var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation +? THREE.QuaternionKeyframeTrack +: THREE.VectorKeyframeTrack; +var targetName = node.name ? node.name : node.uuid; +var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear; +tracks.push( new TypedKeyframeTrack( +targetName + '.' + PATH_PROPERTIES[ target.path ], +THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ), +THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ), +interpolation +) ); +} +} +} +var name = animation.name !== undefined ? animation.name : "animation_" + animationId; +return new THREE.AnimationClip( name, undefined, tracks ); +} ); +} ); +}; +GLTFParser.prototype.loadNodes = function () { +var json = this.json; +var extensions = this.extensions; +var scope = this; +return _each( json.nodes, function ( node ) { +var matrix = new THREE.Matrix4(); +var _node; +if ( node.jointName ) { +_node = new THREE.Bone(); +_node.name = node.name !== undefined ? node.name : node.jointName; +_node.jointName = node.jointName; +} else { +_node = new THREE.Object3D(); +if ( node.name !== undefined ) _node.name = node.name; +} +if ( node.extras ) _node.userData = node.extras; +if ( node.matrix !== undefined ) { +matrix.fromArray( node.matrix ); +_node.applyMatrix( matrix ); +} else { +if ( node.translation !== undefined ) { +_node.position.fromArray( node.translation ); +} +if ( node.rotation !== undefined ) { +_node.quaternion.fromArray( node.rotation ); +} +if ( node.scale !== undefined ) { +_node.scale.fromArray( node.scale ); +} +} +return _node; +} ).then( function ( __nodes ) { +return scope._withDependencies( [ +"meshes", +"skins", +"cameras" +] ).then( function ( dependencies ) { +return _each( __nodes, function ( _node, nodeId ) { +var node = json.nodes[ nodeId ]; +if ( node.meshes !== undefined ) { +for ( var meshId in node.meshes ) { +var mesh = node.meshes[ meshId ]; +var group = dependencies.meshes[ mesh ]; +if ( group === undefined ) { +console.warn( 'GLTFLoader: Couldn\'t find node "' + mesh + '".' ); +continue; +} +for ( var childrenId in group.children ) { +var child = group.children[ childrenId ]; +var originalMaterial = child.material; +var originalGeometry = child.geometry; +var originalUserData = child.userData; +var originalName = child.name; +var material; +if ( originalMaterial.isDeferredShaderMaterial ) { +originalMaterial = material = originalMaterial.create(); +} else { +material = originalMaterial; +} +switch ( child.type ) { +case 'LineSegments': +child = new THREE.LineSegments( originalGeometry, material ); +break; +case 'LineLoop': +child = new THREE.LineLoop( originalGeometry, material ); +break; +case 'Line': +child = new THREE.Line( originalGeometry, material ); +break; +default: +child = new THREE.Mesh( originalGeometry, material ); +} +child.castShadow = true; +child.userData = originalUserData; +child.name = originalName; +var skinEntry; +if ( node.skin ) { +skinEntry = dependencies.skins[ node.skin ]; +} +if ( skinEntry ) { +var getJointNode = function ( jointId ) { +var keys = Object.keys( __nodes ); +for ( var i = 0, il = keys.length; i < il; i ++ ) { +var n = __nodes[ keys[ i ] ]; +if ( n.jointName === jointId ) return n; +} +return null; +}; +var geometry = originalGeometry; +var material = originalMaterial; +material.skinning = true; +child = new THREE.SkinnedMesh( geometry, material, false ); +child.castShadow = true; +child.userData = originalUserData; +child.name = originalName; +var bones = []; +var boneInverses = []; +for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) { +var jointId = skinEntry.jointNames[ i ]; +var jointNode = getJointNode( jointId ); +if ( jointNode ) { +bones.push( jointNode ); +var m = skinEntry.inverseBindMatrices.array; +var mat = new THREE.Matrix4().fromArray( m, i * 16 ); +boneInverses.push( mat ); +} else { +console.warn( "WARNING: joint: '" + jointId + "' could not be found" ); +} +} +child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix ); +var buildBoneGraph = function ( parentJson, parentObject, property ) { +var children = parentJson[ property ]; +if ( children === undefined ) return; +for ( var i = 0, il = children.length; i < il; i ++ ) { +var nodeId = children[ i ]; +var bone = __nodes[ nodeId ]; +var boneJson = json.nodes[ nodeId ]; +if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) { +parentObject.add( bone ); +buildBoneGraph( boneJson, bone, 'children' ); +} +} +}; +buildBoneGraph( node, child, 'skeletons' ); +} +_node.add( child ); +} +} +} +if ( node.camera !== undefined ) { +var camera = dependencies.cameras[ node.camera ]; +_node.add( camera ); +} +if ( node.extensions +&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] +&& node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) { +var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights; +var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ]; +_node.add( light ); +} +return _node; +} ); +} ); +} ); +}; +GLTFParser.prototype.loadScenes = function () { +var json = this.json; +function buildNodeHierachy( nodeId, parentObject, allNodes ) { +var _node = allNodes[ nodeId ]; +parentObject.add( _node ); +var node = json.nodes[ nodeId ]; +if ( node.children ) { +var children = node.children; +for ( var i = 0, l = children.length; i < l; i ++ ) { +var child = children[ i ]; +buildNodeHierachy( child, _node, allNodes ); +} +} +} +return this._withDependencies( [ +"nodes" +] ).then( function ( dependencies ) { +return _each( json.scenes, function ( scene ) { +var _scene = new THREE.Scene(); +if ( scene.name !== undefined ) _scene.name = scene.name; +if ( scene.extras ) _scene.userData = scene.extras; +var nodes = scene.nodes || []; +for ( var i = 0, l = nodes.length; i < l; i ++ ) { +var nodeId = nodes[ i ]; +buildNodeHierachy( nodeId, _scene, dependencies.nodes ); +} +_scene.traverse( function ( child ) { +if ( child.material && child.material.isRawShaderMaterial ) { +child.gltfShader = new GLTFShader( child, dependencies.nodes ); +child.onBeforeRender = function(renderer, scene, camera){ +this.gltfShader.update(scene, camera); +}; +} +} ); +return _scene; +} ); +} ); +}; +return GLTFLoader; +} )(); +"use strict"; +var JSONParser = function() +{ +} +JSONParser.prototype.constructor = JSONParser; +/** +* Load X3D JSON into an element. +* jsobj - the JavaScript object to convert to DOM. +*/ +JSONParser.prototype.parseJavaScript = function(jsobj) { +var child = this.CreateElement('scene'); +this.ConvertToX3DOM(jsobj, "", child); +console.log(jsobj, child); +return child; +}; +/** +* Yet another way to set an attribute on an element. does not allow you to +* set JSON schema or encoding. +*/ +JSONParser.prototype.elementSetAttribute = function(element, key, value) { +if (key === 'SON schema') { +} else if (key === 'ncoding') { +} else { +if (typeof element.setAttribute === 'function') { +element.setAttribute(key, value); +} +} +}; +/** +* converts children of object to DOM. +*/ +JSONParser.prototype.ConvertChildren = function(parentkey, object, element) { +var key; +for (key in object) { +if (typeof object[key] === 'object') { +if (isNaN(parseInt(key))) { +this.ConvertObject(key, object, element, parentkey.substr(1)); +} else { +this.ConvertToX3DOM(object[key], key, element, parentkey.substr(1)); +} +} +} +}; +/** +* a method to create and element with tagnam key to DOM in a namespace. If +* containerField is set, then the containerField is set in the elemetn. +*/ +JSONParser.prototype.CreateElement = function(key, containerField) { +var child = document.createElement(key); +if (typeof containerField !== 'undefined') { +this.elementSetAttribute(child, 'containerField', containerField); +} +return child; +}; +/** +* a way to create a CDATA function or script in HTML, by using a DOM parser. +*/ +JSONParser.prototype.CDATACreateFunction = function(document, element, str) { +var y = str.replace(/\\"/g, "\\\"") +.replace(/</g, "<") +.replace(/>/g, ">") +.replace(/&/g, "&"); +do { +str = y; +y = str.replace(/'([^'\r\n]*)\n([^']*)'/g, "'$1\\n$2'"); +if (str !== y) { +console.log("CDATA Replacing",str,"with",y); +} +} while (y != str); +var domParser = new DOMParser(); +var cdataStr = ''; // has to be wrapped into an element +var scriptDoc = domParser .parseFromString (cdataStr, 'application/xml'); +var cdata = scriptDoc .children[0] .childNodes[1]; // space after script is childNode[0] +element .appendChild(cdata); +}; +/** +* convert the object at object[key] to DOM. +*/ +JSONParser.prototype.ConvertObject = function(key, object, element, containerField) { +var child; +if (object !== null && typeof object[key] === 'object') { +if (key.substr(0,1) === '@') { +this.ConvertToX3DOM(object[key], key, element); +} else if (key.substr(0,1) === '-') { +this.ConvertChildren(key, object[key], element); +} else if (key === '#comment') { +for (var c in object[key]) { +child = document.createComment(this.CommentStringToXML(object[key][c])); +element.appendChild(child); +} +} else if (key === '#text') { +child = document.createTextNode(object[key].join("")); +element.appendChild(child); +} else if (key === '#sourceText') { +this.CDATACreateFunction(document, element, object[key].join("\r\n")+"\r\n"); +} else { +if (key === 'connect' || key === 'fieldValue' || key === 'field' || key === 'meta' || key === 'component') { +for (var childkey in object[key]) { // for each field +if (typeof object[key][childkey] === 'object') { +child = this.CreateElement(key, containerField); +this.ConvertToX3DOM(object[key][childkey], childkey, child); +element.appendChild(child); +element.appendChild(document.createTextNode("\n")); +} +} +} else { +child = this.CreateElement(key, containerField); +this.ConvertToX3DOM(object[key], key, child); +element.appendChild(child); +element.appendChild(document.createTextNode("\n")); +} +} +} +}; +/** +* convert a comment string in JavaScript to XML. Pass the string +*/ +JSONParser.prototype.CommentStringToXML = function(str) { +var y = str; +str = str.replace(/\\\\/g, '\\'); +if (y !== str) { +console.log("X3DJSONLD replacing", y, "with", str); +} +return str; +}; +/** +* convert an SFString to XML. +*/ +JSONParser.prototype.SFStringToXML = function(str) { +var y = str; +/* +str = (""+str).replace(/\\\\/g, '\\\\'); +str = str.replace(/\\\\\\\\/g, '\\\\'); +str = str.replace(/(\\+)"/g, '\\"'); +*/ +str = str.replace(/\\/g, '\\\\'); +str = str.replace(/"/g, '\\\"'); +if (y !== str) { +console.log("X3DJSONLD [] replacing", y, "with", str); +} +return str; +}; +/** +* convert a JSON String to XML. +*/ +JSONParser.prototype.JSONStringToXML = function(str) { +var y = str; +str = str.replace(/\\/g, '\\\\'); +str = str.replace(/\n/g, '\\n'); +if (y !== str) { +console.log("X3DJSONLD replacing", y, "with", str); +} +return str; +}; +/** +* main routine for converting a JavaScript object to DOM. +* object is the object to convert. +* parentkey is the key of the object in the parent. +* element is the parent element. +* containerField is a possible containerField. +*/ +JSONParser.prototype.ConvertToX3DOM = function(object, parentkey, element, containerField) { +var key; +var localArray = []; +var isArray = false; +var arrayOfStrings = false; +for (key in object) { +if (isNaN(parseInt(key))) { +isArray = false; +} else { +isArray = true; +} +if (isArray) { +if (typeof object[key] === 'number') { +localArray.push(object[key]); +} else if (typeof object[key] === 'string') { +localArray.push(object[key]); +arrayOfStrings = true; +} else if (typeof object[key] === 'boolean') { +localArray.push(object[key]); +} else if (typeof object[key] === 'object') { +/* +if (object[key] != null && typeof object[key].join === 'function') { +localArray.push(object[key].join(" ")); +} +*/ +this.ConvertToX3DOM(object[key], key, element); +} else if (typeof object[key] === 'undefined') { +} else { +console.error("Unknown type found in array "+typeof object[key]); +} +} else if (typeof object[key] === 'object') { +if (key === 'scene') { +this.ConvertToX3DOM(object[key], key, element); +} else { +this.ConvertObject(key, object, element); +} +} else if (typeof object[key] === 'number') { +this.elementSetAttribute(element, key.substr(1),object[key]); +} else if (typeof object[key] === 'string') { +if (key === '#comment') { +var child = document.createComment(this.CommentStringToXML(object[key])); +element.appendChild(child); +} else if (key === '#text') { +var child = document.createTextNode(object[key]); +element.appendChild(child); +} else { +this.elementSetAttribute(element, key.substr(1), this.JSONStringToXML(object[key])); +} +} else if (typeof object[key] === 'boolean') { +this.elementSetAttribute(element, key.substr(1),object[key]); +} else if (typeof object[key] === 'undefined') { +} else { +console.error("Unknown type found in object "+typeof object[key]); +console.error(object); +} +} +if (isArray) { +if (parentkey.substr(0,1) === '@') { +if (arrayOfStrings) { +arrayOfStrings = false; +for (var str in localArray) { +localArray[str] = this.SFStringToXML(localArray[str]); +} +this.elementSetAttribute(element, parentkey.substr(1),'"'+localArray.join('" "')+'"'); +} else { +this.elementSetAttribute(element, parentkey.substr(1),localArray.join(" ")); +} +} +isArray = false; +} +return element; +}; +/* +* For use with XSeen JavaScript Library +* http://tools.realism.com/... +* +* Licensed under MIT or GNU in the same manner as XSeen +* +* (C)2017 Daly Realiusm, Los Angeles +* +*/ +/* +* Manages all download requests. +* Requests are queued up and processed to the maximum limit (.MaxRequests) +* Use this for processing text (X3D, XML, JSON, HTML) files. +* Not really setup for binary files (.jpg, png, etc.) +* +* Requires jQuery -- should work on removing that... +* +*/ +function LoadManager () { +this.urlQueue = []; +this.urlNext = -1; +this.MaxRequests = 3; +this.totalRequests = 0; +this.totalResponses = 0; +this.requestCount = 0; +var lmThat = this; +this.load = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.loadText = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'text', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.loadHtml = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'html', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.loadXml = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'xml', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.loadJson = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'json', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.loadImage = function (url, success, progress, failed, userdata) { +this.urlQueue.push( {'url':url, 'type':'image', 'userdata':userdata, 'success':success, 'failure':failed, 'progress':progress} ); +this.loadNextUrl(); +} +this.success = function (response, string, xhr) { +if (typeof(xhr._loadManager.success) !== undefined) { +xhr._loadManager.success (response, xhr._loadManager.userdata, xhr); +} +} +this.failure = function (xhr, errorCode, errorText) { +if (typeof(xhr._loadManager.failure) !== undefined) { +xhr._loadManager.failure (xhr, xhr._loadManager.userdata, errorCode, errorText); +} +} +this.requestComplete = function (event, xhr, settings) { +lmThat.requestCount --; +lmThat.totalResponses++; +lmThat.loadNextUrl(); +} +this.loadNextUrl = function () { +if (this.requestCount >= this.MaxRequests) {return; } +if (this.urlNext >= this.urlQueue.length || this.urlNext < 0) { +this.urlNext = -1; +for (var i=0; i 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +break; +case Consts.CODE_SLASH: +slashes[ slashesPointer++ ] = i; +if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +break; +case Consts.CODE_LF: +if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ); +slashesPointer = 0; +bufferPointer = 0; +break; +case Consts.CODE_CR: +break; +default: +word += String.fromCharCode( code ); +break; +} +} +}; +/** +* Parse the provided text +* @memberOf Parser +* +* @param {string} text OBJ data as string +*/ +Parser.prototype.parseText = function ( text ) { +var length = text.length; +var buffer = new Array( 32 ); +var bufferPointer = 0; +var slashes = new Array( 32 ); +var slashesPointer = 0; +var reachedFaces = false; +var char; +var word = ''; +for ( var i = 0; i < length; i++ ) { +char = text[ i ]; +switch ( char ) { +case Consts.STRING_SPACE: +if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +break; +case Consts.STRING_SLASH: +slashes[ slashesPointer++ ] = i; +if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +break; +case Consts.STRING_LF: +if ( word.length > 0 ) buffer[ bufferPointer++ ] = word; +word = ''; +reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ); +slashesPointer = 0; +bufferPointer = 0; +break; +case Consts.STRING_CR: +break; +default: +word += char; +} +} +}; +Parser.prototype.processLine = function ( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ) { +if ( bufferPointer < 1 ) return reachedFaces; +var bufferLength = bufferPointer - 1; +switch ( buffer[ 0 ] ) { +case Consts.LINE_V: +if ( reachedFaces ) { +this.processCompletedObject( null, this.rawObject.groupName ); +reachedFaces = false; +} +this.rawObject.pushVertex( buffer ); +break; +case Consts.LINE_VT: +this.rawObject.pushUv( buffer ); +break; +case Consts.LINE_VN: +this.rawObject.pushNormal( buffer ); +break; +case Consts.LINE_F: +reachedFaces = true; +/* +* 0: "f vertex/uv/normal ..." +* 1: "f vertex/uv ..." +* 2: "f vertex//normal ..." +* 3: "f vertex ..." +*/ +var haveQuad = bufferLength % 4 === 0; +if ( slashesPointer > 1 && ( slashes[ 1 ] - slashes[ 0 ] ) === 1 ) { +if ( haveQuad ) { +this.rawObject.buildQuadVVn( buffer ); +} else { +this.rawObject.buildFaceVVn( buffer ); +} +} else if ( bufferLength === slashesPointer * 2 ) { +if ( haveQuad ) { +this.rawObject.buildQuadVVt( buffer ); +} else { +this.rawObject.buildFaceVVt( buffer ); +} +} else if ( bufferLength * 2 === slashesPointer * 3 ) { +if ( haveQuad ) { +this.rawObject.buildQuadVVtVn( buffer ); +} else { +this.rawObject.buildFaceVVtVn( buffer ); +} +} else { +if ( haveQuad ) { +this.rawObject.buildQuadV( buffer ); +} else { +this.rawObject.buildFaceV( buffer ); +} +} +break; +case Consts.LINE_L: +if ( bufferLength === slashesPointer * 2 ) { +this.rawObject.buildLineVvt( buffer ); +} else { +this.rawObject.buildLineV( buffer ); +} +break; +case Consts.LINE_S: +this.rawObject.pushSmoothingGroup( buffer[ 1 ] ); +break; +case Consts.LINE_G: +this.processCompletedGroup( buffer[ 1 ] ); +break; +case Consts.LINE_O: +if ( this.rawObject.vertices.length > 0 ) { +this.processCompletedObject( buffer[ 1 ], null ); +reachedFaces = false; +} else { +this.rawObject.pushObject( buffer[ 1 ] ); +} +break; +case Consts.LINE_MTLLIB: +this.rawObject.pushMtllib( buffer[ 1 ] ); +break; +case Consts.LINE_USEMTL: +this.rawObject.pushUsemtl( buffer[ 1 ] ); +break; +default: +break; +} +return reachedFaces; +}; +Parser.prototype.processCompletedObject = function ( objectName, groupName ) { +this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); +this.inputObjectCount++; +this.rawObject = this.rawObject.newInstanceFromObject( objectName, groupName ); +}; +Parser.prototype.processCompletedGroup = function ( groupName ) { +var notEmpty = this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); +if ( notEmpty ) { +this.inputObjectCount ++; +this.rawObject = this.rawObject.newInstanceFromGroup( groupName ); +} else { +this.rawObject.pushGroup( groupName ); +} +}; +Parser.prototype.finalize = function () { +this.rawObject.finalize( this.meshCreator, this.inputObjectCount, this.debug ); +this.inputObjectCount++; +}; +return Parser; +})(); +/** +* {@link RawObject} is only used by {@link Parser}. +* The user of OBJLoader2 does not need to care about this class. +* It is defined publicly for inclusion in web worker based OBJ loader ({@link THREE.OBJLoader2.WWOBJLoader2}) +*/ +var RawObject = (function () { +function RawObject( objectName, groupName, mtllibName ) { +this.globalVertexOffset = 1; +this.globalUvOffset = 1; +this.globalNormalOffset = 1; +this.vertices = []; +this.normals = []; +this.uvs = []; +this.mtllibName = Validator.verifyInput( mtllibName, 'none' ); +this.objectName = Validator.verifyInput( objectName, 'none' ); +this.groupName = Validator.verifyInput( groupName, 'none' ); +this.activeMtlName = 'none'; +this.activeSmoothingGroup = 1; +this.mtlCount = 0; +this.smoothingGroupCount = 0; +this.rawObjectDescriptions = []; +var index = this.buildIndex( this.activeMtlName, this.activeSmoothingGroup ); +this.rawObjectDescriptionInUse = new RawObjectDescription( this.objectName, this.groupName, this.activeMtlName, this.activeSmoothingGroup ); +this.rawObjectDescriptions[ index ] = this.rawObjectDescriptionInUse; +} +RawObject.prototype.buildIndex = function ( materialName, smoothingGroup) { +return materialName + '|' + smoothingGroup; +}; +RawObject.prototype.newInstanceFromObject = function ( objectName, groupName ) { +var newRawObject = new RawObject( objectName, groupName, this.mtllibName ); +newRawObject.globalVertexOffset = this.globalVertexOffset + this.vertices.length / 3; +newRawObject.globalUvOffset = this.globalUvOffset + this.uvs.length / 2; +newRawObject.globalNormalOffset = this.globalNormalOffset + this.normals.length / 3; +return newRawObject; +}; +RawObject.prototype.newInstanceFromGroup = function ( groupName ) { +var newRawObject = new RawObject( this.objectName, groupName, this.mtllibName ); +newRawObject.vertices = this.vertices; +newRawObject.uvs = this.uvs; +newRawObject.normals = this.normals; +newRawObject.globalVertexOffset = this.globalVertexOffset; +newRawObject.globalUvOffset = this.globalUvOffset; +newRawObject.globalNormalOffset = this.globalNormalOffset; +return newRawObject; +}; +RawObject.prototype.pushVertex = function ( buffer ) { +this.vertices.push( parseFloat( buffer[ 1 ] ) ); +this.vertices.push( parseFloat( buffer[ 2 ] ) ); +this.vertices.push( parseFloat( buffer[ 3 ] ) ); +}; +RawObject.prototype.pushUv = function ( buffer ) { +this.uvs.push( parseFloat( buffer[ 1 ] ) ); +this.uvs.push( parseFloat( buffer[ 2 ] ) ); +}; +RawObject.prototype.pushNormal = function ( buffer ) { +this.normals.push( parseFloat( buffer[ 1 ] ) ); +this.normals.push( parseFloat( buffer[ 2 ] ) ); +this.normals.push( parseFloat( buffer[ 3 ] ) ); +}; +RawObject.prototype.pushObject = function ( objectName ) { +this.objectName = objectName; +}; +RawObject.prototype.pushMtllib = function ( mtllibName ) { +this.mtllibName = mtllibName; +}; +RawObject.prototype.pushGroup = function ( groupName ) { +this.groupName = groupName; +this.verifyIndex(); +}; +RawObject.prototype.pushUsemtl = function ( mtlName ) { +if ( this.activeMtlName === mtlName || ! Validator.isValid( mtlName ) ) return; +this.activeMtlName = mtlName; +this.mtlCount++; +this.verifyIndex(); +}; +RawObject.prototype.pushSmoothingGroup = function ( activeSmoothingGroup ) { +var normalized = activeSmoothingGroup === 'off' ? 0 : activeSmoothingGroup; +if ( this.activeSmoothingGroup === normalized ) return; +this.activeSmoothingGroup = normalized; +this.smoothingGroupCount++; +this.verifyIndex(); +}; +RawObject.prototype.verifyIndex = function () { +var index = this.buildIndex( this.activeMtlName, ( this.activeSmoothingGroup === 0 ) ? 0 : 1 ); +this.rawObjectDescriptionInUse = this.rawObjectDescriptions[ index ]; +if ( ! Validator.isValid( this.rawObjectDescriptionInUse ) ) { +this.rawObjectDescriptionInUse = new RawObjectDescription( this.objectName, this.groupName, this.activeMtlName, this.activeSmoothingGroup ); +this.rawObjectDescriptions[ index ] = this.rawObjectDescriptionInUse; +} +}; +RawObject.prototype.buildQuadVVtVn = function ( indexArray ) { +for ( var i = 0; i < 6; i ++ ) { +this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_3[ i ] ] ); +this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_3[ i ] + 1 ] ); +this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_3[ i ] + 2 ] ); +} +}; +RawObject.prototype.buildQuadVVt = function ( indexArray ) { +for ( var i = 0; i < 6; i ++ ) { +this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] ); +this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] ); +} +}; +RawObject.prototype.buildQuadVVn = function ( indexArray ) { +for ( var i = 0; i < 6; i ++ ) { +this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] ); +this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] ); +} +}; +RawObject.prototype.buildQuadV = function ( indexArray ) { +for ( var i = 0; i < 6; i ++ ) { +this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_1[ i ] ] ); +} +}; +RawObject.prototype.buildFaceVVtVn = function ( indexArray ) { +for ( var i = 1; i < 10; i += 3 ) { +this.attachFaceV_( indexArray[ i ] ); +this.attachFaceVt( indexArray[ i + 1 ] ); +this.attachFaceVn( indexArray[ i + 2 ] ); +} +}; +RawObject.prototype.buildFaceVVt = function ( indexArray ) { +for ( var i = 1; i < 7; i += 2 ) { +this.attachFaceV_( indexArray[ i ] ); +this.attachFaceVt( indexArray[ i + 1 ] ); +} +}; +RawObject.prototype.buildFaceVVn = function ( indexArray ) { +for ( var i = 1; i < 7; i += 2 ) { +this.attachFaceV_( indexArray[ i ] ); +this.attachFaceVn( indexArray[ i + 1 ] ); +} +}; +RawObject.prototype.buildFaceV = function ( indexArray ) { +for ( var i = 1; i < 4; i ++ ) { +this.attachFaceV_( indexArray[ i ] ); +} +}; +RawObject.prototype.attachFaceV_ = function ( faceIndex ) { +var faceIndexInt = parseInt( faceIndex ); +var index = ( faceIndexInt - this.globalVertexOffset ) * 3; +var rodiu = this.rawObjectDescriptionInUse; +rodiu.vertices.push( this.vertices[ index++ ] ); +rodiu.vertices.push( this.vertices[ index++ ] ); +rodiu.vertices.push( this.vertices[ index ] ); +}; +RawObject.prototype.attachFaceVt = function ( faceIndex ) { +var faceIndexInt = parseInt( faceIndex ); +var index = ( faceIndexInt - this.globalUvOffset ) * 2; +var rodiu = this.rawObjectDescriptionInUse; +rodiu.uvs.push( this.uvs[ index++ ] ); +rodiu.uvs.push( this.uvs[ index ] ); +}; +RawObject.prototype.attachFaceVn = function ( faceIndex ) { +var faceIndexInt = parseInt( faceIndex ); +var index = ( faceIndexInt - this.globalNormalOffset ) * 3; +var rodiu = this.rawObjectDescriptionInUse; +rodiu.normals.push( this.normals[ index++ ] ); +rodiu.normals.push( this.normals[ index++ ] ); +rodiu.normals.push( this.normals[ index ] ); +}; +/* +* Support for lines with or without texture. irst element in indexArray is the line identification +* 0: "f vertex/uv vertex/uv ..." +* 1: "f vertex vertex ..." +*/ +RawObject.prototype.buildLineVvt = function ( lineArray ) { +var length = lineArray.length; +for ( var i = 1; i < length; i ++ ) { +this.vertices.push( parseInt( lineArray[ i ] ) ); +this.uvs.push( parseInt( lineArray[ i ] ) ); +} +}; +RawObject.prototype.buildLineV = function ( lineArray ) { +var length = lineArray.length; +for ( var i = 1; i < length; i++ ) { +this.vertices.push( parseInt( lineArray[ i ] ) ); +} +}; +/** +* Clear any empty rawObjectDescription and calculate absolute vertex, normal and uv counts +*/ +RawObject.prototype.finalize = function ( meshCreator, inputObjectCount, debug ) { +var temp = this.rawObjectDescriptions; +this.rawObjectDescriptions = []; +var rawObjectDescription; +var index = 0; +var absoluteVertexCount = 0; +var absoluteNormalCount = 0; +var absoluteUvCount = 0; +for ( var name in temp ) { +rawObjectDescription = temp[ name ]; +if ( rawObjectDescription.vertices.length > 0 ) { +if ( rawObjectDescription.objectName === 'none' ) rawObjectDescription.objectName = rawObjectDescription.groupName; +this.rawObjectDescriptions[ index++ ] = rawObjectDescription; +absoluteVertexCount += rawObjectDescription.vertices.length; +absoluteUvCount += rawObjectDescription.uvs.length; +absoluteNormalCount += rawObjectDescription.normals.length; +} +} +var notEmpty = false; +if ( index > 0 ) { +if ( debug ) this.createReport( inputObjectCount, true ); +meshCreator.buildMesh( +this.rawObjectDescriptions, +inputObjectCount, +absoluteVertexCount, +absoluteNormalCount, +absoluteUvCount +); +notEmpty = true; +} +return notEmpty; +}; +RawObject.prototype.createReport = function ( inputObjectCount, printDirectly ) { +var report = { +name: this.objectName ? this.objectName : 'groups', +mtllibName: this.mtllibName, +vertexCount: this.vertices.length / 3, +normalCount: this.normals.length / 3, +uvCount: this.uvs.length / 2, +smoothingGroupCount: this.smoothingGroupCount, +mtlCount: this.mtlCount, +rawObjectDescriptions: this.rawObjectDescriptions.length +}; +if ( printDirectly ) { +console.log( 'Input Object number: ' + inputObjectCount + ' Object name: ' + report.name ); +console.log( 'Mtllib name: ' + report.mtllibName ); +console.log( 'Vertex count: ' + report.vertexCount ); +console.log( 'Normal count: ' + report.normalCount ); +console.log( 'UV count: ' + report.uvCount ); +console.log( 'SmoothingGroup count: ' + report.smoothingGroupCount ); +console.log( 'Material count: ' + report.mtlCount ); +console.log( 'Real RawObjectDescription count: ' + report.rawObjectDescriptions ); +console.log( '' ); +} +return report; +}; +return RawObject; +})(); +/** +* Descriptive information and data (vertices, normals, uvs) to passed on to mesh building function. +* @class +* +* @param {string} objectName Name of the mesh +* @param {string} groupName Name of the group +* @param {string} materialName Name of the material +* @param {number} smoothingGroup Normalized smoothingGroup (0: THREE.FlatShading, 1: THREE.SmoothShading) +*/ +var RawObjectDescription = (function () { +function RawObjectDescription( objectName, groupName, materialName, smoothingGroup ) { +this.objectName = objectName; +this.groupName = groupName; +this.materialName = materialName; +this.smoothingGroup = smoothingGroup; +this.vertices = []; +this.uvs = []; +this.normals = []; +} +return RawObjectDescription; +})(); +/** +* MeshCreator is used to transform RawObjectDescriptions to THREE.Mesh +* +* @class +*/ +var MeshCreator = (function () { +function MeshCreator() { +this.sceneGraphBaseNode = null; +this.materials = null; +this.debug = false; +this.globalObjectCount = 1; +this.validated = false; +} +MeshCreator.prototype.setSceneGraphBaseNode = function ( sceneGraphBaseNode ) { +this.sceneGraphBaseNode = Validator.verifyInput( sceneGraphBaseNode, this.sceneGraphBaseNode ); +this.sceneGraphBaseNode = Validator.verifyInput( this.sceneGraphBaseNode, new THREE.Group() ); +}; +MeshCreator.prototype.setMaterials = function ( materials ) { +this.materials = Validator.verifyInput( materials, this.materials ); +this.materials = Validator.verifyInput( this.materials, { materials: [] } ); +}; +MeshCreator.prototype.setDebug = function ( debug ) { +if ( debug === true || debug === false ) this.debug = debug; +}; +MeshCreator.prototype.validate = function () { +if ( this.validated ) return; +this.setSceneGraphBaseNode( null ); +this.setMaterials( null ); +this.setDebug( null ); +this.globalObjectCount = 1; +}; +MeshCreator.prototype.finalize = function () { +this.sceneGraphBaseNode = null; +this.materials = null; +this.validated = false; +}; +/** +* This is an internal function, but due to its importance to Parser it is documented. +* RawObjectDescriptions are transformed to THREE.Mesh. +* It is ensured that rawObjectDescriptions only contain objects with vertices (no need to check). +* This method shall be overridden by the web worker implementation +* +* @param {RawObjectDescription[]} rawObjectDescriptions Array of descriptive information and data (vertices, normals, uvs) about the parsed object(s) +* @param {number} inputObjectCount Number of objects already retrieved from OBJ +* @param {number} absoluteVertexCount Sum of all vertices of all rawObjectDescriptions +* @param {number} absoluteNormalCount Sum of all normals of all rawObjectDescriptions +* @param {number} absoluteUvCount Sum of all uvs of all rawObjectDescriptions +*/ +MeshCreator.prototype.buildMesh = function ( rawObjectDescriptions, inputObjectCount, absoluteVertexCount, absoluteNormalCount, absoluteUvCount ) { +if ( this.debug ) console.log( 'MeshCreator.buildRawMeshData:\nInput object no.: ' + inputObjectCount ); +var bufferGeometry = new THREE.BufferGeometry(); +var vertexBA = new THREE.BufferAttribute( new Float32Array( absoluteVertexCount ), 3 ); +bufferGeometry.addAttribute( 'position', vertexBA ); +var normalBA; +if ( absoluteNormalCount > 0 ) { +normalBA = new THREE.BufferAttribute( new Float32Array( absoluteNormalCount ), 3 ); +bufferGeometry.addAttribute( 'normal', normalBA ); +} +var uvBA; +if ( absoluteUvCount > 0 ) { +uvBA = new THREE.BufferAttribute( new Float32Array( absoluteUvCount ), 2 ); +bufferGeometry.addAttribute( 'uv', uvBA ); +} +if ( this.debug ) console.log( 'Creating Multi-Material for object no.: ' + this.globalObjectCount ); +var rawObjectDescription; +var material; +var materialName; +var createMultiMaterial = rawObjectDescriptions.length > 1; +var materials = []; +var materialIndex = 0; +var materialIndexMapping = []; +var selectedMaterialIndex; +var vertexBAOffset = 0; +var vertexGroupOffset = 0; +var vertexLength; +var normalOffset = 0; +var uvOffset = 0; +for ( var oodIndex in rawObjectDescriptions ) { +rawObjectDescription = rawObjectDescriptions[ oodIndex ]; +materialName = rawObjectDescription.materialName; +material = this.materials[ materialName ]; +if ( ! material ) { +material = this.materials[ 'defaultMaterial' ]; +if ( ! material ) { +material = new THREE.MeshStandardMaterial( { color: 0xDCF1FF} ); +material.name = 'defaultMaterial'; +this.materials[ 'defaultMaterial' ] = material; +} +console.warn( 'object_group "' + rawObjectDescription.objectName + '_' + rawObjectDescription.groupName + '" was defined without material! Assigning "defaultMaterial".' ); +} +if ( rawObjectDescription.smoothingGroup === 0 ) { +materialName = material.name + '_flat'; +var materialClone = this.materials[ materialName ]; +if ( ! materialClone ) { +materialClone = material.clone(); +materialClone.name = materialName; +materialClone.shading = THREE.FlatShading; +this.materials[ materialName ] = name; +} +} +vertexLength = rawObjectDescription.vertices.length; +if ( createMultiMaterial ) { +selectedMaterialIndex = materialIndexMapping[ materialName ]; +if ( ! selectedMaterialIndex ) { +selectedMaterialIndex = materialIndex; +materialIndexMapping[ materialName ] = materialIndex; +materials.push( material ); +materialIndex++; +} +bufferGeometry.addGroup( vertexGroupOffset, vertexLength / 3, selectedMaterialIndex ); +vertexGroupOffset += vertexLength / 3; +} +vertexBA.set( rawObjectDescription.vertices, vertexBAOffset ); +vertexBAOffset += vertexLength; +if ( normalBA ) { +normalBA.set( rawObjectDescription.normals, normalOffset ); +normalOffset += rawObjectDescription.normals.length; +} +if ( uvBA ) { +uvBA.set( rawObjectDescription.uvs, uvOffset ); +uvOffset += rawObjectDescription.uvs.length; +} +if ( this.debug ) this.printReport( rawObjectDescription, selectedMaterialIndex ); +} +if ( ! normalBA ) bufferGeometry.computeVertexNormals(); +if ( createMultiMaterial ) material = materials; +var mesh = new THREE.Mesh( bufferGeometry, material ); +this.sceneGraphBaseNode.add( mesh ); +this.globalObjectCount++; +}; +MeshCreator.prototype.printReport = function ( rawObjectDescription, selectedMaterialIndex ) { +console.log( +' Output Object no.: ' + this.globalObjectCount + +'\n objectName: ' + rawObjectDescription.objectName + +'\n groupName: ' + rawObjectDescription.groupName + +'\n materialName: ' + rawObjectDescription.materialName + +'\n materialIndex: ' + selectedMaterialIndex + +'\n smoothingGroup: ' + rawObjectDescription.smoothingGroup + +'\n #vertices: ' + rawObjectDescription.vertices.length / 3 + +'\n #uvs: ' + rawObjectDescription.uvs.length / 2 + +'\n #normals: ' + rawObjectDescription.normals.length / 3 +); +}; +return MeshCreator; +})(); +OBJLoader2.prototype._buildWebWorkerCode = function ( funcBuildObject, funcBuildSingelton ) { +var workerCode = ''; +workerCode += funcBuildObject( 'Consts', Consts ); +workerCode += funcBuildObject( 'Validator', Validator ); +workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser ); +workerCode += funcBuildSingelton( 'RawObject', 'RawObject', RawObject ); +workerCode += funcBuildSingelton( 'RawObjectDescription', 'RawObjectDescription', RawObjectDescription ); +return workerCode; +}; +return OBJLoader2; })(); -/* -* XSeen JavaScript Library -* http://tools.realism.com/... -* -* (C)2017 Daly Realiusm, Los Angeles -* Dual licensed under the MIT and GPL -* -* Some portions may be extracted from -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -* -* Based on code originally provided by -* Philip Taylor: http://philip.html5.org -*/ -/** -* The Namespace container for x3dom objects. -* @namespace x3dom -* -* Removed THREE loaders -loaders: { -'file' : new THREE.FileLoader(), -'image' : 0, -}, -* */ -xseen.updateOnLoad = function () -{ -this.loader.Null = this.loader.X3dLoader; -this.loadMgr = new LoadManager(); -this.loader.X3dLoader = this.loadMgr; -this.loader.ColladaLoader = new THREE.ColladaLoader(); -this.loader.GltfLegacy = new THREE.GLTFLoader(); -this.loader.GltfLoader = new THREE.GLTF2Loader(); -this.loader.ObjLoader = new THREE.OBJLoader2(); -this.loader.ImageLoader = new THREE.TextureLoader(); -this.parseUrl = function (url) -{ -var parser = document.createElement('a'), -searchObject = {}, -queries, split, i, pathFile, path, file, extension; -parser.href = url; -queries = parser.search.replace(/^\?/, '').split('&'); -for( i = 0; i < queries.length; i++ ) { -split = queries[i].split('='); -searchObject[split[0]] = split[1]; -} -pathFile = parser.pathname.split('/'); -file = pathFile[pathFile.length-1]; -pathFile.length --; -path = '/' + pathFile.join('/'); -extension = file.split('.'); -extension = extension[extension.length-1]; -return { -protocol: parser.protocol, -host: parser.host, -hostname: parser.hostname, -port: parser.port, -pathname: parser.pathname, -path: path, -file: file, -extension: extension, -search: parser.search, -searchObject: searchObject, -hash: parser.hash -}; -}; -this.versionInfo = this.generateVersion(); -this.debug = { -INFO: "INFO", -WARNING: "WARNING", -ERROR: "ERROR", -EXCEPTION: "EXCEPTION", -isActive: false, -isFirebugAvailable: false, -isSetup: false, -isAppend: false, -numLinesLogged: 0, -maxLinesToLog: 10000, -logContainer: null, -/** @brief Setup the xseen.debug object. -Checks for firebug and creates the container div for the logging -messages. -*/ -setup: function() { -if (xseen.debug.isSetup) { return; } -try { -if (window.console.firebug !== undefined) { -xseen.debug.isFirebugAvailable = true; -} -} -catch (err) { -xseen.debug.isFirebugAvailable = false; -} -xseen.debug.setupLogContainer(); -xseen.debug.isSetup = true; -}, -/** @brief Activates the log -*/ -activate: function(visible) { -xseen.debug.isActive = true; -xseen.debug.logContainer.style.display = (visible) ? "block" : "none"; -if(!xseen.debug.isAppend) { -if(navigator.appName == "Microsoft Internet Explorer") { -xseen.debug.logContainer.style.marginLeft = "8px"; -document.documentElement.appendChild(xseen.debug.logContainer); -}else{ -document.body.appendChild(xseen.debug.logContainer); -} -xseen.debug.isAppend = true; -} -}, -/** @brief Inserts a container div for the logging messages into the HTML page -*/ -setupLogContainer: function() { -xseen.debug.logContainer = document.createElement("div"); -xseen.debug.logContainer.id = "xseen_logdiv"; -xseen.debug.logContainer.setAttribute("class", "xseen-logContainer"); -xseen.debug.logContainer.style.clear = "both"; -}, -/** @brief Generic logging function which does all the work. -@param msg the log message -@param logType the type of the log message. One of INFO, WARNING, ERROR -or EXCEPTION. -*/ -doLog: function(msg, logType) { -if (!xseen.debug.isActive) { return; } -if (xseen.debug.numLinesLogged === xseen.debug.maxLinesToLog) { -msg = "Maximum number of log lines (=" + xseen.debug.maxLinesToLog + ") reached. Deactivating logging..."; -} -if (xseen.debug.numLinesLogged > xseen.debug.maxLinesToLog) { return; } -var node = document.createElement("p"); -node.style.margin = 0; -switch (logType) { -case xseen.debug.INFO: -node.style.color = "#009900"; -break; -case xseen.debug.WARNING: -node.style.color = "#cd853f"; -break; -case xseen.debug.ERROR: -node.style.color = "#ff4500"; -break; -case xseen.debug.EXCEPTION: -node.style.color = "#ffff00"; -break; -default: -node.style.color = "#009900"; -break; -} -try { -node.innerHTML = logType + ": " + msg; -xseen.debug.logContainer.insertBefore(node, xseen.debug.logContainer.firstChild); -} catch (err) { -if (window.console.firebug !== undefined) { -window.console.warn(msg); -} -} -if (xseen.debug.isFirebugAvailable) { -switch (logType) { -case xseen.debug.INFO: -window.console.info(msg); -break; -case xseen.debug.WARNING: -window.console.warn(msg); -break; -case xseen.debug.ERROR: -window.console.error(msg); -break; -case xseen.debug.EXCEPTION: -window.console.debug(msg); -break; -default: -break; -} -} -xseen.debug.numLinesLogged++; -}, -/** Log an info message. */ -logInfo: function(msg) { -xseen.debug.doLog(msg, xseen.debug.INFO); -}, -/** Log a warning message. */ -logWarning: function(msg) { -xseen.debug.doLog(msg, xseen.debug.WARNING); -}, -/** Log an error message. */ -logError: function(msg) { -xseen.debug.doLog(msg, xseen.debug.ERROR); -}, -/** Log an exception message. */ -logException: function(msg) { -xseen.debug.doLog(msg, xseen.debug.EXCEPTION); -}, -/** Log an assertion. */ -assert: function(c, msg) { -if (!c) { -xseen.debug.doLog("Assertion failed in " + xseen.debug.assert.caller.name + ': ' + msg, xseen.debug.ERROR); -} -}, -/** -Checks the type of a given object. -@param obj the object to check. -@returns one of; "boolean", "number", "string", "object", -"function", or "null". -*/ -typeOf: function (obj) { -var type = typeof obj; -return type === "object" && !obj ? "null" : type; -}, -/** -Checks if a property of a specified object has the given type. -@param obj the object to check. -@param name the property name. -@param type the property type (optional, default is "function"). -@returns true if the property exists and has the specified type, -otherwise false. -*/ -exists: function (obj, name, type) { -type = type || "function"; -return (obj ? this.typeOf(obj[name]) : "null") === type; -}, -/** -Dumps all members of the given object. -*/ -dumpFields: function (node) { -var str = ""; -for (var fName in node) { -str += (fName + ", "); -} -str += '\n'; -xseen.debug.logInfo(str); -return str; -} -}; -this.debug.setup(); -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -/* -* xseen.nodes. is the definition of -* All internal variables are stored in ._internal. All functions start with '_' -* -* This is a bare-bones setup. There is no error checking - missing arguments or -* methods that do not exist (e.g., .init) -* -* These are intended to be development support routines. It is anticipated that in -* production systems the array dump (_dumpTable) would be loaded. As a result, it is necessary -* to have a routine that dumps out the Object so it can be captured and saved. A routine -* or documentation on how to load the Object would also be good. -* -* Fields are added with the .addField method. It takes its values from the argument list -* or an object passed as the first argument. The properties of the argument are: -* name - the name of the field. This is converted to lowercase before use -* datatype - the datatype of the field. There must be a method in xseen.types by this name -* defaultValue - the default value of the field to be used if the field is not present or incorrectly defined. -* If this argument is an array, then it is the set of allowed values. The first element is the default. -* enumerated - the list of allowed values when the datatype only allows specific values for this field (optional) -* animatable - Flag (T/F) indicating if the field is animatable. Generally speaking, enumerated fieles are not animatable -*/ -xseen.nodes = { -'_defineNode' : function(nodeName, nodeComponent, nodeMethod) { -methodBase = 'xseen.node.'; -methodBase = ''; -node = { -'tag' : nodeName, -'taglc' : nodeName.toLowerCase(), -'component' : nodeComponent, -'method' : methodBase + nodeMethod, -'fields' : [], -'fieldIndex': [], -'addField' : function (fieldObj, datatype, defaultValue) { -var fieldName, namelc, enumerated, animatable; -if (typeof(fieldObj) === 'object') { -fieldName = fieldObj.name; -datatype = fieldObj.datatype; -defaultValue = fieldObj.defaultValue; -enumerated = (typeof(fieldObj.enumerated) === 'undefined') ? [] : fieldObj.enumerated; -animatable = (typeof(fieldObj.animatable) === 'undefined') ? false : fieldObj.animatable; -} else { -fieldName = fieldObj; -animatable = false; -if (typeof(defaultValue) == 'array') { -enumerated = defaultValue; -defaultValue = enumerated[0]; -} else { -enumerated = []; -} -} -namelc = fieldName.toLowerCase(); -this.fields.push ({ -'field' : fieldName, -'fieldlc' : namelc, -'type' : datatype, -'default' : defaultValue, -'enumeration' : enumerated, -'animatable' : animatable, -'clone' : this.cloneField, -'setFieldName' : this.setFieldName, -}); -this.fieldIndex[namelc] = this.fields.length-1; -return this; -}, -'addNode' : function () { -xseen.parseTable[this.taglc] = this; -}, -'cloneField' : function () { -var newFieldObject = { -'field' : this.field, -'fieldlc' : this.fieldlc, -'type' : this.type, -'default' : 0, -'enumeration' : [], -'animatable' : this.animatable, -'clone' : this.clone, -'setFieldName' : this.setFieldName, -}; -for (var i=0; i= 0) { -this._internals.activeNode = this._internals.stack[this._internals.active]; -} else { -this._internals.activeNode = this._internals.defaultNode; -} -} -this.init = function() { // Clears existing stack -this._internals.stack = []; -} -this.pushDown = function(node) { // Push new node onto stack and make active -this._internals.stack.push (node); -this._setActiveNode(); -} -this.popOff = function() { // Pop new node onto stack and make active -this._internals.stack.pop(); -this._setActiveNode(); -} -this.getActive = function() { -return this._internals.activeNode; -} -} -/* -* xseen.types contains the datatype and conversion utilities. These convert one format to another. -* Any method ending in 'toX' where 'X' is some datatype is a conversion to that type -* Other methods convert from string with space-spearated values -*/ -xseen.types = { -'Deg2Rad' : Math.PI / 180, -'SFFloat' : function (value, def) -{ -if (value === null) {return def;} -if (Number.isNaN(value)) {return def}; -return value; -}, -'SFInt' : function (value, def) -{ -if (value === null) {return def;} -if (Number.isNaN(value)) {return def}; -return Math.round(value); -}, -'SFBool' : function (value, def) -{ -if (value === null) {return def;} -if (value) {return true;} -if (!value) {return false;} -return def; -}, -'SFTime' : function (value, def) -{ -if (value === null) {return def;} -if (Number.isNaN(value)) {return def}; -return value; -}, -'SFVec3f' : function (value, def) -{ -if (value === null) {return def;} -var v3 = value.split(' '); -if (v3.length < 3 || Number.isNaN(v3[0]) || Number.isNaN(v3[1]) || Number.isNaN(v3[2])) { -return def; -} -return [v3[0]-0, v3[1]-0, v3[2]-0]; -}, -'SFVec2f' : function (value, def) -{ -if (value === null) {return def;} -var v2 = value.split(' '); -if (v2.length != 2 || Number.isNaN(v2[0]) || Number.isNaN(v2[1])) { -return def; -} -return [v2[0]-0, v2[1]-0]; -}, -'SFRotation' : function (value, def) -{ -if (value === null) {return def;} -var v4 = value.split(' '); -if (v4.length != 4 || Number.isNaN(v4[0]) || Number.isNaN(v4[1]) || Number.isNaN(v4[2]) || Number.isNaN(v4[3])) { -return def; -} -var result = { -'vector' : [v4[0], v4[1], v4[2], v4[3]], -'axis_angle' : [{'x': v4[0], 'y': v4[1], 'z': v4[2]}, v4[3]], -}; -return result; -}, -'SFColor' : function (value, defaultString) -{ -var v3 = this.SFVec3f(value, defaultString); -v3[0] = Math.min(Math.max(v3[0], 0.0), 1.0); -v3[1] = Math.min(Math.max(v3[1], 0.0), 1.0); -v3[2] = Math.min(Math.max(v3[2], 0.0), 1.0); -return v3; -}, -'SFString' : function (value, def) -{ -if (value === null) {value = def;} -return value; -}, -'MFFloat' : function (value, def) -{ -var defReturn = (def == '') ? [] : def; -if (value === null) {return defReturn;} -var mi = value.split(' '); -var rv = []; -for (var i=0; iDocumentation."]; -var version = { -major : Major, -minor : Minor, -patch : Patch, -preRelease : PreRelease, -release : Release, -version : '', -date : Date, -splashText : SplashText -}; -version.version = version.major + '.' + version.minor + '.' + version.patch; -version.version += (version.preRelease != '') ? '-' + version.preRelease : ''; -version.version += (version.release != '') ? '+' + version.release : ''; -return version; -} -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -xseen.node.core_NOOP = { -'init' : function (e,p) {}, -'fin' : function (e,p) {} -}; -xseen.node.parsing = function (s, e) { -xseen.debug.logInfo ('Parsing init details stub for ' + s); -} -xseen.node.af_Entity = { -'init' : function (e,p) -{ -xseen.node.parsing('A-Frame Entity'); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Assets = { -'init' : function (e,p) {}, -'fin' : function (e,p) {} -}; -xseen.node.af_AssetItem = { -'init' : function (e,p) // Only field is SRC. -{ -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Mixin = { -'init' : function (e,p) // Lots of fields -- all nebelous until used -{ -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Appearance = function (e) { -var parameters = { -'aoMap' : e._xseen.fields['ambient-occlusion-map'], -'aoMapIntensity' : e._xseen.fields['ambient-occlusion-map-intensity'], -'color' : e._xseen.fields['color'], -'displacementMap' : e._xseen.fields['displacement-map'], -'displacementScale' : e._xseen.fields['displacement-scale'], -'displacementBias' : e._xseen.fields['displacement-bias'], -'envMap' : e._xseen.fields['env-map'], -'normalMap' : e._xseen.fields['normal-map'], -'normalScale' : e._xseen.fields['normal-scale'], -'wireframe' : e._xseen.fields['wireframe'], -'wireframeLinewidth' : e._xseen.fields['wireframe-linewidth'], -}; -var material = new THREE.MeshPhongMaterial(parameters); -return material; -/* -* === All Entries === -.aoMap -.aoMapIntensity -.color -.combine -.displacementMap -.displacementScale -.displacementBias -.emissive -.emissiveMap -.emissiveIntensity -.envMap -.lightMap -.lightMapIntensity -.map -.morphNormals -.morphTargets -.normalMap -.normalScale -.reflectivity -.refractionRatio -.shininess -.skinning -.specular -.specularMap -.wireframe -.wireframeLinecap -.wireframeLinejoin -.wireframeLinewidth -e._xseen.fields['ambient-occlusion-map'] -e._xseen.fields['ambient-occlusion-map-intensity'] -e._xseen.fields['ambient-occlusion-texture-offset'] -e._xseen.fields['ambient-occlusion-texture-repeat'] -e._xseen.fields['color'] -e._xseen.fields['displacement-bias'] -e._xseen.fields['displacement-map'] -e._xseen.fields['displacement-scale'] -e._xseen.fields['displacement-texture-offset'] -e._xseen.fields['displacement-texture-repeat'] -e._xseen.fields['env-map'] -e._xseen.fields['fog'] -e._xseen.fields['metalness'] -e._xseen.fields['normal-map'] -e._xseen.fields['normal-scale'] -e._xseen.fields['normal-texture-offset'] -e._xseen.fields['normal-texture-repeat'] -e._xseen.fields['repeat'] -e._xseen.fields['roughness'] -e._xseen.fields['spherical-env-map'] -e._xseen.fields['src'] -e._xseen.fields['wireframe'] -e._xseen.fields['wireframe-linewidth'] -* === Unused Entries === -.combine -.emissive -.emissiveMap -.emissiveIntensity -.lightMap -.lightMapIntensity -.map -.morphNormals -.morphTargets -.reflectivity -.refractionRatio -.shininess -.skinning -.specular -.specularMap -.wireframeLinecap -.wireframeLinejoin -e._xseen.fields['ambient-occlusion-texture-offset'] -e._xseen.fields['ambient-occlusion-texture-repeat'] -e._xseen.fields['displacement-texture-offset'] -e._xseen.fields['displacement-texture-repeat'] -e._xseen.fields['fog'] -e._xseen.fields['metalness'] -e._xseen.fields['normal-texture-offset'] -e._xseen.fields['normal-texture-repeat'] -e._xseen.fields['repeat'] -e._xseen.fields['roughness'] -e._xseen.fields['spherical-env-map'] -e._xseen.fields['src'] -*/ -} -xseen.node.af_Box = { -'init' : function (e,p) -{ -var geometry = new THREE.BoxGeometry( -e._xseen.fields.width, -e._xseen.fields.height, -e._xseen.fields.depth, -e._xseen.fields['segments-width'], -e._xseen.fields['segments-height'], -e._xseen.fields['segments-depth'] -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Cone = { -'init' : function (e,p) -{ -var geometry = new THREE.ConeGeometry( -e._xseen.fields.radius, -e._xseen.fields.height, -e._xseen.fields['segments-radial'], -e._xseen.fields['segments-height'], -e._xseen.fields['open-ended'], -e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, -e._xseen.fields['theta-length'] * xseen.types.Deg2Rad -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Cylinder = { -'init' : function (e,p) -{ -var geometry = new THREE.CylinderGeometry( -e._xseen.fields['radius-top'], -e._xseen.fields['radius-bottom'], -e._xseen.fields.height, -e._xseen.fields['segments-radial'], -e._xseen.fields['segments-height'], -e._xseen.fields['open-ended'], -e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, -e._xseen.fields['theta-length'] * xseen.types.Deg2Rad -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Dodecahedron = { -'init' : function (e,p) -{ -var geometry = new THREE.DodecahedronGeometry( -e._xseen.fields.radius, -e._xseen.fields.detail -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Icosahedron = { -'init' : function (e,p) -{ -var geometry = new THREE.IcosahedronGeometry( -e._xseen.fields.radius, -e._xseen.fields.detail -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Octahedron = { -'init' : function (e,p) -{ -var geometry = new THREE.OctahedronGeometry( -e._xseen.fields.radius, -e._xseen.fields.detail -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Sphere = { -'init' : function (e,p) -{ -var geometry = new THREE.SphereGeometry( -e._xseen.fields.radius, -e._xseen.fields['segments-width'], -e._xseen.fields['segments-height'], -e._xseen.fields['phi-start'] * xseen.types.Deg2Rad, -e._xseen.fields['phi-length'] * xseen.types.Deg2Rad, -e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, -e._xseen.fields['theta-length'] * xseen.types.Deg2Rad -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Tetrahedron = { -'init' : function (e,p) -{ -var geometry = new THREE.TetrahedronGeometry( -e._xseen.fields.radius, -e._xseen.fields.detail -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -xseen.node.af_Torus = { -'init' : function (e,p) -{ -var geometry = new THREE.TorusGeometry( -e._xseen.fields.radius, -e._xseen.fields.tube, -e._xseen.fields['segments-radial'], -e._xseen.fields['segments-tubular'], -e._xseen.fields.arc * xseen.types.Deg2Rad -); -var appearance = xseen.node.af_Appearance (e); -var mesh = new THREE.Mesh (geometry, appearance); -var group = new THREE.Group(); -group.add (mesh); -if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} -p._xseen.children.push(group); -}, -'fin' : function (e,p) {} -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -xseen.node.appearance_Material = { -'init' : function (e,p) -{ -var transparency = e._xseen.fields.transparency - 0; -var shininess = e._xseen.fields.shininess - 0; -var colorDiffuse = xseen.types.Color3toInt (e._xseen.fields.diffusecolor); -var colorEmissive = xseen.types.Color3toInt (e._xseen.fields.emissivecolor); -var colorSpecular = xseen.types.Color3toInt (e._xseen.fields.specularcolor); -p._xseen.material = new THREE.MeshPhongMaterial( { -'color' : colorDiffuse, -'emissive' : colorEmissive, -'specular' : colorSpecular, -'shininess' : shininess, -'opacity' : 1.0-transparency, -'transparent' : (transparency > 0.0) ? true : false -} ); -e._xseen.animate['diffusecolor'] = p._xseen.material.color; -e._xseen.animate['emissivecolor'] = p._xseen.material.emissive; -e._xseen.animate['specularcolor'] = p._xseen.material.specular; -e._xseen.animate['transparency'] = p._xseen.material.opacity; -e._xseen.animate['shininess'] = p._xseen.material.shininess; -}, -'fin' : function (e,p) {} -}; -xseen.node.appearance_ImageTexture = { -'init' : function (e,p) -{ -p._xseen.texture = xseen.loader.ImageLoader.load(e._xseen.fields.url); -p._xseen.texture.wrapS = (e._xseen.fields.repeats) ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; -p._xseen.texture.wrapT = (e._xseen.fields.repeatt) ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; -}, -'fin' : function (e,p) {} -}; -xseen.node.appearance_Appearance = { -'init' : function (e,p) {}, -'fin' : function (e,p) -{ -if (typeof(e._xseen.texture) !== 'undefined' && e._xseen.texture !== null) { -e._xseen.material.map = e._xseen.texture; -} -p._xseen.appearance = e._xseen.material; -} -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -xseen.node.geometry_Coordinate = { -'init' : function (e,p) -{ -var vertices = []; -for (var i=0; i= 0 where each triple defines a triangle face. It is assumed that the -* indices define the face in counter-clockwise order when looking at the face. -* vertices - an array of THREE.Vector3 points -*/ -xseen.node.geometry__Indexed3 = function (indices, vertices, normals=[], color=[]) { -var i, face, normal=[], faceCount=0, n; -var useNormals = (normals.length > 0) ? true : false; -var useColor = (color.length > 0) ? true : false; -var maxIndex = Math.max.apply(null, indices); -var minIndex = Math.min.apply(null, indices); -if (maxIndex >= vertices.length) { -console.log ('Maximum index ('+maxIndex+') exceeds vertex count ('+vertices.length+'). No geometry is created'); -return; -} -if (useNormals && maxIndex >= normals.length) { -console.log ('Maximum index ('+maxIndex+') exceeds normal count ('+normals.length+'). No geometry is created'); -return; -} -if (useColor && maxIndex >= color.length) { -console.log ('Maximum index ('+maxIndex+') exceeds color count ('+color.length+'). No geometry is created'); -return; -} -if (minIndex < 0) { -console.log ('Minimum index ('+minIndex+') less than zero. No geometry is created'); -return; -} -if (indices.length % 3 != 0) { -console.log ('Number of indices ('+indices.length+') not divisible by 3. No geometry is created'); -return; -} -var geometry = new THREE.Geometry(); -var normal_pz = new THREE.Vector3 (0, 0, 1); -var normal_mz = new THREE.Vector3 (0, 0, -1); -for (var i=0; i 0) {clip.duration = e._xseen.fields.duration;} -e._xseen.mixer.clipAction( clip ).play(); -} ); -} else { // Play a specific animation -var clip = THREE.AnimationClip.findByName(response.animations, e._xseen.fields.playonload); -var action = e._xseen.mixer.clipAction (clip); -action.play(); -} -} -} -} -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -xseen.node.core_NOOP = { -'init' : function (e,p) {}, -'fin' : function (e,p) {} -}; -xseen.node.core_WorldInfo = { -'init' : function (e,p) {parsing('WorldInfo', e)}, -'fin' : function (e,p) {} -}; -function parsing (s, e) { -xseen.debug.logInfo ('Parsing init details stub for ' + s); -} -xseen.node.unk_Viewpoint = { -'init' : function (e,p) -{ // This should really go in a separate push-down list for Viewpoints -e._xseen.fields._radius0 = Math.sqrt( e._xseen.fields.position[0]*e._xseen.fields.position[0] + -e._xseen.fields.position[1]*e._xseen.fields.position[1] + -e._xseen.fields.position[2]*e._xseen.fields.position[2]); -if (!e._xseen.sceneInfo.tmp.activeViewpoint) { -e._xseen.sceneInfo.stacks.Viewpoints.pushDown(e); -e._xseen.sceneInfo.tmp.activeViewpoint = true; -} -}, -'fin' : function (e,p) {} -}; -xseen.node.unk_Shape = { -'init' : function (e,p) {}, -'fin' : function (e,p) -{ -if (typeof(e._xseen.materialProperty) !== 'undefined') { -e._xseen.appearance.vertexColors = THREE.VertexColors; -e._xseen.appearance._needsUpdate = true; -e._xseen.appearance.needsUpdate = true; -} -var m = new THREE.Mesh (e._xseen.geometry, e._xseen.appearance); -p._xseen.children.push(m); -m = null; -} -}; -xseen.node.grouping_Transform = { -'init' : function (e,p) -{ -var group = new THREE.Group(); -if (e.nodeName == "TRANSFORM") { -var rotation = xseen.types.Rotation2Quat(e._xseen.fields.rotation); -group.name = 'Transform children [' + e.id + ']'; -group.position.x = e._xseen.fields.translation[0]; -group.position.y = e._xseen.fields.translation[1]; -group.position.z = e._xseen.fields.translation[2]; -group.scale.x = e._xseen.fields.scale[0]; -group.scale.y = e._xseen.fields.scale[1]; -group.scale.z = e._xseen.fields.scale[2]; -group.quaternion.x = rotation.x; -group.quaternion.y = rotation.y; -group.quaternion.z = rotation.z; -group.quaternion.w = rotation.w; -e._xseen.animate['translation'] = group.position; -e._xseen.animate['rotation'] = group.quaternion; -e._xseen.animate['scale'] = group.scale; -} -e._xseen.sceneNode = group; -}, -'fin' : function (e,p) -{ -e._xseen.children.forEach (function (child, ndx, wholeThing) -{ -e._xseen.sceneNode.add(child); -}); -p._xseen.children.push(e._xseen.sceneNode); -} -}; -xseen.node.lighting_Light = { -'init' : function (e,p) -{ -var color = xseen.types.Color3toInt (e._xseen.fields.color); -var intensity = e._xseen.fields.intensity - 0; -var lamp, type=e._xseen.fields.type.toLowerCase(); -/* -if (typeof(p._xseen.children) == 'undefined') { -console.log('Parent of Light does not have children...'); -p._xseen.children = []; -} -*/ -if (type == 'point') { -lamp = new THREE.PointLight (color, intensity); -lamp.distance = Math.max(0.0, e._xseen.fields.radius - 0); -lamp.decay = Math.max (.1, e._xseen.fields.attenuation[1]/2 + e._xseen.fields.attenuation[2]); -} else if (type == 'spot') { -lamp = new THREE.SpotLight (color, intensity); -lamp.position.set(0-e._xseen.fields.direction[0], 0-e._xseen.fields.direction[1], 0-e._xseen.fields.direction[2]); -lamp.distance = Math.max(0.0, e._xseen.fields.radius - 0); -lamp.decay = Math.max (.1, e._xseen.fields.attenuation[1]/2 + e._xseen.fields.attenuation[2]); -lamp.angle = Math.max(0.0, Math.min(1.5707963267948966192313216916398, e._xseen.fields.cutoffangle)); -lamp.penumbra = 1 - Math.max(0.0, Math.min(lamp.angle, e._xseen.fields.beamwidth)) / lamp.angle; -} else { // DirectionalLight (by default) -lamp = new THREE.DirectionalLight (color, intensity); -lamp.position.x = 0-e._xseen.fields.direction[0]; -lamp.position.y = 0-e._xseen.fields.direction[1]; -lamp.position.z = 0-e._xseen.fields.direction[2]; -} -p._xseen.children.push(lamp); -lamp = null; -} -, -'fin' : function (e,p) -{ -} -}; -xseen.node.networking_Inline = { -'init' : function (e,p) -{ -if (typeof(e._xseen.processedUrl) === 'undefined' || !e._xseen.requestedUrl) { -var uri = xseen.parseUrl (e._xseen.fields.url); -var type = uri.extension; -e._xseen.loadGroup = new THREE.Group(); -e._xseen.loadGroup.name = 'Inline content [' + e.id + ']'; -console.log ('Created Inline Group with UUID ' + e._xseen.loadGroup.uuid); -var userdata = {'requestType':'x3d', 'e':e, 'p':p} -if (type.toLowerCase() == 'json') { -userdata.requestType = 'json'; -xseen.loadMgr.loadJson (e._xseen.fields.url, this.loadSuccess, xseen.loadProgress, xseen.loadError, userdata); -} else { -xseen.loadMgr.loadXml (e._xseen.fields.url, this.loadSuccess, xseen.loadProgress, xseen.loadError, userdata); -} -e._xseen.requestedUrl = true; -} -p._xseen.children.push(e._xseen.loadGroup); -console.log ('Using Inline Group with UUID ' + e._xseen.loadGroup.uuid); -}, -'fin' : function (e,p) -{ -}, -'loadSuccess' : -function (response, userdata, xhr) { -userdata.e._xseen.processedUrl = true; -userdata.e._xseen.loadResponse = response; -console.log("download successful for "+userdata.e.id); -if (userdata.requestType == 'json') { -var tmp = {'scene': response}; -response = null; -response = (new JSONParser()).parseJavaScript(tmp); -} -var start = {'_xseen':0}; -var findSceneTag = function (fragment) { -if (typeof(fragment._xseen) === 'undefined') {fragment._xseen = {'childCount': -1};} -if (fragment.nodeName.toLowerCase() == 'scene') { -start = fragment; -return; -} else if (fragment.children.length > 0) { -for (fragment._xseen.childCount=0; fragment._xseen.childCount 0) { -userdata.e.appendChild(start.children[0]); -} -xseen.Parse(userdata.e, userdata.p, userdata.p._xseen.sceneInfo); -userdata.e._xseen.children.forEach (function (child, ndx, wholeThing) -{ -userdata.e._xseen.loadGroup.add(child); -console.log ('...Adding ' + child.type + ' (' + child.name + ') to Inline Group? with UUID ' + userdata.e._xseen.loadGroup.uuid + ' (' + userdata.e._xseen.loadGroup.name + ')'); -}); -userdata.p._xseen.sceneInfo.scene.updateMatrixWorld(); -} else { -console.log("Found illegal X3D file -- no 'scene' tag"); -} -} -}; -xseen.node.core_Scene = { -'init' : function (e,p) -{ -var width = e._xseen.sceneInfo.size.width; -var height = e._xseen.sceneInfo.size.height; -e._xseen.renderer = { -'canvas' : e._xseen.sceneInfo.scene, -'width' : width, -'height' : height, -'camera' : e._xseen.sceneInfo.camera[0], -'renderer' : e._xseen.sceneInfo.renderer, -}; -e._xseen.renderer.renderer.setSize (width, height); -var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 ); -camera.position.x = 0; // hardwired for now... -camera.position.y = 0; -camera.position.z = 4; -e._xseen.renderer.camera = camera; -}, -/* -* This appears now to be working!!! -* -* Late loading content is not getting inserted into the scene graph for rendering. Need to read -* THREE docs about how to do that. -* Camera will need to be redone. Existing camera is treated as a special child. A separate camera -* should be established and Viewpoint nodes define "photostops" rather than a camera. The camera is -* in effect, parented to the "photostop". This probably needs to list of Viewpoints discussed in the -* X3D specification. -*/ -'fin' : function (e,p) -{ -e._xseen.children.forEach (function (child, ndx, wholeThing) -{ -console.log('Adding child of type ' + child.type + ' (' + child.name + ')'); -e._xseen.renderer.canvas.add(child); -}); -xseen.dumpSceneGraph (); -e._xseen.renderer.renderer.render( e._xseen.renderer.canvas, e._xseen.renderer.camera ); -xseen.debug.logInfo("Rendered all elements -- Starting animation"); -var vp = xseen.sceneInfo[0].stacks.Viewpoints.getActive(); -var currentCamera = xseen.sceneInfo[0].element._xseen.renderer.camera; -currentCamera.position.x = vp._xseen.fields.position[0]; -currentCamera.position.y = vp._xseen.fields.position[1]; -currentCamera.position.z = vp._xseen.fields.position[2]; -xseen.render(); -} -}; -xseen.node.env_Background = { -'init' : function (e,p) -{ -var color = new THREE.Color(e._xseen.fields.skycolor[0], e._xseen.fields.skycolor[1], e._xseen.fields.skycolor[2]); -var textureCube = new THREE.CubeTextureLoader() -.load ([e._xseen.fields.srcright, -e._xseen.fields.srcleft, -e._xseen.fields.srctop, -e._xseen.fields.srcbottom, -e._xseen.fields.srcfront, -e._xseen.fields.srcback], -this.loadSuccess({'e':e, 'p':p}) -); -e._xseen.sceneInfo.scene.background = color; -/* -var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } ); -var size = 1; -var geometry = new THREE.Geometry(); -geometry.vertices.push ( -new THREE.Vector3(-size, -size, size), -new THREE.Vector3( size, -size, size), -new THREE.Vector3( size, -size, -size), -new THREE.Vector3(-size, -size, -size), -new THREE.Vector3(-size, size, size), -new THREE.Vector3( size, size, size), -new THREE.Vector3( size, size, -size), -new THREE.Vector3(-size, size, -size) -); -geometry.faces.push ( // external facing geometry -new THREE.Face3(0, 1, 5), -new THREE.Face3(0, 5, 4), -new THREE.Face3(1, 2, 6), -new THREE.Face3(1, 6, 5), -new THREE.Face3(2, 3, 7), -new THREE.Face3(2, 7, 6), -new THREE.Face3(3, 0, 4), -new THREE.Face3(3, 4, 7), -new THREE.Face3(4, 5, 6), -new THREE.Face3(4, 6, 7), -new THREE.Face3(0, 2, 1), -new THREE.Face3(0, 3, 2), -); -geometry.computeBoundingSphere(); -var mesh = new THREE.Mesh (geometry, material); -e._xseen.sceneInfo.element._xseen.renderer.canvas.add(mesh); -*/ -}, -'fin' : function (e,p) -{ -p._xseen.appearance = e._xseen.material; -}, -'loadSuccess' : function (userdata) -{ -var e = userdata.e; -var p = userdata.p; -return function (textureCube) -{ -e._xseen.processedUrl = true; -e._xseen.loadTexture = textureCube; -e._xseen.sceneInfo.scene.background = textureCube; -} -}, -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -xseen.node.x_Animate = { -'init' : function (e,p) -{ -var delay = e._xseen.fields.delay * 1000; // Convert to milliseconds -var duration = e._xseen.fields.duration * 1000; // Convert to milliseconds -var repeat = (e._xseen.fields.repeat < 0) ? Infinity : e._xseen.fields.repeat; -var interpolator = e._xseen.fields.interpolator; -var easing = e._xseen.fields.easing; -var fields = xseen.parseTable[p.localName.toLowerCase()].fields; -var fieldIndex = xseen.parseTable[p.localName.toLowerCase()].fieldIndex; -var toField = e._xseen.fields.field; -var toFieldIndex = fieldIndex[toField]; -if (typeof(fields[toFieldIndex]) === 'undefined') { -xseen.debug.logInfo("Field '" + toField + "' not found in parent (" + p.localName.toLowerCase() + "). No animation performed."); -return; -} -var fieldObject = fields[toFieldIndex].clone().setFieldName('to'); // Parse table entry for 'toField' -var to = xseen.nodes._parseField(fieldObject, e); // Parsed data -- need to convert to THREE format -var interpolation; -if (fieldObject.type == 'SFVec3f') { -interpolation = TWEEN.Interpolation.Linear; -to = xseen.types.Vector3(to); -xseen.debug.logInfo("Interpolating field '" + toField + "' as 3-space."); -} else if (fieldObject.type == 'SFColor') { -interpolation = this.Interpolator.color; -to = new THREE.Color (xseen.types.Color3toInt(to)); -xseen.debug.logInfo("Interpolation field '" + toField + "' as color."); -} else if (fieldObject.type == 'SFRotation') { -interpolation = this.Interpolator.slerp; -to = xseen.types.Rotation2Quat(to); -xseen.debug.logInfo("Interpolation field '" + toField + "' as rotation."); -} else { -xseen.debug.logInfo("Field '" + toField + "' not converted to THREE format. No animation performed."); -return; -} -var fieldTHREE = p._xseen.animate[toField]; // THREE field for animation -var tween = new TWEEN.Tween(fieldTHREE) -.to(to, duration) -.delay(delay) -.repeat(repeat) -.interpolation(interpolation); -var easingType = e._xseen.fields.easingtype; -easingType = easingType.charAt(0).toUpperCase() + easingType.slice(1); -easing = (easingType != 'Linear' && easing == '') ? 'inout' : easing; -if (easing != '') { -easing = easing.replace('in', 'In').replace('out', 'Out'); -easingType = (easingType == 'Linear') ? 'Quadratic' : easingType; -e._xseen.fields.easing = easing; -e._xseen.fields.easingtype = easingType; -tween.easing(TWEEN.Easing[easingType][easing]); -} -tween.start(); -e._xseen.animating = tween; -p._xseen.animation.push (tween); -}, -'fin' : function (e,p) {}, -/* -* Various interpolator functions for use with different data types -* All are designed to be used within TWEEN and take two arguments -* v A vector of way points (key values) that define the interpolated path -* k The interpolating factor that defines how far along the path for the current result -* -* Functions -* slerp - Linear in quaterian space (though not yet) -* color - Linear in color space (currently HSL as used by THREE) -* -*/ -'Interpolator' : { -'slerp' : function (v,k) -{ -var m = v.length - 1; -var f = m * k; -var i = Math.floor(f); -if (k < 0) { -return v[0].slerp(v[1], f); -} -if (k > 1) { -return v[m].slerp(v[m-1], m-f); -} -return v[i].slerp (v[i + 1 > m ? m : i + 1], f-i); -}, -'color' : function (v,k) -{ -var m = v.length - 1; -var f = m * k; -var i = Math.floor(f); -var fn = this.slerpCompute; -if (k < 0) { -return v[0].lerp(v[1], f); -} -if (k > 1) { -return v[m].lerp(v[m-1], m-f); -} -return v[i].lerp (v[i + 1 > m ? m : i + 1], f - i); -}, -}, -/* -Probably need to store the animation someplace. Also need to start worrying -about methods to call when animating, at least start/stop since the target is -identified by 'id'. Need to put the method references into the DOM node -There is also other unresolved references, -* capturing the 'to' data -* handling differening interpolation methods (rotation, color space, discrete) -* handling array of 'to' values (probably a child node) -* handling array of key values -* investigate other easing types (besides Quadratic) -*/ -}; -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -/* -* These are intended to be development support routines. It is anticipated that in -* production systems the array dump would be loaded. As a result, it is necessary -* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine -* or documentation on how to load the Object would also be good. -* -*/ -xseen._addAframeAppearance = function (node) { -node -.addField('ambient-occlusion-map', 'SFString', '') -.addField('ambient-occlusion-map-intensity', 'SFFloat', 1) -.addField('ambient-occlusion-texture-offset', 'SFVec2f', '0 0') -.addField('ambient-occlusion-texture-repeat', 'SFVec2f', '1 1') -.addField('color', 'Color', '#FFF') -.addField('displacement-bias', 'SFFloat', 0.5) -.addField('displacement-map', 'SFString', '') -.addField('displacement-scale', 'SFFloat', 1) -.addField('displacement-texture-offset', 'SFVec2f', '0 0') -.addField('displacement-texture-repeat', 'SFVec2f', '1 1') -.addField('env-map', 'SFString', '') -.addField('fog', 'SFBool', true) -.addField('metalness', 'SFFloat', 0) -.addField('normal-map', 'SFString', '') -.addField('normal-scale', 'SFVec2f', '1 1') -.addField('normal-texture-offset', 'SFVec2f', '0 0') -.addField('normal-texture-repeat', 'SFVec2f', '1 1') -.addField('repeat', 'SFVec2f', '1 1') -.addField('roughness', 'SFFloat', 0.5) -.addField('spherical-env-map', 'SFString', '') -.addField('src', 'SFString', '') -.addField('wireframe', 'SFBool', false) -.addField('wireframe-linewidth', 'SFInt', 2) -.addNode(); -} -xseen.nodes._defineNode('a-entity', 'A-Frame', 'af_Entity') -.addField('geometry', 'SFString', '') -.addField('material', 'SFString', '') -.addField('light', 'SFString', '') -.addNode(); -var node; -node = xseen.nodes._defineNode('a-box', 'A-Frame', 'af_Box') -.addField('depth', 'SFFloat', 1) -.addField('height', 'SFFloat', 1) -.addField('width', 'SFFloat', 512) -.addField('segments-depth', 'SFInt', 1) -.addField('segments-height', 'SFInt', 1) -.addField('segments-width', 'SFInt', 1); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-cone', 'A-Frame', 'af_Cone') -.addField('height', 'SFFloat', 1) -.addField('radius', 'SFFloat', 1) -.addField('open-ended', 'SFBool', false) -.addField('theta-start', 'SFFloat', 0) -.addField('theta-length', 'SFFloat', 360) -.addField('segments-height', 'SFInt', 1) -.addField('segments-radial', 'SFInt', 8); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-cylinder', 'A-Frame', 'af_Cylinder') -.addField('height', 'SFFloat', 1) -.addField('open-ended', 'SFBool', false) -.addField('radius-bottom', 'SFFloat', 1) -.addField('radius-top', 'SFFloat', 1) -.addField('theta-start', 'SFFloat', 0) -.addField('theta-length', 'SFFloat', 360) -.addField('segments-height', 'SFInt', 1) -.addField('segments-radial', 'SFInt', 8); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-dodecahedron', 'A-Frame', 'af_Dodecahedron') -.addField('radius', 'SFFloat', 1) -.addField('detail', 'SFFloat', 0); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-icosahedron', 'A-Frame', 'af_Icosahedron') -.addField('radius', 'SFFloat', 1) -.addField('detail', 'SFFloat', 0); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-octahedron', 'A-Frame', 'af_Octahedron') -.addField('radius', 'SFFloat', 1) -.addField('detail', 'SFFloat', 0); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-sphere', 'A-Frame', 'af_Sphere') -.addField('radius', 'SFFloat', 1) -.addField('theta-start', 'SFFloat', 0) -.addField('theta-length', 'SFFloat', 180) -.addField('phi-start', 'SFFloat', 0) -.addField('phi-length', 'SFFloat', 360) -.addField('segments-height', 'SFInt', 18) -.addField('segments-width', 'SFInt', 36); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-tetrahedron', 'A-Frame', 'af_Tetrahedron') -.addField('radius', 'SFFloat', 1) -.addField('detail', 'SFFloat', 0); -xseen._addAframeAppearance (node); -node = xseen.nodes._defineNode('a-torus', 'A-Frame', 'af_Torus') -.addField('radius', 'SFFloat', 2) -.addField('tube', 'SFFloat', 1) -.addField('arc', 'SFFloat', 360) -.addField('segments-radial', 'SFInt', 8) -.addField('segments-tubular', 'SFInt', 6); -xseen._addAframeAppearance (node); -/* -* Asset management system nodes -*/ -xseen.nodes._defineNode('a-assets', 'A-Frame', 'af_Assets') -.addNode(); -xseen.nodes._defineNode('a-asset-item', 'A-Frame', 'af_AssetItem') -.addField('src', 'SFString', '') -.addNode(); -xseen.nodes._defineNode('a-mixin', 'A-Frame', 'af_Mixin') -.addField('*', 'SFString', '') -.addNode(); -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -/* -* These are intended to be development support routines. It is anticipated that in -* production systems the array dump would be loaded. As a result, it is necessary -* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine -* or documentation on how to load the Object would also be good. -* -*/ -xseen.nodes._defineNode('Cone', 'Geometry3D', 'geometry3D_Cone') -.addField('bottomRadius', 'SFFloat', 1) -.addField('height', 'SFFloat', 2) -.addField('bottom', 'SFBool', true) -.addField('side', 'SFBool', true) -.addNode(); -xseen.nodes._defineNode('Box', 'Geometry3D', 'geometry3D_Box') -.addField('size', 'SFVec3f', [1,1,1]) -.addNode(); -xseen.nodes._defineNode('Sphere', 'Geometry3D', 'geometry3D_Sphere') -.addField('radius', 'SFFloat', '1') -.addNode(); -xseen.nodes._defineNode('Cylinder', 'Geometry3D', 'geometry3D_Cylinder') -.addField('radius', 'SFFloat', 1) -.addField('height', 'SFFloat', 2) -.addField('bottom', 'SFBool', true) -.addField('side', 'SFBool', true) -.addField('top', 'SFBool', true) -.addNode(); -xseen.nodes._defineNode ('Material', 'Appearance', 'appearance_Material') -.addField({name:'diffuseColor', datatype:'SFColor', defaultValue:[.8,.8,.8], animatable:true}) -.addField({name:'emissiveColor',datatype: 'SFColor', defaultValue:[0,0,0], animatable:true}) -.addField({name:'specularColor', datatype:'SFColor', defaultValue:[0,0,0], animatable:true}) -.addField({name:'transparency', datatype:'SFFloat', defaultValue:'0', animatable:true}) -.addField({name:'shininess', datatype:'SFFloat', defaultValue:'0', animatable:true}) -.addNode(); -xseen.nodes._defineNode ('Transform', 'Grouping', 'grouping_Transform') -.addField({name:'translation', datatype:'SFVec3f', defaultValue:[0,0,0], animatable:true}) -.addField({name:'scale', datatype:'SFVec3f', defaultValue:[1,1,1], animatable:true}) -.addField({name:'rotation', datatype:'SFRotation', defaultValue:xseen.types.SFRotation('0 1 0 0',''), animatable:true}) -.addNode(); -xseen.nodes._defineNode ('Group', 'Grouping', 'grouping_Transform') -.addNode(); -xseen.nodes._defineNode ('Light', 'Lighting', 'lighting_Light') -.addField('direction', 'SFVec3f', [0,0,-1]) // DirectionalLight -.addField('location', 'SFVec3f', [0,0,0]) // PointLight & SpotLight -.addField('radius', 'SFFloat', '100') // PointLight & SpotLight -.addField('attenuation', 'SFVec3f', [1,0,0]) // PointLight & SpotLight -.addField('beamWidth', 'SFFloat', '0.78539816339744830961566084581988') // SpotLight -.addField('cutOffAngle', 'SFFloat', '1.5707963267948966192313216916398') // SpotLight -.addField('color', 'SFColor', [1,1,1]) // General -.addField('intensity', 'SFFloat', '1') // General -.addField({name:'type', datatype:'EnumerateString', defaultValue:'Directional', enumerated:['Directional', 'Spot', 'Point'], animatable:true}) -.addNode(); -xseen.nodes._defineNode ('DirectionalLight', 'Lighting', 'lighting_Light') -.addField('direction', 'SFVec3f', [0,0,-1]) -.addField('color', 'SFColor', [1,1,1]) -.addField('intensity', 'SFFloat', '1') -.addField('type', 'SFString', 'Directional') -.addNode(); -xseen.nodes._defineNode ('PointLight', 'Lighting', 'lighting_Light') -.addField('location', 'SFVec3f', [0,0,0]) -.addField('radius', 'SFFloat', '100') -.addField('attenuation', 'SFVec3f', [1,0,0]) -.addField('color', 'SFColor', [1,1,1]) -.addField('intensity', 'SFFloat', '1') -.addField('type', 'SFString', 'Point') -.addNode(); -xseen.nodes._defineNode ('SpotLight', 'Lighting', 'lighting_Light') -.addField('direction', 'SFVec3f', [0,0,-1]) -.addField('radius', 'SFFloat', '100') -.addField('attenuation', 'SFVec3f', [1,0,0]) -.addField('beamWidth', 'SFFloat', '0.78539816339744830961566084581988') // pi/4 -.addField('cutOffAngle', 'SFFloat', '1.5707963267948966192313216916398') // pi/2 -.addField('color', 'SFColor', [1,1,1]) -.addField('intensity', 'SFFloat', '1') -.addField('type', 'SFString', 'Spot') -.addNode(); -xseen.nodes._defineNode ('Camera', 'Unknown', 'unk_Viewpoint') -.addField('position', 'SFVec3f', [0,0,10]) -.addField('orientation', 'SFRotation', xseen.types.SFRotation('0 1 0 0','')) -.addNode(); -xseen.nodes._defineNode ('Inline', 'Networking', 'networking_Inline') -.addField('url', 'SFString', '') -.addNode(); -xseen.nodes._defineNode ('scene', 'Core', 'core_Scene') -.addNode(); -xseen.nodes._defineNode ('canvas', 'Core', 'core_NOOP') -.addNode(); -xseen.nodes._defineNode ('WorldInfo', 'Core', 'core_WorldInfo') -.addNode(); -xseen.nodes._defineNode ('Appearance', 'Appearance', 'appearance_Appearance') -.addNode(); -xseen.nodes._defineNode ('ImageTexture', 'Appearance', 'appearance_ImageTexture') -.addField('url', 'SFString', '') -.addField('repeatS', 'SFBool', true) -.addField('repeatT', 'SFBool', true) -.addNode(); -xseen.nodes._defineNode ('Shape', 'Shape', 'unk_Shape') -.addNode(); -xseen.nodes._defineNode ('Viewpoint', 'Unknown', 'unk_Viewpoint') -.addField('position', 'SFVec3f', '0 0 10') -.addField('orientation', 'SFRotation', xseen.types.SFRotation('0 1 0 0','')) -.addNode(); -xseen.nodes._defineNode('Background', 'Environmental', 'env_Background') -.addField('skyColor', 'SFColor', [0,0,0]) -.addField('srcFront', 'SFString', '') -.addField('srcBack', 'SFString', '') -.addField('srcTop', 'SFString', '') -.addField('srcBottom', 'SFString', '') -.addField('srcLeft', 'SFString', '') -.addField('srcRight', 'SFString', '') -.addField('backgroundIsCube', 'SFBool', 'true') -.addNode(); -xseen.nodes._defineNode('TriangleSet', 'Geometry', 'geometry_TriangleSet') -.addField('ccw', 'SFBool', 'true') -.addField('colorPerVertex', 'SFBool', 'true') -.addField('solid', 'SFBool', 'true') -.addNode(); -xseen.nodes._defineNode('IndexedTriangleSet', 'Geometry', 'geometry_IndexedTriangleSet') -.addField('ccw', 'SFBool', true) -.addField('colorPerVertex', 'SFBool', true) -.addField('solid', 'SFBool', true) -.addField('index', 'MFInt', '') -.addNode(); -xseen.nodes._defineNode('Coordinate', 'Geometry', 'geometry_Coordinate') -.addField('point', 'MFVec3f', []) -.addNode(); -xseen.nodes._defineNode('Normal', 'Geometry', 'geometry_Normal') -.addField('vector', 'MFVec3f', []) -.addNode(); -xseen.nodes._defineNode('Color', 'Geometry', 'geometry_Color') -.addField('color', 'MFColor', []) -.addNode(); -xseen.nodes._defineNode('IndexedFaceSet', 'Geometry', 'geometry_IndexedFaceSet') -.addField('ccw', 'SFBool', true) -.addField('colorPerVertex', 'SFBool', true) -.addField('solid', 'SFBool', true) -.addField('coordIndex', 'MFInt', '') -.addNode(); -xseen.nodes._defineNode('IndexedQuadSet', 'Geometry', 'geometry_IndexedQuadSet') -.addField('ccw', 'SFBool', true) -.addField('colorPerVertex', 'SFBool', true) -.addField('solid', 'SFBool', true) -.addField('index', 'MFInt', '') -.addNode(); -xseen.nodes._defineNode('QuadSet', 'Geometry', 'geometry_QuadSet') -.addField('ccw', 'SFBool', true) -.addField('colorPerVertex', 'SFBool', true) -.addField('solid', 'SFBool', true) -.addNode(); -/* -* XSeen JavaScript library -* -* (c)2017, Daly Realism, Los Angeles -* -* portions extracted from or inspired by -* X3DOM JavaScript Library -* http://www.x3dom.org -* -* (C)2009 Fraunhofer IGD, Darmstadt, Germany -* Dual licensed under the MIT and GPL -*/ -/* -* These are intended to be development support routines. It is anticipated that in -* production systems the array dump would be loaded. As a result, it is necessary -* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine -* or documentation on how to load the Object would also be good. -* -*/ -xseen.nodes._defineNode('model', 'XSeen', 'x_Model') -.addField('src', 'SFString', '') -.addField('playonload', 'SFString', '') -.addField('duration', 'SFFloat', '-1') -.addNode(); -xseen.nodes._defineNode('animate', 'XSeen', 'x_Animate') -.addField('field', 'SFString', '') -.addField('to', 'MFFloat', '') // Needs to be 'field' datatype. That is not known until node-parse. For now insist on numeric array -.addField('delay', 'SFTime', 0) -.addField('duration', 'SFTime', 0) -.addField('repeat', 'SFInt', 0) -.addField({name:'interpolator', datatype:'EnumerateString', defaultValue:'position', enumerated:['position', 'rotation', 'color'], animatable:false}) -.addField({name:'Easing', datatype:'EnumerateString', defaultValue:'', enumerated:['', 'in', 'out', 'inout'], animatable:false}) -.addField({name:'EasingType', datatype:'EnumerateString', defaultValue:'linear', enumerated:['linear', 'quadratic', 'sinusoidal', 'exponential', 'elastic', 'bounce'], animatable:false}) -.addField('start', 'SFTime', 0) // incoming event, need to set timer trigger -.addField('end', 'SFTime', 0) // incoming event, need to set timer trigger -.addNode(); \ No newline at end of file +/* +* XSeen JavaScript Library +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +* +* Based on code originally provided by +* Philip Taylor: http://philip.html5.org +*/ +/** +* The Namespace container for x3dom objects. +* @namespace x3dom +* +* Removed THREE loaders +loaders: { +'file' : new THREE.FileLoader(), +'image' : 0, +}, +* */ +var xseen = { +canvases : [], +sceneInfo : [], +nodeDefinitions : {}, +parseTable : {}, +node : {}, +utils : {}, +loadMgr : {}, +loader : { +'Null' : '', +'ColladaLoader' : '', +'GltfLegacy' : '', +'GltfLoader' : '', +'ObjLoader' : '', +'ImageLoader' : '', +'X3dLoader' : '', +}, +loadProgress : function (xhr) { +if (xhr.total != 0) { +console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); +} +}, +loadError : function (xhr, userdata, code, message) { +console.error('An error happened on '+userdata.e.id+'\n'+code+'\n'+message); +}, +loadMime : { +'' : {name: 'Null', loader: 'Null'}, +'dae' : {name: 'Collada', loader: 'ColladaLoader'}, +'glb' : {name: 'glTF Binary', loader: 'GltfLoader'}, +'glbl' : {name: 'glTF Binary', loader: 'GltfLegacy'}, +'gltf' : {name: 'glTF JSON', loader: 'GltfLoader'}, +'obj' : {name: 'OBJ', loader: 'ObjLoader'}, +'png' : {name: 'PNG', loader: 'ImageLoader'}, +'jpg' : {name: 'JPEG', loader: 'ImageLoader'}, +'jpeg' : {name: 'JPEG', loader: 'ImageLoader'}, +'gif' : {name: 'GIF', loader: 'ImageLoader'}, +'x3d' : {name: 'X3D XML', loader: 'X3dLoader'}, +}, +array_to_object : function (a) { +var o = {}; +for(var i=0;i ' + obj.type + ' (' + obj.name + ')'); +for (var i=0; i +var validParams = xseen.array_to_object([ +'showLog', +'showStat', +'showProgress', +'PrimitiveQuality', +'components', +'loadpath', +'disableDoubleClick', +'backend', +'altImg', +'runtimeEnabled', +'keysEnabled', +'showTouchpoints', +'disableTouch', +'maxActiveDownloads' +]); +var components, prefix; +var showLoggingConsole = false; +for (var i=0; i < xseens.length; i++) { +settings.setProperty("showLog", xseens[i].getAttribute("showLog") || 'false'); +settings.setProperty("showLog", xseens[i].getAttribute("showLog") || 'true'); +settings.setProperty("showStat", xseens[i].getAttribute("showStat") || 'false'); +settings.setProperty("showProgress", xseens[i].getAttribute("showProgress") || 'true'); +settings.setProperty("PrimitiveQuality", xseens[i].getAttribute("PrimitiveQuality") || 'High'); +params = xseens[i].getElementsByTagName('PARAM'); +for (var j=0; j < params.length; j++) { +if (params[j].getAttribute('name') in validParams) { +settings.setProperty(params[j].getAttribute('name'), params[j].getAttribute('value')); +} else { +} +} +if (settings.getProperty('showLog') === 'true') { +showLoggingConsole = true; +} +if (typeof X3DOM_SECURITY_OFF != 'undefined' && X3DOM_SECURITY_OFF === true) { +components = settings.getProperty('components', xseens[i].getAttribute("components")); +if (components) { +prefix = settings.getProperty('loadpath', xseens[i].getAttribute("loadpath")); +components = components.trim().split(','); +for (j=0; j < components.length; j++) { +xseen.loadJS(components[j] + ".js", prefix); +} +} +if (xseens[i].getAttribute("src")) { +var _scene = document.createElement("scene"); +var _inl = document.createElement("Inline"); +_inl.setAttribute("url", xseens[i].getAttribute("src")); +_scene.appendChild(_inl); +xseens[i].appendChild(_scene); +} +} +} +if (showLoggingConsole == true) { +xseen.debug.activate(true); +} else { +xseen.debug.activate(false); +} +/* Don't think so -- commented out +xseens = Array.map(xseens, function (n) { +n.hasRuntime = true; +return n; +}); +*/ +if (xseen.versionInfo !== undefined) { +xseen.debug.logInfo("XSeen version " + xseen.versionInfo.version + ", " + +"Date " + xseen.versionInfo.date); +xseen.debug.logInfo(xseen.versionInfo.splashText); +} +var x_element; +var x_canvas; +var altDiv, altP, aLnk, altImg; +var t0, t1; +for (var i=0; i < xseens.length; i++) +{ +x_element = xseens[i]; +x_canvas = new THREE.Scene(); // May need addtl info if multiple: xseen.X3DCanvas(x_element, xseen.canvases.length); +xseen.canvases.push(x_canvas); +t0 = new Date().getTime(); +/* +* Handle opening tag attributes +* divHeight +* divWidth +* turntable Indicates if view automatically rotates (independent of navigation) +*/ +var divWidth = x_element.getAttribute('width'); +var divHeight = x_element.getAttribute('height'); +if (divHeight + divWidth < 100) { +divHeight = 450; +divWidth = 800; +} else if (divHeight < 50) { +divHeight = Math.floor(divWidth/2) + 50; +} else if (divWidth < 50) { +divWidth = divHeight * 2 - 100; +} +var turntable = (x_element.getAttribute('turntable') || '').toLowerCase(); +if (turntable == 'on' || turntable == 'yes' || turntable == 'y' || turntable == '1') { +turntable = true; +} else { +turntable = false; +} +var x_camera = new THREE.PerspectiveCamera( 75, divWidth / divHeight, 0.1, 1000 ); +x_camera.position.x = 0; +x_camera.position.z = 10; +var x_renderer = new THREE.WebGLRenderer(); +x_renderer.setSize (divWidth, divHeight); +x_element.appendChild (x_renderer.domElement); +xseen.sceneInfo.push ({ +'size' : {'width':divWidth, 'height':divHeight}, +'scene' : x_canvas, +'renderer' : x_renderer, +'camera' : [x_camera], +'turntable' : turntable, +'mixers' : [], +'clock' : new THREE.Clock(), +'element' : x_element, +'stacks' : [], +'tmp' : {activeViewpoint:false}, +}); +x_element._xseen = {}; +x_element._xseen.children = []; +x_element._xseen.sceneInfo = xseen.sceneInfo[xseen.sceneInfo.length-1]; +t1 = new Date().getTime() - t0; +xseen.debug.logInfo("Time for setup and init of GL element no. " + i + ": " + t1 + " ms."); +} +var ready = (function(eventType) { +var evt = null; +if (document.createEvent) { +evt = document.createEvent("Events"); +evt.initEvent(eventType, true, true); +document.dispatchEvent(evt); +} else if (document.createEventObject) { +evt = document.createEventObject(); +document.body.fireEvent('on' + eventType, evt); +} +})('load'); +var t=[]; +for (var i=0; i root element that was added after document load. */ +xseen.reload = function() { +onload(); +}; +/* FIX PROBLEM IN CHROME - HACK - searching for better solution !!! */ +if (navigator.userAgent.indexOf("Chrome") != -1) { +document.__getElementsByTagName = document.getElementsByTagName; +document.getElementsByTagName = function(tag) { +var obj = []; +var elems = this.__getElementsByTagName("*"); +if(tag =="*"){ +obj = elems; +} else { +tag = tag.toUpperCase(); +for (var i = 0; i < elems.length; i++) { +var tagName = elems[i].tagName.toUpperCase(); +if (tagName === tag) { +obj.push(elems[i]); +} +} +} +return obj; +}; +document.__getElementById = document.getElementById; +document.getElementById = function(id) { +var obj = this.__getElementById(id); +if (!obj) { +var elems = this.__getElementsByTagName("*"); +for (var i=0; i xseen.debug.maxLinesToLog) { return; } +var node = document.createElement("p"); +node.style.margin = 0; +switch (logType) { +case xseen.debug.INFO: +node.style.color = "#009900"; +break; +case xseen.debug.WARNING: +node.style.color = "#cd853f"; +break; +case xseen.debug.ERROR: +node.style.color = "#ff4500"; +break; +case xseen.debug.EXCEPTION: +node.style.color = "#ffff00"; +break; +default: +node.style.color = "#009900"; +break; +} +try { +node.innerHTML = logType + ": " + msg; +xseen.debug.logContainer.insertBefore(node, xseen.debug.logContainer.firstChild); +} catch (err) { +if (window.console.firebug !== undefined) { +window.console.warn(msg); +} +} +if (xseen.debug.isFirebugAvailable) { +switch (logType) { +case xseen.debug.INFO: +window.console.info(msg); +break; +case xseen.debug.WARNING: +window.console.warn(msg); +break; +case xseen.debug.ERROR: +window.console.error(msg); +break; +case xseen.debug.EXCEPTION: +window.console.debug(msg); +break; +default: +break; +} +} +xseen.debug.numLinesLogged++; +}, +/** Log an info message. */ +logInfo: function(msg) { +xseen.debug.doLog(msg, xseen.debug.INFO); +}, +/** Log a warning message. */ +logWarning: function(msg) { +xseen.debug.doLog(msg, xseen.debug.WARNING); +}, +/** Log an error message. */ +logError: function(msg) { +xseen.debug.doLog(msg, xseen.debug.ERROR); +}, +/** Log an exception message. */ +logException: function(msg) { +xseen.debug.doLog(msg, xseen.debug.EXCEPTION); +}, +/** Log an assertion. */ +assert: function(c, msg) { +if (!c) { +xseen.debug.doLog("Assertion failed in " + xseen.debug.assert.caller.name + ': ' + msg, xseen.debug.ERROR); +} +}, +/** +Checks the type of a given object. +@param obj the object to check. +@returns one of; "boolean", "number", "string", "object", +"function", or "null". +*/ +typeOf: function (obj) { +var type = typeof obj; +return type === "object" && !obj ? "null" : type; +}, +/** +Checks if a property of a specified object has the given type. +@param obj the object to check. +@param name the property name. +@param type the property type (optional, default is "function"). +@returns true if the property exists and has the specified type, +otherwise false. +*/ +exists: function (obj, name, type) { +type = type || "function"; +return (obj ? this.typeOf(obj[name]) : "null") === type; +}, +/** +Dumps all members of the given object. +*/ +dumpFields: function (node) { +var str = ""; +for (var fName in node) { +str += (fName + ", "); +} +str += '\n'; +xseen.debug.logInfo(str); +return str; +} +}; +this.debug.setup(); +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +/* +* xseen.nodes. is the definition of +* All internal variables are stored in ._internal. All functions start with '_' +* +* This is a bare-bones setup. There is no error checking - missing arguments or +* methods that do not exist (e.g., .init) +* +* These are intended to be development support routines. It is anticipated that in +* production systems the array dump (_dumpTable) would be loaded. As a result, it is necessary +* to have a routine that dumps out the Object so it can be captured and saved. A routine +* or documentation on how to load the Object would also be good. +* +* Fields are added with the .addField method. It takes its values from the argument list +* or an object passed as the first argument. The properties of the argument are: +* name - the name of the field. This is converted to lowercase before use +* datatype - the datatype of the field. There must be a method in xseen.types by this name +* defaultValue - the default value of the field to be used if the field is not present or incorrectly defined. +* If this argument is an array, then it is the set of allowed values. The first element is the default. +* enumerated - the list of allowed values when the datatype only allows specific values for this field (optional) +* animatable - Flag (T/F) indicating if the field is animatable. Generally speaking, enumerated fieles are not animatable +*/ +xseen.nodes = { +'_defineNode' : function(nodeName, nodeComponent, nodeMethod) { +methodBase = 'xseen.node.'; +methodBase = ''; +node = { +'tag' : nodeName, +'taglc' : nodeName.toLowerCase(), +'component' : nodeComponent, +'method' : methodBase + nodeMethod, +'fields' : [], +'fieldIndex': [], +'addField' : function (fieldObj, datatype, defaultValue) { +var fieldName, namelc, enumerated, animatable; +if (typeof(fieldObj) === 'object') { +fieldName = fieldObj.name; +datatype = fieldObj.datatype; +defaultValue = fieldObj.defaultValue; +enumerated = (typeof(fieldObj.enumerated) === 'undefined') ? [] : fieldObj.enumerated; +animatable = (typeof(fieldObj.animatable) === 'undefined') ? false : fieldObj.animatable; +} else { +fieldName = fieldObj; +animatable = false; +if (typeof(defaultValue) == 'array') { +enumerated = defaultValue; +defaultValue = enumerated[0]; +} else { +enumerated = []; +} +} +namelc = fieldName.toLowerCase(); +this.fields.push ({ +'field' : fieldName, +'fieldlc' : namelc, +'type' : datatype, +'default' : defaultValue, +'enumeration' : enumerated, +'animatable' : animatable, +'clone' : this.cloneField, +'setFieldName' : this.setFieldName, +}); +this.fieldIndex[namelc] = this.fields.length-1; +return this; +}, +'addNode' : function () { +xseen.parseTable[this.taglc] = this; +}, +'cloneField' : function () { +var newFieldObject = { +'field' : this.field, +'fieldlc' : this.fieldlc, +'type' : this.type, +'default' : 0, +'enumeration' : [], +'animatable' : this.animatable, +'clone' : this.clone, +'setFieldName' : this.setFieldName, +}; +for (var i=0; i= 0) { +this._internals.activeNode = this._internals.stack[this._internals.active]; +} else { +this._internals.activeNode = this._internals.defaultNode; +} +} +this.init = function() { // Clears existing stack +this._internals.stack = []; +} +this.pushDown = function(node) { // Push new node onto stack and make active +this._internals.stack.push (node); +this._setActiveNode(); +} +this.popOff = function() { // Pop new node onto stack and make active +this._internals.stack.pop(); +this._setActiveNode(); +} +this.getActive = function() { +return this._internals.activeNode; +} +} +/* +* xseen.types contains the datatype and conversion utilities. These convert one format to another. +* Any method ending in 'toX' where 'X' is some datatype is a conversion to that type +* Other methods convert from string with space-spearated values +*/ +xseen.types = { +'Deg2Rad' : Math.PI / 180, +'SFFloat' : function (value, def) +{ +if (value === null) {return def;} +if (Number.isNaN(value)) {return def}; +return value; +}, +'SFInt' : function (value, def) +{ +if (value === null) {return def;} +if (Number.isNaN(value)) {return def}; +return Math.round(value); +}, +'SFBool' : function (value, def) +{ +if (value === null) {return def;} +if (value) {return true;} +if (!value) {return false;} +return def; +}, +'SFTime' : function (value, def) +{ +if (value === null) {return def;} +if (Number.isNaN(value)) {return def}; +return value; +}, +'SFVec3f' : function (value, def) +{ +if (value === null) {return def;} +var v3 = value.split(' '); +if (v3.length < 3 || Number.isNaN(v3[0]) || Number.isNaN(v3[1]) || Number.isNaN(v3[2])) { +return def; +} +return [v3[0]-0, v3[1]-0, v3[2]-0]; +}, +'SFVec2f' : function (value, def) +{ +if (value === null) {return def;} +var v2 = value.split(' '); +if (v2.length != 2 || Number.isNaN(v2[0]) || Number.isNaN(v2[1])) { +return def; +} +return [v2[0]-0, v2[1]-0]; +}, +'SFRotation' : function (value, def) +{ +if (value === null) {return def;} +var v4 = value.split(' '); +if (v4.length != 4 || Number.isNaN(v4[0]) || Number.isNaN(v4[1]) || Number.isNaN(v4[2]) || Number.isNaN(v4[3])) { +return def; +} +var result = { +'vector' : [v4[0], v4[1], v4[2], v4[3]], +'axis_angle' : [{'x': v4[0], 'y': v4[1], 'z': v4[2]}, v4[3]], +}; +return result; +}, +'SFColor' : function (value, defaultString) +{ +var v3 = this.SFVec3f(value, defaultString); +v3[0] = Math.min(Math.max(v3[0], 0.0), 1.0); +v3[1] = Math.min(Math.max(v3[1], 0.0), 1.0); +v3[2] = Math.min(Math.max(v3[2], 0.0), 1.0); +return v3; +}, +'SFString' : function (value, def) +{ +if (value === null) {value = def;} +return value; +}, +'MFFloat' : function (value, def) +{ +var defReturn = (def == '') ? [] : def; +if (value === null) {return defReturn;} +var mi = value.split(' '); +var rv = []; +for (var i=0; iDocumentation."]; +var version = { +major : Major, +minor : Minor, +patch : Patch, +preRelease : PreRelease, +release : Release, +version : '', +date : Date, +splashText : SplashText +}; +version.version = version.major + '.' + version.minor + '.' + version.patch; +version.version += (version.preRelease != '') ? '-' + version.preRelease : ''; +version.version += (version.release != '') ? '+' + version.release : ''; +return version; +} +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +xseen.node.core_NOOP = { +'init' : function (e,p) {}, +'fin' : function (e,p) {} +}; +xseen.node.parsing = function (s, e) { +xseen.debug.logInfo ('Parsing init details stub for ' + s); +} +xseen.node.af_Entity = { +'init' : function (e,p) +{ +xseen.node.parsing('A-Frame Entity'); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Assets = { +'init' : function (e,p) {}, +'fin' : function (e,p) {} +}; +xseen.node.af_AssetItem = { +'init' : function (e,p) // Only field is SRC. +{ +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Mixin = { +'init' : function (e,p) // Lots of fields -- all nebelous until used +{ +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Appearance = function (e) { +var parameters = { +'aoMap' : e._xseen.fields['ambient-occlusion-map'], +'aoMapIntensity' : e._xseen.fields['ambient-occlusion-map-intensity'], +'color' : e._xseen.fields['color'], +'displacementMap' : e._xseen.fields['displacement-map'], +'displacementScale' : e._xseen.fields['displacement-scale'], +'displacementBias' : e._xseen.fields['displacement-bias'], +'envMap' : e._xseen.fields['env-map'], +'normalMap' : e._xseen.fields['normal-map'], +'normalScale' : e._xseen.fields['normal-scale'], +'wireframe' : e._xseen.fields['wireframe'], +'wireframeLinewidth' : e._xseen.fields['wireframe-linewidth'], +}; +var material = new THREE.MeshPhongMaterial(parameters); +return material; +/* +* === All Entries === +.aoMap +.aoMapIntensity +.color +.combine +.displacementMap +.displacementScale +.displacementBias +.emissive +.emissiveMap +.emissiveIntensity +.envMap +.lightMap +.lightMapIntensity +.map +.morphNormals +.morphTargets +.normalMap +.normalScale +.reflectivity +.refractionRatio +.shininess +.skinning +.specular +.specularMap +.wireframe +.wireframeLinecap +.wireframeLinejoin +.wireframeLinewidth +e._xseen.fields['ambient-occlusion-map'] +e._xseen.fields['ambient-occlusion-map-intensity'] +e._xseen.fields['ambient-occlusion-texture-offset'] +e._xseen.fields['ambient-occlusion-texture-repeat'] +e._xseen.fields['color'] +e._xseen.fields['displacement-bias'] +e._xseen.fields['displacement-map'] +e._xseen.fields['displacement-scale'] +e._xseen.fields['displacement-texture-offset'] +e._xseen.fields['displacement-texture-repeat'] +e._xseen.fields['env-map'] +e._xseen.fields['fog'] +e._xseen.fields['metalness'] +e._xseen.fields['normal-map'] +e._xseen.fields['normal-scale'] +e._xseen.fields['normal-texture-offset'] +e._xseen.fields['normal-texture-repeat'] +e._xseen.fields['repeat'] +e._xseen.fields['roughness'] +e._xseen.fields['spherical-env-map'] +e._xseen.fields['src'] +e._xseen.fields['wireframe'] +e._xseen.fields['wireframe-linewidth'] +* === Unused Entries === +.combine +.emissive +.emissiveMap +.emissiveIntensity +.lightMap +.lightMapIntensity +.map +.morphNormals +.morphTargets +.reflectivity +.refractionRatio +.shininess +.skinning +.specular +.specularMap +.wireframeLinecap +.wireframeLinejoin +e._xseen.fields['ambient-occlusion-texture-offset'] +e._xseen.fields['ambient-occlusion-texture-repeat'] +e._xseen.fields['displacement-texture-offset'] +e._xseen.fields['displacement-texture-repeat'] +e._xseen.fields['fog'] +e._xseen.fields['metalness'] +e._xseen.fields['normal-texture-offset'] +e._xseen.fields['normal-texture-repeat'] +e._xseen.fields['repeat'] +e._xseen.fields['roughness'] +e._xseen.fields['spherical-env-map'] +e._xseen.fields['src'] +*/ +} +xseen.node.af_Box = { +'init' : function (e,p) +{ +var geometry = new THREE.BoxGeometry( +e._xseen.fields.width, +e._xseen.fields.height, +e._xseen.fields.depth, +e._xseen.fields['segments-width'], +e._xseen.fields['segments-height'], +e._xseen.fields['segments-depth'] +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Cone = { +'init' : function (e,p) +{ +var geometry = new THREE.ConeGeometry( +e._xseen.fields.radius, +e._xseen.fields.height, +e._xseen.fields['segments-radial'], +e._xseen.fields['segments-height'], +e._xseen.fields['open-ended'], +e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, +e._xseen.fields['theta-length'] * xseen.types.Deg2Rad +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Cylinder = { +'init' : function (e,p) +{ +var geometry = new THREE.CylinderGeometry( +e._xseen.fields['radius-top'], +e._xseen.fields['radius-bottom'], +e._xseen.fields.height, +e._xseen.fields['segments-radial'], +e._xseen.fields['segments-height'], +e._xseen.fields['open-ended'], +e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, +e._xseen.fields['theta-length'] * xseen.types.Deg2Rad +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Dodecahedron = { +'init' : function (e,p) +{ +var geometry = new THREE.DodecahedronGeometry( +e._xseen.fields.radius, +e._xseen.fields.detail +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Icosahedron = { +'init' : function (e,p) +{ +var geometry = new THREE.IcosahedronGeometry( +e._xseen.fields.radius, +e._xseen.fields.detail +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Octahedron = { +'init' : function (e,p) +{ +var geometry = new THREE.OctahedronGeometry( +e._xseen.fields.radius, +e._xseen.fields.detail +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Sphere = { +'init' : function (e,p) +{ +var geometry = new THREE.SphereGeometry( +e._xseen.fields.radius, +e._xseen.fields['segments-width'], +e._xseen.fields['segments-height'], +e._xseen.fields['phi-start'] * xseen.types.Deg2Rad, +e._xseen.fields['phi-length'] * xseen.types.Deg2Rad, +e._xseen.fields['theta-start'] * xseen.types.Deg2Rad, +e._xseen.fields['theta-length'] * xseen.types.Deg2Rad +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Tetrahedron = { +'init' : function (e,p) +{ +var geometry = new THREE.TetrahedronGeometry( +e._xseen.fields.radius, +e._xseen.fields.detail +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +xseen.node.af_Torus = { +'init' : function (e,p) +{ +var geometry = new THREE.TorusGeometry( +e._xseen.fields.radius, +e._xseen.fields.tube, +e._xseen.fields['segments-radial'], +e._xseen.fields['segments-tubular'], +e._xseen.fields.arc * xseen.types.Deg2Rad +); +var appearance = xseen.node.af_Appearance (e); +var mesh = new THREE.Mesh (geometry, appearance); +var group = new THREE.Group(); +group.add (mesh); +if (typeof(p._xseen.children) == 'undefined') {p._xseen.children = [];} +p._xseen.children.push(group); +}, +'fin' : function (e,p) {} +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +xseen.node.appearance_Material = { +'init' : function (e,p) +{ +var transparency = e._xseen.fields.transparency - 0; +var shininess = e._xseen.fields.shininess - 0; +var colorDiffuse = xseen.types.Color3toInt (e._xseen.fields.diffusecolor); +var colorEmissive = xseen.types.Color3toInt (e._xseen.fields.emissivecolor); +var colorSpecular = xseen.types.Color3toInt (e._xseen.fields.specularcolor); +p._xseen.material = new THREE.MeshPhongMaterial( { +'color' : colorDiffuse, +'emissive' : colorEmissive, +'specular' : colorSpecular, +'shininess' : shininess, +'opacity' : 1.0-transparency, +'transparent' : (transparency > 0.0) ? true : false +} ); +e._xseen.animate['diffusecolor'] = p._xseen.material.color; +e._xseen.animate['emissivecolor'] = p._xseen.material.emissive; +e._xseen.animate['specularcolor'] = p._xseen.material.specular; +e._xseen.animate['transparency'] = p._xseen.material.opacity; +e._xseen.animate['shininess'] = p._xseen.material.shininess; +}, +'fin' : function (e,p) {} +}; +xseen.node.appearance_ImageTexture = { +'init' : function (e,p) +{ +p._xseen.texture = xseen.loader.ImageLoader.load(e._xseen.fields.url); +p._xseen.texture.wrapS = (e._xseen.fields.repeats) ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; +p._xseen.texture.wrapT = (e._xseen.fields.repeatt) ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping; +}, +'fin' : function (e,p) {} +}; +xseen.node.appearance_Appearance = { +'init' : function (e,p) {}, +'fin' : function (e,p) +{ +if (typeof(e._xseen.texture) !== 'undefined' && e._xseen.texture !== null) { +e._xseen.material.map = e._xseen.texture; +} +p._xseen.appearance = e._xseen.material; +} +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +xseen.node.geometry_Coordinate = { +'init' : function (e,p) +{ +var vertices = []; +for (var i=0; i= 0 where each triple defines a triangle face. It is assumed that the +* indices define the face in counter-clockwise order when looking at the face. +* vertices - an array of THREE.Vector3 points +*/ +xseen.node.geometry__Indexed3 = function (indices, vertices, normals=[], color=[]) { +var i, face, normal=[], faceCount=0, n; +var useNormals = (normals.length > 0) ? true : false; +var useColor = (color.length > 0) ? true : false; +var maxIndex = Math.max.apply(null, indices); +var minIndex = Math.min.apply(null, indices); +if (maxIndex >= vertices.length) { +console.log ('Maximum index ('+maxIndex+') exceeds vertex count ('+vertices.length+'). No geometry is created'); +return; +} +if (useNormals && maxIndex >= normals.length) { +console.log ('Maximum index ('+maxIndex+') exceeds normal count ('+normals.length+'). No geometry is created'); +return; +} +if (useColor && maxIndex >= color.length) { +console.log ('Maximum index ('+maxIndex+') exceeds color count ('+color.length+'). No geometry is created'); +return; +} +if (minIndex < 0) { +console.log ('Minimum index ('+minIndex+') less than zero. No geometry is created'); +return; +} +if (indices.length % 3 != 0) { +console.log ('Number of indices ('+indices.length+') not divisible by 3. No geometry is created'); +return; +} +var geometry = new THREE.Geometry(); +var normal_pz = new THREE.Vector3 (0, 0, 1); +var normal_mz = new THREE.Vector3 (0, 0, -1); +for (var i=0; i 0) {clip.duration = e._xseen.fields.duration;} +e._xseen.mixer.clipAction( clip ).play(); +} ); +} else { // Play a specific animation +var clip = THREE.AnimationClip.findByName(response.animations, e._xseen.fields.playonload); +var action = e._xseen.mixer.clipAction (clip); +action.play(); +} +} +} +} +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +xseen.node.core_NOOP = { +'init' : function (e,p) {}, +'fin' : function (e,p) {} +}; +xseen.node.core_WorldInfo = { +'init' : function (e,p) {parsing('WorldInfo', e)}, +'fin' : function (e,p) {} +}; +function parsing (s, e) { +xseen.debug.logInfo ('Parsing init details stub for ' + s); +} +xseen.node.unk_Viewpoint = { +'init' : function (e,p) +{ // This should really go in a separate push-down list for Viewpoints +e._xseen.fields._radius0 = Math.sqrt( e._xseen.fields.position[0]*e._xseen.fields.position[0] + +e._xseen.fields.position[1]*e._xseen.fields.position[1] + +e._xseen.fields.position[2]*e._xseen.fields.position[2]); +if (!e._xseen.sceneInfo.tmp.activeViewpoint) { +e._xseen.sceneInfo.stacks.Viewpoints.pushDown(e); +e._xseen.sceneInfo.tmp.activeViewpoint = true; +} +}, +'fin' : function (e,p) {} +}; +xseen.node.unk_Shape = { +'init' : function (e,p) {}, +'fin' : function (e,p) +{ +if (typeof(e._xseen.materialProperty) !== 'undefined') { +e._xseen.appearance.vertexColors = THREE.VertexColors; +e._xseen.appearance._needsUpdate = true; +e._xseen.appearance.needsUpdate = true; +} +var m = new THREE.Mesh (e._xseen.geometry, e._xseen.appearance); +p._xseen.children.push(m); +m = null; +} +}; +xseen.node.grouping_Transform = { +'init' : function (e,p) +{ +var group = new THREE.Group(); +if (e.nodeName == "TRANSFORM") { +var rotation = xseen.types.Rotation2Quat(e._xseen.fields.rotation); +group.name = 'Transform children [' + e.id + ']'; +group.position.x = e._xseen.fields.translation[0]; +group.position.y = e._xseen.fields.translation[1]; +group.position.z = e._xseen.fields.translation[2]; +group.scale.x = e._xseen.fields.scale[0]; +group.scale.y = e._xseen.fields.scale[1]; +group.scale.z = e._xseen.fields.scale[2]; +group.quaternion.x = rotation.x; +group.quaternion.y = rotation.y; +group.quaternion.z = rotation.z; +group.quaternion.w = rotation.w; +e._xseen.animate['translation'] = group.position; +e._xseen.animate['rotation'] = group.quaternion; +e._xseen.animate['scale'] = group.scale; +} +e._xseen.sceneNode = group; +}, +'fin' : function (e,p) +{ +e._xseen.children.forEach (function (child, ndx, wholeThing) +{ +e._xseen.sceneNode.add(child); +}); +p._xseen.children.push(e._xseen.sceneNode); +} +}; +xseen.node.lighting_Light = { +'init' : function (e,p) +{ +var color = xseen.types.Color3toInt (e._xseen.fields.color); +var intensity = e._xseen.fields.intensity - 0; +var lamp, type=e._xseen.fields.type.toLowerCase(); +/* +if (typeof(p._xseen.children) == 'undefined') { +console.log('Parent of Light does not have children...'); +p._xseen.children = []; +} +*/ +if (type == 'point') { +lamp = new THREE.PointLight (color, intensity); +lamp.distance = Math.max(0.0, e._xseen.fields.radius - 0); +lamp.decay = Math.max (.1, e._xseen.fields.attenuation[1]/2 + e._xseen.fields.attenuation[2]); +} else if (type == 'spot') { +lamp = new THREE.SpotLight (color, intensity); +lamp.position.set(0-e._xseen.fields.direction[0], 0-e._xseen.fields.direction[1], 0-e._xseen.fields.direction[2]); +lamp.distance = Math.max(0.0, e._xseen.fields.radius - 0); +lamp.decay = Math.max (.1, e._xseen.fields.attenuation[1]/2 + e._xseen.fields.attenuation[2]); +lamp.angle = Math.max(0.0, Math.min(1.5707963267948966192313216916398, e._xseen.fields.cutoffangle)); +lamp.penumbra = 1 - Math.max(0.0, Math.min(lamp.angle, e._xseen.fields.beamwidth)) / lamp.angle; +} else { // DirectionalLight (by default) +lamp = new THREE.DirectionalLight (color, intensity); +lamp.position.x = 0-e._xseen.fields.direction[0]; +lamp.position.y = 0-e._xseen.fields.direction[1]; +lamp.position.z = 0-e._xseen.fields.direction[2]; +} +p._xseen.children.push(lamp); +lamp = null; +} +, +'fin' : function (e,p) +{ +} +}; +xseen.node.networking_Inline = { +'init' : function (e,p) +{ +if (typeof(e._xseen.processedUrl) === 'undefined' || !e._xseen.requestedUrl) { +var uri = xseen.parseUrl (e._xseen.fields.url); +var type = uri.extension; +e._xseen.loadGroup = new THREE.Group(); +e._xseen.loadGroup.name = 'Inline content [' + e.id + ']'; +console.log ('Created Inline Group with UUID ' + e._xseen.loadGroup.uuid); +var userdata = {'requestType':'x3d', 'e':e, 'p':p} +if (type.toLowerCase() == 'json') { +userdata.requestType = 'json'; +xseen.loadMgr.loadJson (e._xseen.fields.url, this.loadSuccess, xseen.loadProgress, xseen.loadError, userdata); +} else { +xseen.loadMgr.loadXml (e._xseen.fields.url, this.loadSuccess, xseen.loadProgress, xseen.loadError, userdata); +} +e._xseen.requestedUrl = true; +} +p._xseen.children.push(e._xseen.loadGroup); +console.log ('Using Inline Group with UUID ' + e._xseen.loadGroup.uuid); +}, +'fin' : function (e,p) +{ +}, +'loadSuccess' : +function (response, userdata, xhr) { +userdata.e._xseen.processedUrl = true; +userdata.e._xseen.loadResponse = response; +console.log("download successful for "+userdata.e.id); +if (userdata.requestType == 'json') { +var tmp = {'scene': response}; +response = null; +response = (new JSONParser()).parseJavaScript(tmp); +} +var start = {'_xseen':0}; +var findSceneTag = function (fragment) { +if (typeof(fragment._xseen) === 'undefined') {fragment._xseen = {'childCount': -1};} +if (fragment.nodeName.toLowerCase() == 'scene') { +start = fragment; +return; +} else if (fragment.children.length > 0) { +for (fragment._xseen.childCount=0; fragment._xseen.childCount 0) { +userdata.e.appendChild(start.children[0]); +} +xseen.Parse(userdata.e, userdata.p, userdata.p._xseen.sceneInfo); +userdata.e._xseen.children.forEach (function (child, ndx, wholeThing) +{ +userdata.e._xseen.loadGroup.add(child); +console.log ('...Adding ' + child.type + ' (' + child.name + ') to Inline Group? with UUID ' + userdata.e._xseen.loadGroup.uuid + ' (' + userdata.e._xseen.loadGroup.name + ')'); +}); +userdata.p._xseen.sceneInfo.scene.updateMatrixWorld(); +} else { +console.log("Found illegal X3D file -- no 'scene' tag"); +} +} +}; +xseen.node.core_Scene = { +'init' : function (e,p) +{ +var width = e._xseen.sceneInfo.size.width; +var height = e._xseen.sceneInfo.size.height; +e._xseen.renderer = { +'canvas' : e._xseen.sceneInfo.scene, +'width' : width, +'height' : height, +'camera' : e._xseen.sceneInfo.camera[0], +'renderer' : e._xseen.sceneInfo.renderer, +}; +e._xseen.renderer.renderer.setSize (width, height); +var camera = new THREE.PerspectiveCamera( 75, width / height, 0.1, 1000 ); +camera.position.x = 0; // hardwired for now... +camera.position.y = 0; +camera.position.z = 4; +e._xseen.renderer.camera = camera; +}, +/* +* This appears now to be working!!! +* +* Late loading content is not getting inserted into the scene graph for rendering. Need to read +* THREE docs about how to do that. +* Camera will need to be redone. Existing camera is treated as a special child. A separate camera +* should be established and Viewpoint nodes define "photostops" rather than a camera. The camera is +* in effect, parented to the "photostop". This probably needs to list of Viewpoints discussed in the +* X3D specification. +*/ +'fin' : function (e,p) +{ +e._xseen.children.forEach (function (child, ndx, wholeThing) +{ +console.log('Adding child of type ' + child.type + ' (' + child.name + ')'); +e._xseen.renderer.canvas.add(child); +}); +xseen.dumpSceneGraph (); +e._xseen.renderer.renderer.render( e._xseen.renderer.canvas, e._xseen.renderer.camera ); +xseen.debug.logInfo("Rendered all elements -- Starting animation"); +var vp = xseen.sceneInfo[0].stacks.Viewpoints.getActive(); +var currentCamera = xseen.sceneInfo[0].element._xseen.renderer.camera; +currentCamera.position.x = vp._xseen.fields.position[0]; +currentCamera.position.y = vp._xseen.fields.position[1]; +currentCamera.position.z = vp._xseen.fields.position[2]; +xseen.render(); +} +}; +xseen.node.env_Background = { +'init' : function (e,p) +{ +var color = new THREE.Color(e._xseen.fields.skycolor[0], e._xseen.fields.skycolor[1], e._xseen.fields.skycolor[2]); +var textureCube = new THREE.CubeTextureLoader() +.load ([e._xseen.fields.srcright, +e._xseen.fields.srcleft, +e._xseen.fields.srctop, +e._xseen.fields.srcbottom, +e._xseen.fields.srcfront, +e._xseen.fields.srcback], +this.loadSuccess({'e':e, 'p':p}) +); +e._xseen.sceneInfo.scene.background = color; +/* +var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube } ); +var size = 1; +var geometry = new THREE.Geometry(); +geometry.vertices.push ( +new THREE.Vector3(-size, -size, size), +new THREE.Vector3( size, -size, size), +new THREE.Vector3( size, -size, -size), +new THREE.Vector3(-size, -size, -size), +new THREE.Vector3(-size, size, size), +new THREE.Vector3( size, size, size), +new THREE.Vector3( size, size, -size), +new THREE.Vector3(-size, size, -size) +); +geometry.faces.push ( // external facing geometry +new THREE.Face3(0, 1, 5), +new THREE.Face3(0, 5, 4), +new THREE.Face3(1, 2, 6), +new THREE.Face3(1, 6, 5), +new THREE.Face3(2, 3, 7), +new THREE.Face3(2, 7, 6), +new THREE.Face3(3, 0, 4), +new THREE.Face3(3, 4, 7), +new THREE.Face3(4, 5, 6), +new THREE.Face3(4, 6, 7), +new THREE.Face3(0, 2, 1), +new THREE.Face3(0, 3, 2), +); +geometry.computeBoundingSphere(); +var mesh = new THREE.Mesh (geometry, material); +e._xseen.sceneInfo.element._xseen.renderer.canvas.add(mesh); +*/ +}, +'fin' : function (e,p) +{ +p._xseen.appearance = e._xseen.material; +}, +'loadSuccess' : function (userdata) +{ +var e = userdata.e; +var p = userdata.p; +return function (textureCube) +{ +e._xseen.processedUrl = true; +e._xseen.loadTexture = textureCube; +e._xseen.sceneInfo.scene.background = textureCube; +} +}, +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +xseen.node.x_Animate = { +'init' : function (e,p) +{ +var delay = e._xseen.fields.delay * 1000; // Convert to milliseconds +var duration = e._xseen.fields.duration * 1000; // Convert to milliseconds +var repeat = (e._xseen.fields.repeat < 0) ? Infinity : e._xseen.fields.repeat; +var interpolator = e._xseen.fields.interpolator; +var easing = e._xseen.fields.easing; +var fields = xseen.parseTable[p.localName.toLowerCase()].fields; +var fieldIndex = xseen.parseTable[p.localName.toLowerCase()].fieldIndex; +var toField = e._xseen.fields.field; +var toFieldIndex = fieldIndex[toField]; +if (typeof(fields[toFieldIndex]) === 'undefined') { +xseen.debug.logInfo("Field '" + toField + "' not found in parent (" + p.localName.toLowerCase() + "). No animation performed."); +return; +} +var fieldObject = fields[toFieldIndex].clone().setFieldName('to'); // Parse table entry for 'toField' +var to = xseen.nodes._parseField(fieldObject, e); // Parsed data -- need to convert to THREE format +var interpolation; +if (fieldObject.type == 'SFVec3f') { +interpolation = TWEEN.Interpolation.Linear; +to = xseen.types.Vector3(to); +xseen.debug.logInfo("Interpolating field '" + toField + "' as 3-space."); +} else if (fieldObject.type == 'SFColor') { +interpolation = this.Interpolator.color; +to = new THREE.Color (xseen.types.Color3toInt(to)); +xseen.debug.logInfo("Interpolation field '" + toField + "' as color."); +} else if (fieldObject.type == 'SFRotation') { +interpolation = this.Interpolator.slerp; +to = xseen.types.Rotation2Quat(to); +xseen.debug.logInfo("Interpolation field '" + toField + "' as rotation."); +} else { +xseen.debug.logInfo("Field '" + toField + "' not converted to THREE format. No animation performed."); +return; +} +var fieldTHREE = p._xseen.animate[toField]; // THREE field for animation +var tween = new TWEEN.Tween(fieldTHREE) +.to(to, duration) +.delay(delay) +.repeat(repeat) +.interpolation(interpolation); +var easingType = e._xseen.fields.easingtype; +easingType = easingType.charAt(0).toUpperCase() + easingType.slice(1); +easing = (easingType != 'Linear' && easing == '') ? 'inout' : easing; +if (easing != '') { +easing = easing.replace('in', 'In').replace('out', 'Out'); +easingType = (easingType == 'Linear') ? 'Quadratic' : easingType; +e._xseen.fields.easing = easing; +e._xseen.fields.easingtype = easingType; +tween.easing(TWEEN.Easing[easingType][easing]); +} +tween.start(); +e._xseen.animating = tween; +p._xseen.animation.push (tween); +}, +'fin' : function (e,p) {}, +/* +* Various interpolator functions for use with different data types +* All are designed to be used within TWEEN and take two arguments +* v A vector of way points (key values) that define the interpolated path +* k The interpolating factor that defines how far along the path for the current result +* +* Functions +* slerp - Linear in quaterian space (though not yet) +* color - Linear in color space (currently HSL as used by THREE) +* +*/ +'Interpolator' : { +'slerp' : function (v,k) +{ +var m = v.length - 1; +var f = m * k; +var i = Math.floor(f); +if (k < 0) { +return v[0].slerp(v[1], f); +} +if (k > 1) { +return v[m].slerp(v[m-1], m-f); +} +return v[i].slerp (v[i + 1 > m ? m : i + 1], f-i); +}, +'color' : function (v,k) +{ +var m = v.length - 1; +var f = m * k; +var i = Math.floor(f); +var fn = this.slerpCompute; +if (k < 0) { +return v[0].lerp(v[1], f); +} +if (k > 1) { +return v[m].lerp(v[m-1], m-f); +} +return v[i].lerp (v[i + 1 > m ? m : i + 1], f - i); +}, +}, +/* +Probably need to store the animation someplace. Also need to start worrying +about methods to call when animating, at least start/stop since the target is +identified by 'id'. Need to put the method references into the DOM node +There is also other unresolved references, +* capturing the 'to' data +* handling differening interpolation methods (rotation, color space, discrete) +* handling array of 'to' values (probably a child node) +* handling array of key values +* investigate other easing types (besides Quadratic) +*/ +}; +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +/* +* These are intended to be development support routines. It is anticipated that in +* production systems the array dump would be loaded. As a result, it is necessary +* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine +* or documentation on how to load the Object would also be good. +* +*/ +xseen._addAframeAppearance = function (node) { +node +.addField('ambient-occlusion-map', 'SFString', '') +.addField('ambient-occlusion-map-intensity', 'SFFloat', 1) +.addField('ambient-occlusion-texture-offset', 'SFVec2f', '0 0') +.addField('ambient-occlusion-texture-repeat', 'SFVec2f', '1 1') +.addField('color', 'Color', '#FFF') +.addField('displacement-bias', 'SFFloat', 0.5) +.addField('displacement-map', 'SFString', '') +.addField('displacement-scale', 'SFFloat', 1) +.addField('displacement-texture-offset', 'SFVec2f', '0 0') +.addField('displacement-texture-repeat', 'SFVec2f', '1 1') +.addField('env-map', 'SFString', '') +.addField('fog', 'SFBool', true) +.addField('metalness', 'SFFloat', 0) +.addField('normal-map', 'SFString', '') +.addField('normal-scale', 'SFVec2f', '1 1') +.addField('normal-texture-offset', 'SFVec2f', '0 0') +.addField('normal-texture-repeat', 'SFVec2f', '1 1') +.addField('repeat', 'SFVec2f', '1 1') +.addField('roughness', 'SFFloat', 0.5) +.addField('spherical-env-map', 'SFString', '') +.addField('src', 'SFString', '') +.addField('wireframe', 'SFBool', false) +.addField('wireframe-linewidth', 'SFInt', 2) +.addNode(); +} +xseen.nodes._defineNode('a-entity', 'A-Frame', 'af_Entity') +.addField('geometry', 'SFString', '') +.addField('material', 'SFString', '') +.addField('light', 'SFString', '') +.addNode(); +var node; +node = xseen.nodes._defineNode('a-box', 'A-Frame', 'af_Box') +.addField('depth', 'SFFloat', 1) +.addField('height', 'SFFloat', 1) +.addField('width', 'SFFloat', 512) +.addField('segments-depth', 'SFInt', 1) +.addField('segments-height', 'SFInt', 1) +.addField('segments-width', 'SFInt', 1); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-cone', 'A-Frame', 'af_Cone') +.addField('height', 'SFFloat', 1) +.addField('radius', 'SFFloat', 1) +.addField('open-ended', 'SFBool', false) +.addField('theta-start', 'SFFloat', 0) +.addField('theta-length', 'SFFloat', 360) +.addField('segments-height', 'SFInt', 1) +.addField('segments-radial', 'SFInt', 8); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-cylinder', 'A-Frame', 'af_Cylinder') +.addField('height', 'SFFloat', 1) +.addField('open-ended', 'SFBool', false) +.addField('radius-bottom', 'SFFloat', 1) +.addField('radius-top', 'SFFloat', 1) +.addField('theta-start', 'SFFloat', 0) +.addField('theta-length', 'SFFloat', 360) +.addField('segments-height', 'SFInt', 1) +.addField('segments-radial', 'SFInt', 8); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-dodecahedron', 'A-Frame', 'af_Dodecahedron') +.addField('radius', 'SFFloat', 1) +.addField('detail', 'SFFloat', 0); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-icosahedron', 'A-Frame', 'af_Icosahedron') +.addField('radius', 'SFFloat', 1) +.addField('detail', 'SFFloat', 0); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-octahedron', 'A-Frame', 'af_Octahedron') +.addField('radius', 'SFFloat', 1) +.addField('detail', 'SFFloat', 0); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-sphere', 'A-Frame', 'af_Sphere') +.addField('radius', 'SFFloat', 1) +.addField('theta-start', 'SFFloat', 0) +.addField('theta-length', 'SFFloat', 180) +.addField('phi-start', 'SFFloat', 0) +.addField('phi-length', 'SFFloat', 360) +.addField('segments-height', 'SFInt', 18) +.addField('segments-width', 'SFInt', 36); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-tetrahedron', 'A-Frame', 'af_Tetrahedron') +.addField('radius', 'SFFloat', 1) +.addField('detail', 'SFFloat', 0); +xseen._addAframeAppearance (node); +node = xseen.nodes._defineNode('a-torus', 'A-Frame', 'af_Torus') +.addField('radius', 'SFFloat', 2) +.addField('tube', 'SFFloat', 1) +.addField('arc', 'SFFloat', 360) +.addField('segments-radial', 'SFInt', 8) +.addField('segments-tubular', 'SFInt', 6); +xseen._addAframeAppearance (node); +/* +* Asset management system nodes +*/ +xseen.nodes._defineNode('a-assets', 'A-Frame', 'af_Assets') +.addNode(); +xseen.nodes._defineNode('a-asset-item', 'A-Frame', 'af_AssetItem') +.addField('src', 'SFString', '') +.addNode(); +xseen.nodes._defineNode('a-mixin', 'A-Frame', 'af_Mixin') +.addField('*', 'SFString', '') +.addNode(); +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +/* +* These are intended to be development support routines. It is anticipated that in +* production systems the array dump would be loaded. As a result, it is necessary +* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine +* or documentation on how to load the Object would also be good. +* +*/ +xseen.nodes._defineNode('Cone', 'Geometry3D', 'geometry3D_Cone') +.addField('bottomRadius', 'SFFloat', 1) +.addField('height', 'SFFloat', 2) +.addField('bottom', 'SFBool', true) +.addField('side', 'SFBool', true) +.addNode(); +xseen.nodes._defineNode('Box', 'Geometry3D', 'geometry3D_Box') +.addField('size', 'SFVec3f', [1,1,1]) +.addNode(); +xseen.nodes._defineNode('Sphere', 'Geometry3D', 'geometry3D_Sphere') +.addField('radius', 'SFFloat', '1') +.addNode(); +xseen.nodes._defineNode('Cylinder', 'Geometry3D', 'geometry3D_Cylinder') +.addField('radius', 'SFFloat', 1) +.addField('height', 'SFFloat', 2) +.addField('bottom', 'SFBool', true) +.addField('side', 'SFBool', true) +.addField('top', 'SFBool', true) +.addNode(); +xseen.nodes._defineNode ('Material', 'Appearance', 'appearance_Material') +.addField({name:'diffuseColor', datatype:'SFColor', defaultValue:[.8,.8,.8], animatable:true}) +.addField({name:'emissiveColor',datatype: 'SFColor', defaultValue:[0,0,0], animatable:true}) +.addField({name:'specularColor', datatype:'SFColor', defaultValue:[0,0,0], animatable:true}) +.addField({name:'transparency', datatype:'SFFloat', defaultValue:'0', animatable:true}) +.addField({name:'shininess', datatype:'SFFloat', defaultValue:'0', animatable:true}) +.addNode(); +xseen.nodes._defineNode ('Transform', 'Grouping', 'grouping_Transform') +.addField({name:'translation', datatype:'SFVec3f', defaultValue:[0,0,0], animatable:true}) +.addField({name:'scale', datatype:'SFVec3f', defaultValue:[1,1,1], animatable:true}) +.addField({name:'rotation', datatype:'SFRotation', defaultValue:xseen.types.SFRotation('0 1 0 0',''), animatable:true}) +.addNode(); +xseen.nodes._defineNode ('Group', 'Grouping', 'grouping_Transform') +.addNode(); +xseen.nodes._defineNode ('Light', 'Lighting', 'lighting_Light') +.addField('direction', 'SFVec3f', [0,0,-1]) // DirectionalLight +.addField('location', 'SFVec3f', [0,0,0]) // PointLight & SpotLight +.addField('radius', 'SFFloat', '100') // PointLight & SpotLight +.addField('attenuation', 'SFVec3f', [1,0,0]) // PointLight & SpotLight +.addField('beamWidth', 'SFFloat', '0.78539816339744830961566084581988') // SpotLight +.addField('cutOffAngle', 'SFFloat', '1.5707963267948966192313216916398') // SpotLight +.addField('color', 'SFColor', [1,1,1]) // General +.addField('intensity', 'SFFloat', '1') // General +.addField({name:'type', datatype:'EnumerateString', defaultValue:'Directional', enumerated:['Directional', 'Spot', 'Point'], animatable:true}) +.addNode(); +xseen.nodes._defineNode ('DirectionalLight', 'Lighting', 'lighting_Light') +.addField('direction', 'SFVec3f', [0,0,-1]) +.addField('color', 'SFColor', [1,1,1]) +.addField('intensity', 'SFFloat', '1') +.addField('type', 'SFString', 'Directional') +.addNode(); +xseen.nodes._defineNode ('PointLight', 'Lighting', 'lighting_Light') +.addField('location', 'SFVec3f', [0,0,0]) +.addField('radius', 'SFFloat', '100') +.addField('attenuation', 'SFVec3f', [1,0,0]) +.addField('color', 'SFColor', [1,1,1]) +.addField('intensity', 'SFFloat', '1') +.addField('type', 'SFString', 'Point') +.addNode(); +xseen.nodes._defineNode ('SpotLight', 'Lighting', 'lighting_Light') +.addField('direction', 'SFVec3f', [0,0,-1]) +.addField('radius', 'SFFloat', '100') +.addField('attenuation', 'SFVec3f', [1,0,0]) +.addField('beamWidth', 'SFFloat', '0.78539816339744830961566084581988') // pi/4 +.addField('cutOffAngle', 'SFFloat', '1.5707963267948966192313216916398') // pi/2 +.addField('color', 'SFColor', [1,1,1]) +.addField('intensity', 'SFFloat', '1') +.addField('type', 'SFString', 'Spot') +.addNode(); +xseen.nodes._defineNode ('Camera', 'Unknown', 'unk_Viewpoint') +.addField('position', 'SFVec3f', [0,0,10]) +.addField('orientation', 'SFRotation', xseen.types.SFRotation('0 1 0 0','')) +.addNode(); +xseen.nodes._defineNode ('Inline', 'Networking', 'networking_Inline') +.addField('url', 'SFString', '') +.addNode(); +xseen.nodes._defineNode ('scene', 'Core', 'core_Scene') +.addNode(); +xseen.nodes._defineNode ('canvas', 'Core', 'core_NOOP') +.addNode(); +xseen.nodes._defineNode ('WorldInfo', 'Core', 'core_WorldInfo') +.addNode(); +xseen.nodes._defineNode ('Appearance', 'Appearance', 'appearance_Appearance') +.addNode(); +xseen.nodes._defineNode ('ImageTexture', 'Appearance', 'appearance_ImageTexture') +.addField('url', 'SFString', '') +.addField('repeatS', 'SFBool', true) +.addField('repeatT', 'SFBool', true) +.addNode(); +xseen.nodes._defineNode ('Shape', 'Shape', 'unk_Shape') +.addNode(); +xseen.nodes._defineNode ('Viewpoint', 'Unknown', 'unk_Viewpoint') +.addField('position', 'SFVec3f', '0 0 10') +.addField('orientation', 'SFRotation', xseen.types.SFRotation('0 1 0 0','')) +.addNode(); +xseen.nodes._defineNode('Background', 'Environmental', 'env_Background') +.addField('skyColor', 'SFColor', [0,0,0]) +.addField('srcFront', 'SFString', '') +.addField('srcBack', 'SFString', '') +.addField('srcTop', 'SFString', '') +.addField('srcBottom', 'SFString', '') +.addField('srcLeft', 'SFString', '') +.addField('srcRight', 'SFString', '') +.addField('backgroundIsCube', 'SFBool', 'true') +.addNode(); +xseen.nodes._defineNode('TriangleSet', 'Geometry', 'geometry_TriangleSet') +.addField('ccw', 'SFBool', 'true') +.addField('colorPerVertex', 'SFBool', 'true') +.addField('solid', 'SFBool', 'true') +.addNode(); +xseen.nodes._defineNode('IndexedTriangleSet', 'Geometry', 'geometry_IndexedTriangleSet') +.addField('ccw', 'SFBool', true) +.addField('colorPerVertex', 'SFBool', true) +.addField('solid', 'SFBool', true) +.addField('index', 'MFInt', '') +.addNode(); +xseen.nodes._defineNode('Coordinate', 'Geometry', 'geometry_Coordinate') +.addField('point', 'MFVec3f', []) +.addNode(); +xseen.nodes._defineNode('Normal', 'Geometry', 'geometry_Normal') +.addField('vector', 'MFVec3f', []) +.addNode(); +xseen.nodes._defineNode('Color', 'Geometry', 'geometry_Color') +.addField('color', 'MFColor', []) +.addNode(); +xseen.nodes._defineNode('IndexedFaceSet', 'Geometry', 'geometry_IndexedFaceSet') +.addField('ccw', 'SFBool', true) +.addField('colorPerVertex', 'SFBool', true) +.addField('solid', 'SFBool', true) +.addField('coordIndex', 'MFInt', '') +.addNode(); +xseen.nodes._defineNode('IndexedQuadSet', 'Geometry', 'geometry_IndexedQuadSet') +.addField('ccw', 'SFBool', true) +.addField('colorPerVertex', 'SFBool', true) +.addField('solid', 'SFBool', true) +.addField('index', 'MFInt', '') +.addNode(); +xseen.nodes._defineNode('QuadSet', 'Geometry', 'geometry_QuadSet') +.addField('ccw', 'SFBool', true) +.addField('colorPerVertex', 'SFBool', true) +.addField('solid', 'SFBool', true) +.addNode(); +/* +* XSeen JavaScript library +* +* (c)2017, Daly Realism, Los Angeles +* +* portions extracted from or inspired by +* X3DOM JavaScript Library +* http://www.x3dom.org +* +* (C)2009 Fraunhofer IGD, Darmstadt, Germany +* Dual licensed under the MIT and GPL +*/ +/* +* These are intended to be development support routines. It is anticipated that in +* production systems the array dump would be loaded. As a result, it is necessary +* to have a routine that dumps out the Object (_dumpTable) so it can be captured and saved. A routine +* or documentation on how to load the Object would also be good. +* +*/ +xseen.nodes._defineNode('model', 'XSeen', 'x_Model') +.addField('src', 'SFString', '') +.addField('playonload', 'SFString', '') +.addField('duration', 'SFFloat', '-1') +.addNode(); +xseen.nodes._defineNode('animate', 'XSeen', 'x_Animate') +.addField('field', 'SFString', '') +.addField('to', 'MFFloat', '') // Needs to be 'field' datatype. That is not known until node-parse. For now insist on numeric array +.addField('delay', 'SFTime', 0) +.addField('duration', 'SFTime', 0) +.addField('repeat', 'SFInt', 0) +.addField({name:'interpolator', datatype:'EnumerateString', defaultValue:'position', enumerated:['position', 'rotation', 'color'], animatable:false}) +.addField({name:'Easing', datatype:'EnumerateString', defaultValue:'', enumerated:['', 'in', 'out', 'inout'], animatable:false}) +.addField({name:'EasingType', datatype:'EnumerateString', defaultValue:'linear', enumerated:['linear', 'quadratic', 'sinusoidal', 'exponential', 'elastic', 'bounce'], animatable:false}) +.addField('start', 'SFTime', 0) // incoming event, need to set timer trigger +.addField('end', 'SFTime', 0) // incoming event, need to set timer trigger +.addNode(); \ No newline at end of file