diff --git a/build/three.js b/build/three.js index 02873eaee2e201..d731683e47f135 100644 --- a/build/three.js +++ b/build/three.js @@ -18,9 +18,11 @@ if ( typeof module === 'object' ) { if ( Math.sign === undefined ) { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + Math.sign = function ( x ) { - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0; + return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : +x; }; @@ -8101,6 +8103,8 @@ THREE.Object3D.prototype = { data.geometry = parseGeometry( object.geometry ); data.material = parseMaterial( object.material ); + if ( object instanceof THREE.Line ) data.mode = object.mode; + } else if ( object instanceof THREE.Sprite ) { data.material = parseMaterial( object.material ); @@ -8553,6 +8557,18 @@ THREE.BufferGeometry.prototype = { } + if ( this.boundingBox instanceof THREE.Box3 ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere instanceof THREE.Sphere ) { + + this.computeBoundingSphere(); + + } + }, center: function () { @@ -11457,12 +11473,18 @@ THREE.Loader.prototype = { } - if ( m.transparent !== undefined || m.opacity < 1.0 ) { + if ( m.transparent !== undefined ) { mpars.transparent = m.transparent; } + if ( m.opacity !== undefined && m.opacity < 1.0 ) { + + mpars.transparent = true; + + } + if ( m.depthTest !== undefined ) { mpars.depthTest = m.depthTest; @@ -11539,14 +11561,14 @@ THREE.Loader.prototype = { // modifiers - if ( m.transparency ) { + if ( m.transparency !== undefined ) { console.warn( 'THREE.Loader: transparency has been renamed to opacity' ); - mpars.opacity = m.transparency; + m.opacity = m.transparency; } - if ( m.opacity ) { + if ( m.opacity !== undefined ) { mpars.opacity = m.opacity; @@ -12579,6 +12601,7 @@ THREE.MaterialLoader.prototype = { THREE.ObjectLoader = function ( manager ) { this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + this.texturePath = ''; }; @@ -12588,7 +12611,7 @@ THREE.ObjectLoader.prototype = { load: function ( url, onLoad, onProgress, onError ) { - if ( this.texturePath === undefined ) { + if ( this.texturePath === '' ) { this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); @@ -12631,6 +12654,12 @@ THREE.ObjectLoader.prototype = { var materials = this.parseMaterials( json.materials, textures ); var object = this.parseObject( json.object, geometries, materials ); + if ( json.images === undefined || json.images.length === 0 ) { + + if ( onLoad !== undefined ) onLoad( object ); + + } + return object; }, @@ -12813,6 +12842,9 @@ THREE.ObjectLoader.prototype = { if ( data.bumpMap !== undefined ) { material.bumpMap = getTexture( data.bumpMap ); + if ( data.bumpScale ) { + material.bumpScale = new THREE.Vector2( data.bumpScale, data.bumpScale ); + } } @@ -12831,6 +12863,9 @@ THREE.ObjectLoader.prototype = { if ( data.normalMap !== undefined ) { material.normalMap = getTexture( data.normalMap ); + if ( data.normalScale ) { + material.normalScale = new THREE.Vector2( data.normalScale, data.normalScale ); + } } @@ -12883,15 +12918,12 @@ THREE.ObjectLoader.prototype = { for ( var i = 0, l = json.length; i < l; i ++ ) { var image = json[ i ]; + var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; - images[ image.uuid ] = loadImage( scope.texturePath + image.url ); + images[ image.uuid ] = loadImage( path ); } - } else { - - if ( onLoad !== undefined ) onLoad(); - } return images; @@ -13037,7 +13069,7 @@ THREE.ObjectLoader.prototype = { case 'Line': - object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ) ); + object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); break; @@ -13399,6 +13431,8 @@ THREE.Material = function () { this.depthTest = true; this.depthWrite = true; + this.colorWrite = true; + this.polygonOffset = false; this.polygonOffsetFactor = 0; this.polygonOffsetUnits = 0; @@ -13501,6 +13535,7 @@ THREE.Material.prototype = { output.color = this.color.getHex(); output.emissive = this.emissive.getHex(); if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; @@ -13511,12 +13546,12 @@ THREE.Material.prototype = { output.specular = this.specular.getHex(); output.shininess = this.shininess; if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; } else if ( this instanceof THREE.MeshNormalMaterial ) { - if ( this.shading !== THREE.FlatShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; @@ -13530,10 +13565,10 @@ THREE.Material.prototype = { output.size = this.size; output.sizeAttenuation = this.sizeAttenuation; output.color = this.color.getHex(); - + if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; - + } else if ( this instanceof THREE.ShaderMaterial ) { output.uniforms = this.uniforms; @@ -14234,8 +14269,6 @@ THREE.MeshNormalMaterial = function ( parameters ) { this.type = 'MeshNormalMaterial'; - this.shading = THREE.FlatShading; - this.wireframe = false; this.wireframeLinewidth = 1; @@ -14254,8 +14287,6 @@ THREE.MeshNormalMaterial.prototype.clone = function () { THREE.Material.prototype.clone.call( this, material ); - material.shading = this.shading; - material.wireframe = this.wireframe; material.wireframeLinewidth = this.wireframeLinewidth; @@ -15051,7 +15082,7 @@ THREE.Line = function ( geometry, material, mode ) { this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } ); - this.mode = ( mode !== undefined ) ? mode : THREE.LineStrip; + this.mode = mode !== undefined ? mode : THREE.LineStrip; }; @@ -16573,7 +16604,7 @@ THREE.ShaderChunk[ 'lightmap_pars_vertex'] = "#ifdef USE_LIGHTMAP\n\n varying ve // File:src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl -THREE.ShaderChunk[ 'lights_phong_fragment'] = "vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\n\n#ifdef DOUBLE_SIDED\n\n normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n#endif\n\n#ifdef USE_NORMALMAP\n\n normal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n vec3 pointDiffuse = vec3( 0.0 );\n vec3 pointSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float pointDiffuseWeightFull = max( dotProduct, 0.0 );\n float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float pointDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * attenuation;\n\n // specular\n\n vec3 pointHalfVector = normalize( lVector + viewPosition );\n float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );\n pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n vec3 spotDiffuse = vec3( 0.0 );\n vec3 spotSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float spotDiffuseWeightFull = max( dotProduct, 0.0 );\n float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float spotDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;\n\n // specular\n\n vec3 spotHalfVector = normalize( lVector + viewPosition );\n float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );\n spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n vec3 dirDiffuse = vec3( 0.0 );\n vec3 dirSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, dirVector );\n\n #ifdef WRAP_AROUND\n\n float dirDiffuseWeightFull = max( dotProduct, 0.0 );\n float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float dirDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\n\n // specular\n\n vec3 dirHalfVector = normalize( dirVector + viewPosition );\n float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\n /*\n // fresnel term from skin shader\n const float F0 = 0.128;\n\n float base = 1.0 - dot( viewPosition, dirHalfVector );\n float exponential = pow( base, 5.0 );\n\n float fresnel = exponential + F0 * ( 1.0 - exponential );\n */\n\n /*\n // fresnel term from fresnel shader\n const float mFresnelBias = 0.08;\n const float mFresnelScale = 0.3;\n const float mFresnelPower = 5.0;\n\n float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );\n */\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n // dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n vec3 hemiDiffuse = vec3( 0.0 );\n vec3 hemiSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n hemiDiffuse += diffuse * hemiColor;\n\n // specular (sky light)\n\n vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\n // specular (ground light)\n\n vec3 lVectorGround = -lVector;\n\n vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\n float dotProductGround = dot( normal, lVectorGround );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\n }\n\n#endif\n\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n\n#if MAX_DIR_LIGHTS > 0\n\n totalDiffuse += dirDiffuse;\n totalSpecular += dirSpecular;\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n totalDiffuse += hemiDiffuse;\n totalSpecular += hemiSpecular;\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n totalDiffuse += pointDiffuse;\n totalSpecular += pointSpecular;\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n totalDiffuse += spotDiffuse;\n totalSpecular += spotSpecular;\n\n#endif\n\n#ifdef METAL\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse + totalSpecular );\n\n#else\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse ) + totalSpecular;\n\n#endif\n"; +THREE.ShaderChunk[ 'lights_phong_fragment'] = "#ifndef FLAT_SHADED\n\n vec3 normal = normalize( vNormal );\n\n #ifdef DOUBLE_SIDED\n\n normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );\n\n #endif\n\n#else\n\n vec3 fdx = dFdx( vViewPosition );\n vec3 fdy = dFdy( vViewPosition );\n vec3 normal = normalize( cross( fdx, fdy ) );\n\n#endif\n\nvec3 viewPosition = normalize( vViewPosition );\n\n#ifdef USE_NORMALMAP\n\n normal = perturbNormal2Arb( -vViewPosition, normal );\n\n#elif defined( USE_BUMPMAP )\n\n normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n vec3 pointDiffuse = vec3( 0.0 );\n vec3 pointSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float pointDiffuseWeightFull = max( dotProduct, 0.0 );\n float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 pointDiffuseWeight = mix( vec3( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float pointDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * attenuation;\n\n // specular\n\n vec3 pointHalfVector = normalize( lVector + viewPosition );\n float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );\n float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );\n pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;\n\n }\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n vec3 spotDiffuse = vec3( 0.0 );\n vec3 spotSpecular = vec3( 0.0 );\n\n for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {\n\n vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );\n vec3 lVector = lPosition.xyz + vViewPosition.xyz;\n\n float attenuation = calcLightAttenuation( length( lVector ), spotLightDistance[ i ], spotLightDecay[ i ] );\n\n lVector = normalize( lVector );\n\n float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );\n\n if ( spotEffect > spotLightAngleCos[ i ] ) {\n\n spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n\n #ifdef WRAP_AROUND\n\n float spotDiffuseWeightFull = max( dotProduct, 0.0 );\n float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 spotDiffuseWeight = mix( vec3( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float spotDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;\n\n // specular\n\n vec3 spotHalfVector = normalize( lVector + viewPosition );\n float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );\n float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );\n spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;\n\n }\n\n }\n\n#endif\n\n#if MAX_DIR_LIGHTS > 0\n\n vec3 dirDiffuse = vec3( 0.0 );\n vec3 dirSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {\n\n vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, dirVector );\n\n #ifdef WRAP_AROUND\n\n float dirDiffuseWeightFull = max( dotProduct, 0.0 );\n float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );\n\n vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );\n\n #else\n\n float dirDiffuseWeight = max( dotProduct, 0.0 );\n\n #endif\n\n dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;\n\n // specular\n\n vec3 dirHalfVector = normalize( dirVector + viewPosition );\n float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );\n float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );\n\n /*\n // fresnel term from skin shader\n const float F0 = 0.128;\n\n float base = 1.0 - dot( viewPosition, dirHalfVector );\n float exponential = pow( base, 5.0 );\n\n float fresnel = exponential + F0 * ( 1.0 - exponential );\n */\n\n /*\n // fresnel term from fresnel shader\n const float mFresnelBias = 0.08;\n const float mFresnelScale = 0.3;\n const float mFresnelPower = 5.0;\n\n float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );\n */\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n // dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;\n\n vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );\n dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;\n\n\n }\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n vec3 hemiDiffuse = vec3( 0.0 );\n vec3 hemiSpecular = vec3( 0.0 );\n\n for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {\n\n vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );\n\n // diffuse\n\n float dotProduct = dot( normal, lVector );\n float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;\n\n vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );\n\n hemiDiffuse += diffuse * hemiColor;\n\n // specular (sky light)\n\n vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );\n float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;\n float hemiSpecularWeightSky = specularStrength * max( pow( max( hemiDotNormalHalfSky, 0.0 ), shininess ), 0.0 );\n\n // specular (ground light)\n\n vec3 lVectorGround = -lVector;\n\n vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );\n float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;\n float hemiSpecularWeightGround = specularStrength * max( pow( max( hemiDotNormalHalfGround, 0.0 ), shininess ), 0.0 );\n\n float dotProductGround = dot( normal, lVectorGround );\n\n float specularNormalization = ( shininess + 2.0 ) / 8.0;\n\n vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );\n vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );\n hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );\n\n }\n\n#endif\n\nvec3 totalDiffuse = vec3( 0.0 );\nvec3 totalSpecular = vec3( 0.0 );\n\n#if MAX_DIR_LIGHTS > 0\n\n totalDiffuse += dirDiffuse;\n totalSpecular += dirSpecular;\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n totalDiffuse += hemiDiffuse;\n totalSpecular += hemiSpecular;\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n totalDiffuse += pointDiffuse;\n totalSpecular += pointSpecular;\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n totalDiffuse += spotDiffuse;\n totalSpecular += spotSpecular;\n\n#endif\n\n#ifdef METAL\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse + totalSpecular );\n\n#else\n\n gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse ) + totalSpecular;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl @@ -16593,7 +16624,7 @@ THREE.ShaderChunk[ 'logdepthbuf_fragment'] = "#if defined(USE_LOGDEPTHBUF) && de // File:src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl -THREE.ShaderChunk[ 'normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n // Per-Pixel Tangent Space Normal Mapping\n // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n#endif\n"; +THREE.ShaderChunk[ 'normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n\n uniform sampler2D normalMap;\n uniform vec2 normalScale;\n\n // Per-Pixel Tangent Space Normal Mapping\n // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\n vec3 q0 = dFdx( eye_pos.xyz );\n vec3 q1 = dFdy( eye_pos.xyz );\n vec2 st0 = dFdx( vUv.st );\n vec2 st1 = dFdy( vUv.st );\n\n vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n vec3 N = normalize( surf_norm );\n\n vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n mapN.xy = normalScale * mapN.xy;\n mat3 tsn = mat3( S, T, N );\n return normalize( tsn * mapN );\n\n }\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_vertex.glsl @@ -16681,7 +16712,7 @@ THREE.ShaderChunk[ 'fog_fragment'] = "#ifdef USE_FOG\n\n #ifdef USE_LOGDEPTHBUF_ // File:src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl -THREE.ShaderChunk[ 'bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n\n // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\n // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\n\n // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n vec2 dHdxy_fwd() {\n\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n return vec2( dBx, dBy );\n\n }\n\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm; // normalized\n\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n\n float fDet = dot( vSigmaX, R1 );\n\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n\n }\n\n#endif"; +THREE.ShaderChunk[ 'bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n\n uniform sampler2D bumpMap;\n uniform float bumpScale;\n\n // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen\n // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html\n\n // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n vec2 dHdxy_fwd() {\n\n vec2 dSTdx = dFdx( vUv );\n vec2 dSTdy = dFdy( vUv );\n\n float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n return vec2( dBx, dBy );\n\n }\n\n vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n vec3 vSigmaX = dFdx( surf_pos );\n vec3 vSigmaY = dFdy( surf_pos );\n vec3 vN = surf_norm; // normalized\n\n vec3 R1 = cross( vSigmaY, vN );\n vec3 R2 = cross( vN, vSigmaX );\n\n float fDet = dot( vSigmaX, R1 );\n\n vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n return normalize( abs( fDet ) * surf_norm - vGrad );\n\n }\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl @@ -16689,7 +16720,7 @@ THREE.ShaderChunk[ 'defaultnormal_vertex'] = "#ifdef USE_SKINNING\n\n vec3 objec // File:src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl -THREE.ShaderChunk[ 'lights_phong_pars_fragment'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;\n"; +THREE.ShaderChunk[ 'lights_phong_pars_fragment'] = "uniform vec3 ambientLightColor;\n\n#if MAX_DIR_LIGHTS > 0\n\n uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\n uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n\n#endif\n\n#if MAX_HEMI_LIGHTS > 0\n\n uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];\n uniform vec3 hemisphereLightDirection[ MAX_HEMI_LIGHTS ];\n\n#endif\n\n#if MAX_POINT_LIGHTS > 0\n\n uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\n\n uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n uniform float pointLightDistance[ MAX_POINT_LIGHTS ];\n uniform float pointLightDecay[ MAX_POINT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0\n\n uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];\n uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];\n uniform float spotLightAngleCos[ MAX_SPOT_LIGHTS ];\n uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];\n uniform float spotLightDecay[ MAX_SPOT_LIGHTS ];\n\n#endif\n\n#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP ) || defined( USE_ENVMAP )\n\n varying vec3 vWorldPosition;\n\n#endif\n\n#ifdef WRAP_AROUND\n\n uniform vec3 wrapRGB;\n\n#endif\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n varying vec3 vNormal;\n\n#endif\n"; // File:src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl @@ -17179,7 +17210,12 @@ THREE.ShaderLib = { "#define PHONG", "varying vec3 vViewPosition;", - "varying vec3 vNormal;", + + "#ifndef FLAT_SHADED", + + " varying vec3 vNormal;", + + "#endif", THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], @@ -17203,8 +17239,12 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "skinnormal_vertex" ], THREE.ShaderChunk[ "defaultnormal_vertex" ], + "#ifndef FLAT_SHADED", + " vNormal = normalize( transformedNormal );", + "#endif", + THREE.ShaderChunk[ "morphtarget_vertex" ], THREE.ShaderChunk[ "skinning_vertex" ], THREE.ShaderChunk[ "default_vertex" ], @@ -17619,7 +17659,7 @@ THREE.ShaderLib = { "vec3 direction = normalize( vWorldPosition );", "vec2 sampleUV;", "sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );", - "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;", + "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;", "gl_FragColor = texture2D( tEquirect, sampleUV );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], @@ -18890,13 +18930,13 @@ THREE.WebGLRenderer = function ( parameters ) { ? object.material.materials[ geometryGroup.materialIndex ] : object.material; - }; + } - function materialNeedsSmoothNormals ( material ) { + function materialNeedsFaceNormals ( material ) { - return material && material.shading !== undefined && material.shading === THREE.SmoothShading; + return material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading; - }; + } // Buffer setting @@ -19237,7 +19277,7 @@ THREE.WebGLRenderer = function ( parameters ) { } - var needsSmoothNormals = materialNeedsSmoothNormals( material ); + var needsFaceNormals = materialNeedsFaceNormals( material ); var f, fl, fi, face, vertexNormals, faceNormal, normal, @@ -19382,7 +19422,13 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.morphNormals ) { - if ( needsSmoothNormals ) { + if ( needsFaceNormals ) { + + n1 = morphNormals[ vk ].faceNormals[ chf ]; + n2 = n1; + n3 = n1; + + } else { faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ]; @@ -19390,12 +19436,6 @@ THREE.WebGLRenderer = function ( parameters ) { n2 = faceVertexNormals.b; n3 = faceVertexNormals.c; - } else { - - n1 = morphNormals[ vk ].faceNormals[ chf ]; - n2 = n1; - n3 = n1; - } nka = morphNormalsArrays[ vk ]; @@ -19591,7 +19631,7 @@ THREE.WebGLRenderer = function ( parameters ) { vertexNormals = face.vertexNormals; faceNormal = face.normal; - if ( vertexNormals.length === 3 && needsSmoothNormals ) { + if ( vertexNormals.length === 3 && needsFaceNormals === false ) { for ( i = 0; i < 3; i ++ ) { @@ -20054,7 +20094,8 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer ); - if ( material.shading === THREE.FlatShading ) { + if ( material instanceof THREE.MeshPhongMaterial === false && + material.shading === THREE.FlatShading ) { var nx, ny, nz, nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz, @@ -20944,9 +20985,9 @@ THREE.WebGLRenderer = function ( parameters ) { function painterSortStable ( a, b ) { - if ( a.renderOrder !== b.renderOrder ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return a.renderOrder - b.renderOrder; + return a.object.renderOrder - b.object.renderOrder; } else if ( a.material.id !== b.material.id ) { @@ -20966,9 +21007,9 @@ THREE.WebGLRenderer = function ( parameters ) { function reversePainterSortStable ( a, b ) { - if ( a.renderOrder !== b.renderOrder ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return a.renderOrder - b.renderOrder; + return a.object.renderOrder - b.object.renderOrder; } if ( a.z !== b.z ) { @@ -21128,6 +21169,7 @@ THREE.WebGLRenderer = function ( parameters ) { state.setDepthTest( true ); state.setDepthWrite( true ); + state.setColorWrite( true ); // _gl.finish(); @@ -21875,6 +21917,8 @@ THREE.WebGLRenderer = function ( parameters ) { useFog: material.fog, fogExp: fog instanceof THREE.FogExp2, + flatShading: material.shading === THREE.FlatShading, + sizeAttenuation: material.sizeAttenuation, logarithmicDepthBuffer: _logarithmicDepthBuffer, @@ -22041,6 +22085,7 @@ THREE.WebGLRenderer = function ( parameters ) { state.setDepthTest( material.depthTest ); state.setDepthWrite( material.depthWrite ); + state.setColorWrite( material.colorWrite ); state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); } @@ -24295,6 +24340,8 @@ THREE.WebGLProgram = ( function () { parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.flatShading ? '#define FLAT_SHADED': '', + parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', @@ -24374,7 +24421,7 @@ THREE.WebGLProgram = ( function () { 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - ( parameters.bumpMap || parameters.normalMap ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', customDefines, @@ -24406,6 +24453,8 @@ THREE.WebGLProgram = ( function () { parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.flatShading ? '#define FLAT_SHADED': '', + parameters.metal ? '#define METAL' : '', parameters.wrapAround ? '#define WRAP_AROUND' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', @@ -24452,7 +24501,7 @@ THREE.WebGLProgram = ( function () { THREE.error( 'THREE.WebGLProgram: shader error: ' + _gl.getError(), 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ), 'gl.getPRogramInfoLog', programLogInfo ); } - + if ( programLogInfo !== '' ) { THREE.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()' + programLogInfo ); @@ -24629,6 +24678,8 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { var currentDepthTest = null; var currentDepthWrite = null; + var currentColorWrite = null; + var currentDoubleSided = null; var currentFlipSided = null; @@ -24790,6 +24841,17 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { }; + this.setColorWrite = function ( colorWrite ) { + + if ( currentColorWrite !== colorWrite ) { + + gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite ); + currentColorWrite = colorWrite; + + } + + }; + this.setDoubleSided = function ( doubleSided ) { if ( currentDoubleSided !== doubleSided ) { @@ -24882,6 +24944,7 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { currentBlending = null; currentDepthTest = null; currentDepthWrite = null; + currentColorWrite = null; currentDoubleSided = null; currentFlipSided = null; @@ -33964,7 +34027,7 @@ THREE.GridHelper.prototype.setColors = function( colorCenterLine, colorGrid ) { * @author mrdoob / http://mrdoob.com/ */ -THREE.HemisphereLightHelper = function ( light, sphereSize, arrowLength, domeSize ) { +THREE.HemisphereLightHelper = function ( light, sphereSize ) { THREE.Object3D.call( this ); diff --git a/build/three.min.js b/build/three.min.js index 6c7eff1ff43fdd..7823c76477e3f1 100644 --- a/build/three.min.js +++ b/build/three.min.js @@ -1,5 +1,5 @@ // threejs.org/license -'use strict';var THREE={REVISION:"71dev"};"object"===typeof module&&(module.exports=THREE);void 0===Math.sign&&(Math.sign=function(a){return 0>a?-1:0a?-1:0qa?-1:1;h[4*a]=oa.x;h[4*a+1]=oa.y;h[4*a+2]=oa.z;h[4*a+3]=ca}if(void 0===this.attributes.index||void 0===this.attributes.position||void 0===this.attributes.normal||void 0===this.attributes.uv)THREE.warn("THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()");else{var c=this.attributes.index.array,d=this.attributes.position.array, -e=this.attributes.normal.array,f=this.attributes.uv.array,g=d.length/3;void 0===this.attributes.tangent&&this.addAttribute("tangent",new THREE.BufferAttribute(new Float32Array(4*g),4));for(var h=this.attributes.tangent.array,k=[],l=[],p=0;pr;r++)s=a[3*c+r],-1==n[s]?(q[2*r]=s,q[2*r+1]=-1,p++):n[s]k.index+b)for(k={start:f,count:0,index:g},h.push(k),p=0;6>p;p+=2)r=q[p+1],-1p;p+=2)s=q[p],r=q[p+1],-1===r&&(r=g++),n[s]=r,t[r]=s,e[f++]=r-k.index,k.count++}this.reorderBuffers(e,t,g);return this.offsets=h},merge:function(a,b){if(!1===a instanceof THREE.BufferGeometry)THREE.error("THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.",a);else{void 0===b&&(b=0);var c=this.attributes,d;for(d in c)if(void 0!==a.attributes[d])for(var e=c[d].array,f=a.attributes[d],g=f.array,h=0,f=f.itemSize*b;hqa?-1:1;h[4*a]=oa.x;h[4*a+1]=oa.y;h[4*a+2]=oa.z;h[4*a+3]=ca}if(void 0===this.attributes.index||void 0===this.attributes.position||void 0===this.attributes.normal||void 0===this.attributes.uv)THREE.warn("THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()"); +else{var c=this.attributes.index.array,d=this.attributes.position.array,e=this.attributes.normal.array,f=this.attributes.uv.array,g=d.length/3;void 0===this.attributes.tangent&&this.addAttribute("tangent",new THREE.BufferAttribute(new Float32Array(4*g),4));for(var h=this.attributes.tangent.array,k=[],l=[],p=0;pr;r++)s=a[3*c+r],-1==n[s]?(q[2*r]=s,q[2*r+1]=-1,p++):n[s]k.index+ +b)for(k={start:f,count:0,index:g},h.push(k),p=0;6>p;p+=2)r=q[p+1],-1p;p+=2)s=q[p],r=q[p+1],-1===r&&(r=g++),n[s]=r,t[r]=s,e[f++]=r-k.index,k.count++}this.reorderBuffers(e,t,g);return this.offsets=h},merge:function(a,b){if(!1===a instanceof THREE.BufferGeometry)THREE.error("THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.",a);else{void 0===b&&(b=0);var c=this.attributes,d;for(d in c)if(void 0!==a.attributes[d])for(var e=c[d].array, +f=a.attributes[d],g=f.array,h=0,f=f.itemSize*b;hd?-1:1,e.vertexTangents[c]=new THREE.Vector4(w.x,w.y,w.z,d);this.hasTangents=!0},computeLineDistances:function(){for(var a=0,b=this.vertices,c=0,d=b.length;cd;d++)if(e[d]==e[(d+1)%3]){a.push(f);break}for(f=a.length-1;0<=f;f--)for(e=a[f],this.faces.splice(e,1),c=0,g=this.faceVertexUvs.length;ca.opacity)h.transparent=a.transparent;void 0!==a.depthTest&&(h.depthTest=a.depthTest);void 0!==a.depthWrite&&(h.depthWrite=a.depthWrite);void 0!==a.visible&&(h.visible=a.visible);void 0!==a.flipSided&&(h.side=THREE.BackSide);void 0!==a.doubleSided&&(h.side=THREE.DoubleSide);void 0!==a.wireframe&&(h.wireframe=a.wireframe);void 0!==a.vertexColors&&("face"=== -a.vertexColors?h.vertexColors=THREE.FaceColors:a.vertexColors&&(h.vertexColors=THREE.VertexColors));a.colorDiffuse?h.color=e(a.colorDiffuse):a.DbgColor&&(h.color=a.DbgColor);a.colorSpecular&&(h.specular=e(a.colorSpecular));a.colorEmissive&&(h.emissive=e(a.colorEmissive));a.transparency&&(console.warn("THREE.Loader: transparency has been renamed to opacity"),h.opacity=a.transparency);a.opacity&&(h.opacity=a.opacity);a.specularCoef&&(h.shininess=a.specularCoef);a.mapDiffuse&&b&&d(h,"map",a.mapDiffuse, -a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap,a.mapDiffuseAnisotropy);a.mapLight&&b&&d(h,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&d(h,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&d(h,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&d(h,"specularMap",a.mapSpecular,a.mapSpecularRepeat,a.mapSpecularOffset, -a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapAlpha&&b&&d(h,"alphaMap",a.mapAlpha,a.mapAlphaRepeat,a.mapAlphaOffset,a.mapAlphaWrap,a.mapAlphaAnisotropy);a.mapBumpScale&&(h.bumpScale=a.mapBumpScale);a.mapNormalFactor&&(h.normalScale=new THREE.Vector2(a.mapNormalFactor,a.mapNormalFactor));g=new THREE[g](h);void 0!==a.DbgName&&(g.name=a.DbgName);return g}}; +"basic"===k&&(g="MeshBasicMaterial")}void 0!==a.blending&&void 0!==THREE[a.blending]&&(h.blending=THREE[a.blending]);void 0!==a.transparent&&(h.transparent=a.transparent);void 0!==a.opacity&&1>a.opacity&&(h.transparent=!0);void 0!==a.depthTest&&(h.depthTest=a.depthTest);void 0!==a.depthWrite&&(h.depthWrite=a.depthWrite);void 0!==a.visible&&(h.visible=a.visible);void 0!==a.flipSided&&(h.side=THREE.BackSide);void 0!==a.doubleSided&&(h.side=THREE.DoubleSide);void 0!==a.wireframe&&(h.wireframe=a.wireframe); +void 0!==a.vertexColors&&("face"===a.vertexColors?h.vertexColors=THREE.FaceColors:a.vertexColors&&(h.vertexColors=THREE.VertexColors));a.colorDiffuse?h.color=e(a.colorDiffuse):a.DbgColor&&(h.color=a.DbgColor);a.colorSpecular&&(h.specular=e(a.colorSpecular));a.colorEmissive&&(h.emissive=e(a.colorEmissive));void 0!==a.transparency&&(console.warn("THREE.Loader: transparency has been renamed to opacity"),a.opacity=a.transparency);void 0!==a.opacity&&(h.opacity=a.opacity);a.specularCoef&&(h.shininess= +a.specularCoef);a.mapDiffuse&&b&&d(h,"map",a.mapDiffuse,a.mapDiffuseRepeat,a.mapDiffuseOffset,a.mapDiffuseWrap,a.mapDiffuseAnisotropy);a.mapLight&&b&&d(h,"lightMap",a.mapLight,a.mapLightRepeat,a.mapLightOffset,a.mapLightWrap,a.mapLightAnisotropy);a.mapBump&&b&&d(h,"bumpMap",a.mapBump,a.mapBumpRepeat,a.mapBumpOffset,a.mapBumpWrap,a.mapBumpAnisotropy);a.mapNormal&&b&&d(h,"normalMap",a.mapNormal,a.mapNormalRepeat,a.mapNormalOffset,a.mapNormalWrap,a.mapNormalAnisotropy);a.mapSpecular&&b&&d(h,"specularMap", +a.mapSpecular,a.mapSpecularRepeat,a.mapSpecularOffset,a.mapSpecularWrap,a.mapSpecularAnisotropy);a.mapAlpha&&b&&d(h,"alphaMap",a.mapAlpha,a.mapAlphaRepeat,a.mapAlphaOffset,a.mapAlphaWrap,a.mapAlphaAnisotropy);a.mapBumpScale&&(h.bumpScale=a.mapBumpScale);a.mapNormalFactor&&(h.normalScale=new THREE.Vector2(a.mapNormalFactor,a.mapNormalFactor));g=new THREE[g](h);void 0!==a.DbgName&&(g.name=a.DbgName);return g}}; THREE.Loader.Handlers={handlers:[],add:function(a,b){this.handlers.push(a,b)},get:function(a){for(var b=0,c=this.handlers.length;bg;g++)n=x[k++],v=u[2*n],n=u[2*n+1],v=new THREE.Vector2(v,n),2!==g&&c.faceVertexUvs[d][h].push(v),0!==g&&c.faceVertexUvs[d][h+1].push(v);q&&(q=3*x[k++],t.normal.set(F[q++],F[q++],F[q]),r.normal.copy(t.normal));if(s)for(d=0;4>d;d++)q=3*x[k++],s=new THREE.Vector3(F[q++], -F[q++],F[q]),2!==d&&t.vertexNormals.push(s),0!==d&&r.vertexNormals.push(s);p&&(p=x[k++],p=w[p],t.color.setHex(p),r.color.setHex(p));if(b)for(d=0;4>d;d++)p=x[k++],p=w[p],2!==d&&t.vertexColors.push(new THREE.Color(p)),0!==d&&r.vertexColors.push(new THREE.Color(p));c.faces.push(t);c.faces.push(r)}else{t=new THREE.Face3;t.a=x[k++];t.b=x[k++];t.c=x[k++];h&&(h=x[k++],t.materialIndex=h);h=c.faces.length;if(d)for(d=0;dg;g++)n=x[k++],v=u[2*n],n=u[2*n+1], -v=new THREE.Vector2(v,n),c.faceVertexUvs[d][h].push(v);q&&(q=3*x[k++],t.normal.set(F[q++],F[q++],F[q]));if(s)for(d=0;3>d;d++)q=3*x[k++],s=new THREE.Vector3(F[q++],F[q++],F[q]),t.vertexNormals.push(s);p&&(p=x[k++],t.color.setHex(w[p]));if(b)for(d=0;3>d;d++)p=x[k++],t.vertexColors.push(new THREE.Color(w[p]));c.faces.push(t)}})(d);(function(){var b=void 0!==a.influencesPerVertex?a.influencesPerVertex:2;if(a.skinWeights)for(var d=0,g=a.skinWeights.length;dg;g++)n=x[k++],v=u[2*n],n=u[2*n+1],v=new THREE.Vector2(v,n),2!==g&&c.faceVertexUvs[d][h].push(v),0!==g&&c.faceVertexUvs[d][h+1].push(v);q&&(q=3*x[k++],t.normal.set(D[q++],D[q++],D[q]),r.normal.copy(t.normal));if(s)for(d=0;4>d;d++)q=3*x[k++],s=new THREE.Vector3(D[q++], +D[q++],D[q]),2!==d&&t.vertexNormals.push(s),0!==d&&r.vertexNormals.push(s);p&&(p=x[k++],p=w[p],t.color.setHex(p),r.color.setHex(p));if(b)for(d=0;4>d;d++)p=x[k++],p=w[p],2!==d&&t.vertexColors.push(new THREE.Color(p)),0!==d&&r.vertexColors.push(new THREE.Color(p));c.faces.push(t);c.faces.push(r)}else{t=new THREE.Face3;t.a=x[k++];t.b=x[k++];t.c=x[k++];h&&(h=x[k++],t.materialIndex=h);h=c.faces.length;if(d)for(d=0;dg;g++)n=x[k++],v=u[2*n],n=u[2*n+1], +v=new THREE.Vector2(v,n),c.faceVertexUvs[d][h].push(v);q&&(q=3*x[k++],t.normal.set(D[q++],D[q++],D[q]));if(s)for(d=0;3>d;d++)q=3*x[k++],s=new THREE.Vector3(D[q++],D[q++],D[q]),t.vertexNormals.push(s);p&&(p=x[k++],t.color.setHex(w[p]));if(b)for(d=0;3>d;d++)p=x[k++],t.vertexColors.push(new THREE.Color(w[p]));c.faces.push(t)}})(d);(function(){var b=void 0!==a.influencesPerVertex?a.influencesPerVertex:2;if(a.skinWeights)for(var d=0,g=a.skinWeights.length;dthis.opacity&&(a.opacity=this.opacity);!1!==this.transparent&&(a.transparent=this.transparent);!1!==this.wireframe&&(a.wireframe=this.wireframe);return a},clone:function(a){void 0===a&&(a=new THREE.Material); -a.name=this.name;a.side=this.side;a.opacity=this.opacity;a.transparent=this.transparent;a.blending=this.blending;a.blendSrc=this.blendSrc;a.blendDst=this.blendDst;a.blendEquation=this.blendEquation;a.blendSrcAlpha=this.blendSrcAlpha;a.blendDstAlpha=this.blendDstAlpha;a.blendEquationAlpha=this.blendEquationAlpha;a.depthTest=this.depthTest;a.depthWrite=this.depthWrite;a.polygonOffset=this.polygonOffset;a.polygonOffsetFactor=this.polygonOffsetFactor;a.polygonOffsetUnits=this.polygonOffsetUnits;a.alphaTest= -this.alphaTest;a.overdraw=this.overdraw;a.visible=this.visible;return a},update:function(){this.dispatchEvent({type:"update"})},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.EventDispatcher.prototype.apply(THREE.Material.prototype);THREE.MaterialIdCount=0;THREE.LineBasicMaterial=function(a){THREE.Material.call(this);this.type="LineBasicMaterial";this.color=new THREE.Color(16777215);this.linewidth=1;this.linejoin=this.linecap="round";this.vertexColors=THREE.NoColors;this.fog=!0;this.setValues(a)}; -THREE.LineBasicMaterial.prototype=Object.create(THREE.Material.prototype);THREE.LineBasicMaterial.prototype.constructor=THREE.LineBasicMaterial;THREE.LineBasicMaterial.prototype.clone=function(){var a=new THREE.LineBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.linewidth=this.linewidth;a.linecap=this.linecap;a.linejoin=this.linejoin;a.vertexColors=this.vertexColors;a.fog=this.fog;return a}; +(a.vertexColors=this.vertexColors),this.shading!==THREE.SmoothShading&&(a.shading=this.shading),this.blending!==THREE.NormalBlending&&(a.blending=this.blending),this.side!==THREE.FrontSide&&(a.side=this.side)):this instanceof THREE.MeshPhongMaterial?(a.color=this.color.getHex(),a.emissive=this.emissive.getHex(),a.specular=this.specular.getHex(),a.shininess=this.shininess,this.vertexColors!==THREE.NoColors&&(a.vertexColors=this.vertexColors),this.shading!==THREE.SmoothShading&&(a.shading=this.shading), +this.blending!==THREE.NormalBlending&&(a.blending=this.blending),this.side!==THREE.FrontSide&&(a.side=this.side)):this instanceof THREE.MeshNormalMaterial?(this.blending!==THREE.NormalBlending&&(a.blending=this.blending),this.side!==THREE.FrontSide&&(a.side=this.side)):this instanceof THREE.MeshDepthMaterial?(this.blending!==THREE.NormalBlending&&(a.blending=this.blending),this.side!==THREE.FrontSide&&(a.side=this.side)):this instanceof THREE.PointCloudMaterial?(a.size=this.size,a.sizeAttenuation= +this.sizeAttenuation,a.color=this.color.getHex(),this.vertexColors!==THREE.NoColors&&(a.vertexColors=this.vertexColors),this.blending!==THREE.NormalBlending&&(a.blending=this.blending)):this instanceof THREE.ShaderMaterial?(a.uniforms=this.uniforms,a.vertexShader=this.vertexShader,a.fragmentShader=this.fragmentShader):this instanceof THREE.SpriteMaterial&&(a.color=this.color.getHex());1>this.opacity&&(a.opacity=this.opacity);!1!==this.transparent&&(a.transparent=this.transparent);!1!==this.wireframe&& +(a.wireframe=this.wireframe);return a},clone:function(a){void 0===a&&(a=new THREE.Material);a.name=this.name;a.side=this.side;a.opacity=this.opacity;a.transparent=this.transparent;a.blending=this.blending;a.blendSrc=this.blendSrc;a.blendDst=this.blendDst;a.blendEquation=this.blendEquation;a.blendSrcAlpha=this.blendSrcAlpha;a.blendDstAlpha=this.blendDstAlpha;a.blendEquationAlpha=this.blendEquationAlpha;a.depthTest=this.depthTest;a.depthWrite=this.depthWrite;a.polygonOffset=this.polygonOffset;a.polygonOffsetFactor= +this.polygonOffsetFactor;a.polygonOffsetUnits=this.polygonOffsetUnits;a.alphaTest=this.alphaTest;a.overdraw=this.overdraw;a.visible=this.visible;return a},update:function(){this.dispatchEvent({type:"update"})},dispose:function(){this.dispatchEvent({type:"dispose"})}};THREE.EventDispatcher.prototype.apply(THREE.Material.prototype);THREE.MaterialIdCount=0; +THREE.LineBasicMaterial=function(a){THREE.Material.call(this);this.type="LineBasicMaterial";this.color=new THREE.Color(16777215);this.linewidth=1;this.linejoin=this.linecap="round";this.vertexColors=THREE.NoColors;this.fog=!0;this.setValues(a)};THREE.LineBasicMaterial.prototype=Object.create(THREE.Material.prototype);THREE.LineBasicMaterial.prototype.constructor=THREE.LineBasicMaterial; +THREE.LineBasicMaterial.prototype.clone=function(){var a=new THREE.LineBasicMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.linewidth=this.linewidth;a.linecap=this.linecap;a.linejoin=this.linejoin;a.vertexColors=this.vertexColors;a.fog=this.fog;return a}; THREE.LineDashedMaterial=function(a){THREE.Material.call(this);this.type="LineDashedMaterial";this.color=new THREE.Color(16777215);this.scale=this.linewidth=1;this.dashSize=3;this.gapSize=1;this.vertexColors=!1;this.fog=!0;this.setValues(a)};THREE.LineDashedMaterial.prototype=Object.create(THREE.Material.prototype);THREE.LineDashedMaterial.prototype.constructor=THREE.LineDashedMaterial; THREE.LineDashedMaterial.prototype.clone=function(){var a=new THREE.LineDashedMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.linewidth=this.linewidth;a.scale=this.scale;a.dashSize=this.dashSize;a.gapSize=this.gapSize;a.vertexColors=this.vertexColors;a.fog=this.fog;return a}; THREE.MeshBasicMaterial=function(a){THREE.Material.call(this);this.type="MeshBasicMaterial";this.color=new THREE.Color(16777215);this.envMap=this.alphaMap=this.specularMap=this.lightMap=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refractionRatio=.98;this.fog=!0;this.shading=THREE.SmoothShading;this.wireframe=!1;this.wireframeLinewidth=1;this.wireframeLinejoin=this.wireframeLinecap="round";this.vertexColors=THREE.NoColors;this.morphTargets=this.skinning=!1;this.setValues(a)}; @@ -319,8 +321,8 @@ THREE.MeshPhongMaterial=function(a){THREE.Material.call(this);this.type="MeshPho THREE.MeshPhongMaterial.prototype.clone=function(){var a=new THREE.MeshPhongMaterial;THREE.Material.prototype.clone.call(this,a);a.color.copy(this.color);a.emissive.copy(this.emissive);a.specular.copy(this.specular);a.shininess=this.shininess;a.metal=this.metal;a.wrapAround=this.wrapAround;a.wrapRGB.copy(this.wrapRGB);a.map=this.map;a.lightMap=this.lightMap;a.bumpMap=this.bumpMap;a.bumpScale=this.bumpScale;a.normalMap=this.normalMap;a.normalScale.copy(this.normalScale);a.specularMap=this.specularMap; a.alphaMap=this.alphaMap;a.envMap=this.envMap;a.combine=this.combine;a.reflectivity=this.reflectivity;a.refractionRatio=this.refractionRatio;a.fog=this.fog;a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;a.wireframeLinecap=this.wireframeLinecap;a.wireframeLinejoin=this.wireframeLinejoin;a.vertexColors=this.vertexColors;a.skinning=this.skinning;a.morphTargets=this.morphTargets;a.morphNormals=this.morphNormals;return a}; THREE.MeshDepthMaterial=function(a){THREE.Material.call(this);this.type="MeshDepthMaterial";this.wireframe=this.morphTargets=!1;this.wireframeLinewidth=1;this.setValues(a)};THREE.MeshDepthMaterial.prototype=Object.create(THREE.Material.prototype);THREE.MeshDepthMaterial.prototype.constructor=THREE.MeshDepthMaterial; -THREE.MeshDepthMaterial.prototype.clone=function(){var a=new THREE.MeshDepthMaterial;THREE.Material.prototype.clone.call(this,a);a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};THREE.MeshNormalMaterial=function(a){THREE.Material.call(this,a);this.type="MeshNormalMaterial";this.shading=THREE.FlatShading;this.wireframe=!1;this.wireframeLinewidth=1;this.morphTargets=!1;this.setValues(a)};THREE.MeshNormalMaterial.prototype=Object.create(THREE.Material.prototype); -THREE.MeshNormalMaterial.prototype.constructor=THREE.MeshNormalMaterial;THREE.MeshNormalMaterial.prototype.clone=function(){var a=new THREE.MeshNormalMaterial;THREE.Material.prototype.clone.call(this,a);a.shading=this.shading;a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};THREE.MeshFaceMaterial=function(a){this.uuid=THREE.Math.generateUUID();this.type="MeshFaceMaterial";this.materials=a instanceof Array?a:[]}; +THREE.MeshDepthMaterial.prototype.clone=function(){var a=new THREE.MeshDepthMaterial;THREE.Material.prototype.clone.call(this,a);a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};THREE.MeshNormalMaterial=function(a){THREE.Material.call(this,a);this.type="MeshNormalMaterial";this.wireframe=!1;this.wireframeLinewidth=1;this.morphTargets=!1;this.setValues(a)};THREE.MeshNormalMaterial.prototype=Object.create(THREE.Material.prototype); +THREE.MeshNormalMaterial.prototype.constructor=THREE.MeshNormalMaterial;THREE.MeshNormalMaterial.prototype.clone=function(){var a=new THREE.MeshNormalMaterial;THREE.Material.prototype.clone.call(this,a);a.wireframe=this.wireframe;a.wireframeLinewidth=this.wireframeLinewidth;return a};THREE.MeshFaceMaterial=function(a){this.uuid=THREE.Math.generateUUID();this.type="MeshFaceMaterial";this.materials=a instanceof Array?a:[]}; THREE.MeshFaceMaterial.prototype={constructor:THREE.MeshFaceMaterial,toJSON:function(){for(var a={metadata:{version:4.2,type:"material",generator:"MaterialExporter"},uuid:this.uuid,type:this.type,materials:[]},b=0,c=this.materials.length;bf||(F=b.origin.distanceTo(p),Fd.far||e.push({distance:F,point:l.clone().applyMatrix4(this.matrixWorld),index:g,offsetIndex:r,face:null,faceIndex:null, -object:this}))}}else for(n=n.position.array,g=0;gf||(F=b.origin.distanceTo(p),Fd.far||e.push({distance:F,point:l.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}else if(g instanceof THREE.Geometry)for(h=g.vertices,k=h.length,g=0;gf||(F=b.origin.distanceTo(p),Fd.far||e.push({distance:F,point:l.clone().applyMatrix4(this.matrixWorld), +THREE.BufferGeometry){var n=g.attributes;if(void 0!==n.index){var t=n.index.array,n=n.position.array,s=g.offsets;0===s.length&&(s=[{start:0,count:t.length,index:0}]);for(var r=0;rf||(D=b.origin.distanceTo(p),Dd.far||e.push({distance:D,point:l.clone().applyMatrix4(this.matrixWorld),index:g,offsetIndex:r,face:null,faceIndex:null, +object:this}))}}else for(n=n.position.array,g=0;gf||(D=b.origin.distanceTo(p),Dd.far||e.push({distance:D,point:l.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this}))}else if(g instanceof THREE.Geometry)for(h=g.vertices,k=h.length,g=0;gf||(D=b.origin.distanceTo(p),Dd.far||e.push({distance:D,point:l.clone().applyMatrix4(this.matrixWorld), index:g,face:null,faceIndex:null,object:this}))}}}();THREE.Line.prototype.clone=function(a){void 0===a&&(a=new THREE.Line(this.geometry,this.material,this.mode));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.type="Mesh";this.geometry=void 0!==a?a:new THREE.Geometry;this.material=void 0!==b?b:new THREE.MeshBasicMaterial({color:16777215*Math.random()});this.updateMorphTargets()};THREE.Mesh.prototype=Object.create(THREE.Object3D.prototype); THREE.Mesh.prototype.constructor=THREE.Mesh;THREE.Mesh.prototype.updateMorphTargets=function(){if(void 0!==this.geometry.morphTargets&&0g.far||h.push({distance:A,point:y,face:new THREE.Face3(p,q,n,THREE.Triangle.normal(d,e,f)),faceIndex:null,object:this})}}}else for(r=p.position.array,s=k=0,w=r.length;k -g.far||h.push({distance:A,point:y,face:new THREE.Face3(p,q,n,THREE.Triangle.normal(d,e,f)),faceIndex:null,object:this}))}}else if(k instanceof THREE.Geometry)for(s=this.material instanceof THREE.MeshFaceMaterial,r=!0===s?this.material.materials:null,t=g.precision,u=k.vertices,v=0,x=k.faces.length;vg.far||h.push({distance:A,point:y,face:F,faceIndex:v,object:this}))}}}();THREE.Mesh.prototype.clone=function(a,b){void 0===a&&(a=new THREE.Mesh(this.geometry,this.material));THREE.Object3D.prototype.clone.call(this,a,b);return a};THREE.Bone=function(a){THREE.Object3D.call(this);this.type="Bone";this.skin=a};THREE.Bone.prototype=Object.create(THREE.Object3D.prototype);THREE.Bone.prototype.constructor=THREE.Bone; +g.far||h.push({distance:A,point:y,face:new THREE.Face3(p,q,n,THREE.Triangle.normal(d,e,f)),faceIndex:null,object:this}))}}else if(k instanceof THREE.Geometry)for(s=this.material instanceof THREE.MeshFaceMaterial,r=!0===s?this.material.materials:null,t=g.precision,u=k.vertices,v=0,x=k.faces.length;vg.far||h.push({distance:A,point:y,face:D,faceIndex:v,object:this}))}}}();THREE.Mesh.prototype.clone=function(a,b){void 0===a&&(a=new THREE.Mesh(this.geometry,this.material));THREE.Object3D.prototype.clone.call(this,a,b);return a};THREE.Bone=function(a){THREE.Object3D.call(this);this.type="Bone";this.skin=a};THREE.Bone.prototype=Object.create(THREE.Object3D.prototype);THREE.Bone.prototype.constructor=THREE.Bone; THREE.Skeleton=function(a,b,c){this.useVertexTexture=void 0!==c?c:!0;this.identityMatrix=new THREE.Matrix4;a=a||[];this.bones=a.slice(0);this.useVertexTexture?(this.boneTextureHeight=this.boneTextureWidth=a=256 dashSize ) {\n\t\tdiscard;\n\t}\n\tgl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.logdepthbuf_fragment, -THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3},opacity:{type:"f",value:1}},vertexShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float mNear;\nuniform float mFar;\nuniform float opacity;", -THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {",THREE.ShaderChunk.logdepthbuf_fragment,"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tfloat depth = gl_FragDepthEXT / gl_FragCoord.w;\n\t#else\n\t\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n\t#endif\n\tfloat color = 1.0 - smoothstep( mNear, mFar, depth );\n\tgl_FragColor = vec4( vec3( color ), opacity );\n}"].join("\n")},normal:{uniforms:{opacity:{type:"f",value:1}},vertexShader:["varying vec3 vNormal;",THREE.ShaderChunk.common, -THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvNormal = normalize( normalMatrix * normal );",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float opacity;\nvarying vec3 vNormal;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",THREE.ShaderChunk.logdepthbuf_fragment, -"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:["varying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;", -THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},equirect:{uniforms:{tEquirect:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:["varying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", -THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\nvec3 direction = normalize( vWorldPosition );\nvec2 sampleUV;\nsampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\nsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\ngl_FragColor = texture2D( tEquirect, sampleUV );",THREE.ShaderChunk.logdepthbuf_fragment, -"}"].join("\n")},depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"vec4 pack_depth( const in float depth ) {\n\tconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\n\tconst vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\n\tvec4 res = mod( depth * bit_shift * vec4( 255 ), vec4( 256 ) ) / vec4( 255 );\n\tres -= res.xxyz * bit_mask;\n\treturn res;\n}\nvoid main() {", -THREE.ShaderChunk.logdepthbuf_fragment,"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragDepthEXT );\n\t#else\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n\t#endif\n}"].join("\n")}}; +shininess:{type:"f",value:30},wrapRGB:{type:"v3",value:new THREE.Vector3(1,1,1)}}]),vertexShader:["#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif",THREE.ShaderChunk.common,THREE.ShaderChunk.map_pars_vertex,THREE.ShaderChunk.lightmap_pars_vertex,THREE.ShaderChunk.envmap_pars_vertex,THREE.ShaderChunk.lights_phong_pars_vertex,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex, +THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.map_vertex,THREE.ShaderChunk.lightmap_vertex,THREE.ShaderChunk.color_vertex,THREE.ShaderChunk.morphnormal_vertex,THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.skinnormal_vertex,THREE.ShaderChunk.defaultnormal_vertex,"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex, +"\tvViewPosition = -mvPosition.xyz;",THREE.ShaderChunk.worldpos_vertex,THREE.ShaderChunk.envmap_vertex,THREE.ShaderChunk.lights_phong_vertex,THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["#define PHONG\nuniform vec3 diffuse;\nuniform float opacity;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;",THREE.ShaderChunk.common,THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_pars_fragment,THREE.ShaderChunk.alphamap_pars_fragment,THREE.ShaderChunk.lightmap_pars_fragment, +THREE.ShaderChunk.envmap_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.lights_phong_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.bumpmap_pars_fragment,THREE.ShaderChunk.normalmap_pars_fragment,THREE.ShaderChunk.specularmap_pars_fragment,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = vec4( vec3( 1.0 ), opacity );",THREE.ShaderChunk.logdepthbuf_fragment,THREE.ShaderChunk.map_fragment,THREE.ShaderChunk.alphamap_fragment, +THREE.ShaderChunk.alphatest_fragment,THREE.ShaderChunk.specularmap_fragment,THREE.ShaderChunk.lights_phong_fragment,THREE.ShaderChunk.lightmap_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.envmap_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.linear_to_gamma_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},particle_basic:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.particle,THREE.UniformsLib.shadowmap]),vertexShader:["uniform float size;\nuniform float scale;", +THREE.ShaderChunk.common,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.shadowmap_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.color_vertex,"\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / length( mvPosition.xyz ) );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\tgl_Position = projectionMatrix * mvPosition;",THREE.ShaderChunk.logdepthbuf_vertex,THREE.ShaderChunk.worldpos_vertex, +THREE.ShaderChunk.shadowmap_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 psColor;\nuniform float opacity;",THREE.ShaderChunk.common,THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.map_particle_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.shadowmap_pars_fragment,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = vec4( psColor, opacity );",THREE.ShaderChunk.logdepthbuf_fragment,THREE.ShaderChunk.map_particle_fragment,THREE.ShaderChunk.alphatest_fragment, +THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.shadowmap_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},dashed:{uniforms:THREE.UniformsUtils.merge([THREE.UniformsLib.common,THREE.UniformsLib.fog,{scale:{type:"f",value:1},dashSize:{type:"f",value:1},totalSize:{type:"f",value:2}}]),vertexShader:["uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;",THREE.ShaderChunk.common,THREE.ShaderChunk.color_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {", +THREE.ShaderChunk.color_vertex,"\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;",THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;",THREE.ShaderChunk.common,THREE.ShaderChunk.color_pars_fragment,THREE.ShaderChunk.fog_pars_fragment,THREE.ShaderChunk.logdepthbuf_pars_fragment, +"void main() {\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tgl_FragColor = vec4( diffuse, opacity );",THREE.ShaderChunk.logdepthbuf_fragment,THREE.ShaderChunk.color_fragment,THREE.ShaderChunk.fog_fragment,"}"].join("\n")},depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3},opacity:{type:"f",value:1}},vertexShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.morphtarget_vertex, +THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float mNear;\nuniform float mFar;\nuniform float opacity;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {",THREE.ShaderChunk.logdepthbuf_fragment,"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tfloat depth = gl_FragDepthEXT / gl_FragCoord.w;\n\t#else\n\t\tfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n\t#endif\n\tfloat color = 1.0 - smoothstep( mNear, mFar, depth );\n\tgl_FragColor = vec4( vec3( color ), opacity );\n}"].join("\n")}, +normal:{uniforms:{opacity:{type:"f",value:1}},vertexShader:["varying vec3 vNormal;",THREE.ShaderChunk.common,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvNormal = normalize( normalMatrix * normal );",THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform float opacity;\nvarying vec3 vNormal;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment, +"void main() {\n\tgl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},cube:{uniforms:{tCube:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:["varying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",THREE.ShaderChunk.logdepthbuf_vertex, +"}"].join("\n"),fragmentShader:["uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );",THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},equirect:{uniforms:{tEquirect:{type:"t",value:null},tFlip:{type:"f",value:-1}},vertexShader:["varying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_vertex, +"void main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:["uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;",THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment,"void main() {\nvec3 direction = normalize( vWorldPosition );\nvec2 sampleUV;\nsampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\nsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\ngl_FragColor = texture2D( tEquirect, sampleUV );", +THREE.ShaderChunk.logdepthbuf_fragment,"}"].join("\n")},depthRGBA:{uniforms:{},vertexShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.morphtarget_pars_vertex,THREE.ShaderChunk.skinning_pars_vertex,THREE.ShaderChunk.logdepthbuf_pars_vertex,"void main() {",THREE.ShaderChunk.skinbase_vertex,THREE.ShaderChunk.morphtarget_vertex,THREE.ShaderChunk.skinning_vertex,THREE.ShaderChunk.default_vertex,THREE.ShaderChunk.logdepthbuf_vertex,"}"].join("\n"),fragmentShader:[THREE.ShaderChunk.common,THREE.ShaderChunk.logdepthbuf_pars_fragment, +"vec4 pack_depth( const in float depth ) {\n\tconst vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );\n\tconst vec4 bit_mask = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );\n\tvec4 res = mod( depth * bit_shift * vec4( 255 ), vec4( 256 ) ) / vec4( 255 );\n\tres -= res.xxyz * bit_mask;\n\treturn res;\n}\nvoid main() {",THREE.ShaderChunk.logdepthbuf_fragment,"\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragDepthEXT );\n\t#else\n\t\tgl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );\n\t#endif\n}"].join("\n")}}; THREE.WebGLRenderer=function(a){function b(a){var b=a.geometry;a=a.material;var c=b.vertices.length;if(a.attributes){void 0===b.__webglCustomAttributesList&&(b.__webglCustomAttributesList=[]);for(var d in a.attributes){var e=a.attributes[d];if(!e.__webglInitialized||e.createUniqueBuffers){e.__webglInitialized=!0;var f=1;"v2"===e.type?f=2:"v3"===e.type?f=3:"v4"===e.type?f=4:"c"===e.type&&(f=3);e.size=f;e.array=new Float32Array(c*f);e.buffer=m.createBuffer();e.buffer.belongsToAttribute=d;e.needsUpdate= !0}b.__webglCustomAttributesList.push(e)}}}function c(a,b){return a.material instanceof THREE.MeshFaceMaterial?a.material.materials[b.materialIndex]:a.material}function d(a,b,c,d){c=c.attributes;var e=b.attributes;b=b.attributesKeys;for(var f=0,g=b.length;fh&&(e[v].counter+=1,k=e[v].hash+"_"+e[v].counter,k in r||(q={id:Qb++,faces3:[],materialIndex:v,vertices:0,numMorphTargets:l,numMorphNormals:p},r[k]=q,t.push(q))); -r[k].faces3.push(s);r[k].vertices+=3}f[g]=t;b.groupsNeedUpdate=!1}f=Ua[b.id];g=0;for(d=f.length;gY;Y++)pa=I[Y],Na[Ra]=pa.x,Na[Ra+1]=pa.y,Na[Ra+2]=pa.z,Ra+=3;else for(Y=0;3>Y;Y++)Na[Ra]=H.x,Na[Ra+1]=H.y,Na[Ra+2]=H.z,Ra+=3;m.bindBuffer(m.ARRAY_BUFFER, -w.__webglNormalBuffer);m.bufferData(m.ARRAY_BUFFER,Na,x)}if(vb&&Hb){y=0;for(z=$.length;yY;Y++)ab=U[Y],Ab[kb]=ab.x,Ab[kb+1]=ab.y,kb+=2;0Y;Y++)oa=O[Y],lb[yb]=oa.x,lb[yb+1]=oa.y,yb+=2;0ya;ya++)gb[ya]=!B.autoScaleCubemaps||Rb||Ib?Ib?X.image[ya].image:X.image[ya]:E(X.image[ya],qc);var Yb=gb[0],Zb=THREE.Math.isPowerOfTwo(Yb.width)&&THREE.Math.isPowerOfTwo(Yb.height),Wa=I(X.format),tb=I(X.type);A(m.TEXTURE_CUBE_MAP,X,Zb);for(ya=0;6>ya;ya++)if(Rb)for(var hb,$b=gb[ya].mipmaps,Fb= -0,Sb=$b.length;Fb=Wb&&THREE.warn("WebGLRenderer: trying to use "+a+" texture units while this GPU supports only "+Wb);Mb+=1;return a}function w(a,b){a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getNormalMatrix(a._modelViewMatrix)}function y(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}function A(a,b,c){c?(m.texParameteri(a,m.TEXTURE_WRAP_S,I(b.wrapS)),m.texParameteri(a,m.TEXTURE_WRAP_T,I(b.wrapT)),m.texParameteri(a, -m.TEXTURE_MAG_FILTER,I(b.magFilter)),m.texParameteri(a,m.TEXTURE_MIN_FILTER,I(b.minFilter))):(m.texParameteri(a,m.TEXTURE_WRAP_S,m.CLAMP_TO_EDGE),m.texParameteri(a,m.TEXTURE_WRAP_T,m.CLAMP_TO_EDGE),b.wrapS===THREE.ClampToEdgeWrapping&&b.wrapT===THREE.ClampToEdgeWrapping||THREE.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping. ( "+b.sourceFile+" )"),m.texParameteri(a,m.TEXTURE_MAG_FILTER,D(b.magFilter)),m.texParameteri(a, -m.TEXTURE_MIN_FILTER,D(b.minFilter)),b.minFilter!==THREE.NearestFilter&&b.minFilter!==THREE.LinearFilter&&THREE.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter. ( "+b.sourceFile+" )"));(c=da.get("EXT_texture_filter_anisotropic"))&&b.type!==THREE.FloatType&&b.type!==THREE.HalfFloatType&&(1b||a.height>b){var c=b/Math.max(a.width,a.height),d=document.createElement("canvas");d.width=Math.floor(a.width*c);d.height=Math.floor(a.height*c);d.getContext("2d").drawImage(a,0,0,a.width,a.height,0,0,d.width,d.height);THREE.warn("THREE.WebGLRenderer: image is too big ("+a.width+"x"+a.height+"). Resized to "+d.width+"x"+d.height,a);return d}return a}function G(a,b){m.bindRenderbuffer(m.RENDERBUFFER,a);b.depthBuffer&&!b.stencilBuffer? -(m.renderbufferStorage(m.RENDERBUFFER,m.DEPTH_COMPONENT16,b.width,b.height),m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a)):b.depthBuffer&&b.stencilBuffer?(m.renderbufferStorage(m.RENDERBUFFER,m.DEPTH_STENCIL,b.width,b.height),m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a)):m.renderbufferStorage(m.RENDERBUFFER,m.RGBA4,b.width,b.height)}function z(a){a instanceof THREE.WebGLRenderTargetCube?(m.bindTexture(m.TEXTURE_CUBE_MAP,a.__webglTexture), -m.generateMipmap(m.TEXTURE_CUBE_MAP),m.bindTexture(m.TEXTURE_CUBE_MAP,null)):(m.bindTexture(m.TEXTURE_2D,a.__webglTexture),m.generateMipmap(m.TEXTURE_2D),m.bindTexture(m.TEXTURE_2D,null))}function D(a){return a===THREE.NearestFilter||a===THREE.NearestMipMapNearestFilter||a===THREE.NearestMipMapLinearFilter?m.NEAREST:m.LINEAR}function I(a){var b;if(a===THREE.RepeatWrapping)return m.REPEAT;if(a===THREE.ClampToEdgeWrapping)return m.CLAMP_TO_EDGE;if(a===THREE.MirroredRepeatWrapping)return m.MIRRORED_REPEAT; -if(a===THREE.NearestFilter)return m.NEAREST;if(a===THREE.NearestMipMapNearestFilter)return m.NEAREST_MIPMAP_NEAREST;if(a===THREE.NearestMipMapLinearFilter)return m.NEAREST_MIPMAP_LINEAR;if(a===THREE.LinearFilter)return m.LINEAR;if(a===THREE.LinearMipMapNearestFilter)return m.LINEAR_MIPMAP_NEAREST;if(a===THREE.LinearMipMapLinearFilter)return m.LINEAR_MIPMAP_LINEAR;if(a===THREE.UnsignedByteType)return m.UNSIGNED_BYTE;if(a===THREE.UnsignedShort4444Type)return m.UNSIGNED_SHORT_4_4_4_4;if(a===THREE.UnsignedShort5551Type)return m.UNSIGNED_SHORT_5_5_5_1; -if(a===THREE.UnsignedShort565Type)return m.UNSIGNED_SHORT_5_6_5;if(a===THREE.ByteType)return m.BYTE;if(a===THREE.ShortType)return m.SHORT;if(a===THREE.UnsignedShortType)return m.UNSIGNED_SHORT;if(a===THREE.IntType)return m.INT;if(a===THREE.UnsignedIntType)return m.UNSIGNED_INT;if(a===THREE.FloatType)return m.FLOAT;b=da.get("OES_texture_half_float");if(null!==b&&a===THREE.HalfFloatType)return b.HALF_FLOAT_OES;if(a===THREE.AlphaFormat)return m.ALPHA;if(a===THREE.RGBFormat)return m.RGB;if(a===THREE.RGBAFormat)return m.RGBA; -if(a===THREE.LuminanceFormat)return m.LUMINANCE;if(a===THREE.LuminanceAlphaFormat)return m.LUMINANCE_ALPHA;if(a===THREE.AddEquation)return m.FUNC_ADD;if(a===THREE.SubtractEquation)return m.FUNC_SUBTRACT;if(a===THREE.ReverseSubtractEquation)return m.FUNC_REVERSE_SUBTRACT;if(a===THREE.ZeroFactor)return m.ZERO;if(a===THREE.OneFactor)return m.ONE;if(a===THREE.SrcColorFactor)return m.SRC_COLOR;if(a===THREE.OneMinusSrcColorFactor)return m.ONE_MINUS_SRC_COLOR;if(a===THREE.SrcAlphaFactor)return m.SRC_ALPHA; -if(a===THREE.OneMinusSrcAlphaFactor)return m.ONE_MINUS_SRC_ALPHA;if(a===THREE.DstAlphaFactor)return m.DST_ALPHA;if(a===THREE.OneMinusDstAlphaFactor)return m.ONE_MINUS_DST_ALPHA;if(a===THREE.DstColorFactor)return m.DST_COLOR;if(a===THREE.OneMinusDstColorFactor)return m.ONE_MINUS_DST_COLOR;if(a===THREE.SrcAlphaSaturateFactor)return m.SRC_ALPHA_SATURATE;b=da.get("WEBGL_compressed_texture_s3tc");if(null!==b){if(a===THREE.RGB_S3TC_DXT1_Format)return b.COMPRESSED_RGB_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT1_Format)return b.COMPRESSED_RGBA_S3TC_DXT1_EXT; -if(a===THREE.RGBA_S3TC_DXT3_Format)return b.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(a===THREE.RGBA_S3TC_DXT5_Format)return b.COMPRESSED_RGBA_S3TC_DXT5_EXT}b=da.get("WEBGL_compressed_texture_pvrtc");if(null!==b){if(a===THREE.RGB_PVRTC_4BPPV1_Format)return b.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(a===THREE.RGB_PVRTC_2BPPV1_Format)return b.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(a===THREE.RGBA_PVRTC_4BPPV1_Format)return b.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(a===THREE.RGBA_PVRTC_2BPPV1_Format)return b.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}b= -da.get("EXT_blend_minmax");if(null!==b){if(a===THREE.MinEquation)return b.MIN_EXT;if(a===THREE.MaxEquation)return b.MAX_EXT}return 0}console.log("THREE.WebGLRenderer",THREE.REVISION);a=a||{};var U=void 0!==a.canvas?a.canvas:document.createElement("canvas"),M=void 0!==a.context?a.context:null,H=1,L=void 0!==a.precision?a.precision:"highp",P=void 0!==a.alpha?a.alpha:!1,N=void 0!==a.depth?a.depth:!0,R=void 0!==a.stencil?a.stencil:!0,V=void 0!==a.antialias?a.antialias:!1,J=void 0!==a.premultipliedAlpha? -a.premultipliedAlpha:!0,oa=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,ja=void 0!==a.logarithmicDepthBuffer?a.logarithmicDepthBuffer:!1,ha=new THREE.Color(0),O=0,ca=[],ba={},qa=[],Ka=[],Qa=[],Xa=[],Ya=[];this.domElement=U;this.context=null;this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.gammaFactor=2;this.shadowMapEnabled=this.gammaOutput=this.gammaInput=!1;this.shadowMapType=THREE.PCFShadowMap;this.shadowMapCullFace=THREE.CullFaceFront; -this.shadowMapCascade=this.shadowMapDebug=!1;this.maxMorphTargets=8;this.maxMorphNormals=4;this.autoScaleCubemaps=!0;this.info={memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}};var B=this,Pa=[],ob=null,ab=null,ub=-1,ta="",vb=null,Mb=0,ib=0,bb=0,pb=U.width,qb=U.height,Xb=0,fc=0,cb=new THREE.Frustum,db=new THREE.Matrix4;new THREE.Matrix4;var wa=new THREE.Vector3,pa=new THREE.Vector3,Ob=!0,jc={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0, -colors:[],positions:[],distances:[],decays:[]},spot:{length:0,colors:[],positions:[],distances:[],directions:[],anglesCos:[],exponents:[],decays:[]},hemi:{length:0,skyColors:[],groundColors:[],positions:[]}},m;try{var Yb={alpha:P,depth:N,stencil:R,antialias:V,premultipliedAlpha:J,preserveDrawingBuffer:oa};m=M||U.getContext("webgl",Yb)||U.getContext("experimental-webgl",Yb);if(null===m){if(null!==U.getContext("webgl"))throw"Error creating WebGL context with your selected attributes.";throw"Error creating WebGL context."; -}U.addEventListener("webglcontextlost",function(a){a.preventDefault();Zb();lc();ba={}},!1)}catch(rc){THREE.error("THREE.WebGLRenderer: "+rc)}var W=new THREE.WebGLState(m,I);void 0===m.getShaderPrecisionFormat&&(m.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}});var da=new THREE.WebGLExtensions(m);da.get("OES_texture_float");da.get("OES_texture_float_linear");da.get("OES_texture_half_float");da.get("OES_texture_half_float_linear");da.get("OES_standard_derivatives");ja&& -da.get("EXT_frag_depth");var rb=function(a,b,c,d){!0===J&&(a*=d,b*=d,c*=d);m.clearColor(a,b,c,d)},lc=function(){m.clearColor(0,0,0,1);m.clearDepth(1);m.clearStencil(0);m.enable(m.DEPTH_TEST);m.depthFunc(m.LEQUAL);m.frontFace(m.CCW);m.cullFace(m.BACK);m.enable(m.CULL_FACE);m.enable(m.BLEND);m.blendEquation(m.FUNC_ADD);m.blendFunc(m.SRC_ALPHA,m.ONE_MINUS_SRC_ALPHA);m.viewport(ib,bb,pb,qb);rb(ha.r,ha.g,ha.b,O)},Zb=function(){vb=ob=null;ta="";ub=-1;Ob=!0;W.reset()};lc();this.context=m;this.state=W;var Wb= -m.getParameter(m.MAX_TEXTURE_IMAGE_UNITS),sc=m.getParameter(m.MAX_VERTEX_TEXTURE_IMAGE_UNITS),tc=m.getParameter(m.MAX_TEXTURE_SIZE),qc=m.getParameter(m.MAX_CUBE_MAP_TEXTURE_SIZE),Vb=0h&&(e[u].counter+=1,k=e[u].hash+"_"+e[u].counter,k in r||(q={id:Qb++,faces3:[],materialIndex:u,vertices:0, +numMorphTargets:l,numMorphNormals:p},r[k]=q,t.push(q)));r[k].faces3.push(s);r[k].vertices+=3}f[g]=t;b.groupsNeedUpdate=!1}f=Ua[b.id];g=0;for(d=f.length;gY;Y++)pa=I[Y],Na[Ra]=pa.x,Na[Ra+1]= +pa.y,Na[Ra+2]=pa.z,Ra+=3;else for(Y=0;3>Y;Y++)Na[Ra]=H.x,Na[Ra+1]=H.y,Na[Ra+2]=H.z,Ra+=3;m.bindBuffer(m.ARRAY_BUFFER,v.__webglNormalBuffer);m.bufferData(m.ARRAY_BUFFER,Na,D)}if(vb&&Hb){y=0;for(z=$.length;yY;Y++)ab=U[Y],Ab[kb]=ab.x,Ab[kb+1]=ab.y,kb+=2;0Y;Y++)oa=O[Y],lb[yb]=oa.x,lb[yb+1]=oa.y, +yb+=2;0ya;ya++)gb[ya]=!B.autoScaleCubemaps||Rb||Ib?Ib? +X.image[ya].image:X.image[ya]:E(X.image[ya],qc);var Yb=gb[0],Zb=THREE.Math.isPowerOfTwo(Yb.width)&&THREE.Math.isPowerOfTwo(Yb.height),Wa=I(X.format),tb=I(X.type);A(m.TEXTURE_CUBE_MAP,X,Zb);for(ya=0;6>ya;ya++)if(Rb)for(var hb,$b=gb[ya].mipmaps,Fb=0,Sb=$b.length;Fb=Wb&&THREE.warn("WebGLRenderer: trying to use "+a+" texture units while this GPU supports only "+Wb);Mb+=1;return a}function w(a,b){a._modelViewMatrix.multiplyMatrices(b.matrixWorldInverse,a.matrixWorld);a._normalMatrix.getNormalMatrix(a._modelViewMatrix)} +function y(a,b,c,d){a[b]=c.r*d;a[b+1]=c.g*d;a[b+2]=c.b*d}function A(a,b,c){c?(m.texParameteri(a,m.TEXTURE_WRAP_S,I(b.wrapS)),m.texParameteri(a,m.TEXTURE_WRAP_T,I(b.wrapT)),m.texParameteri(a,m.TEXTURE_MAG_FILTER,I(b.magFilter)),m.texParameteri(a,m.TEXTURE_MIN_FILTER,I(b.minFilter))):(m.texParameteri(a,m.TEXTURE_WRAP_S,m.CLAMP_TO_EDGE),m.texParameteri(a,m.TEXTURE_WRAP_T,m.CLAMP_TO_EDGE),b.wrapS===THREE.ClampToEdgeWrapping&&b.wrapT===THREE.ClampToEdgeWrapping||THREE.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping. ( "+ +b.sourceFile+" )"),m.texParameteri(a,m.TEXTURE_MAG_FILTER,z(b.magFilter)),m.texParameteri(a,m.TEXTURE_MIN_FILTER,z(b.minFilter)),b.minFilter!==THREE.NearestFilter&&b.minFilter!==THREE.LinearFilter&&THREE.warn("THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter. ( "+b.sourceFile+" )"));(c=da.get("EXT_texture_filter_anisotropic"))&&b.type!==THREE.FloatType&&b.type!==THREE.HalfFloatType&&(1b||a.height>b){var c=b/Math.max(a.width,a.height),d=document.createElement("canvas");d.width=Math.floor(a.width*c);d.height=Math.floor(a.height*c);d.getContext("2d").drawImage(a,0,0,a.width,a.height,0,0,d.width,d.height);THREE.warn("THREE.WebGLRenderer: image is too big ("+a.width+"x"+a.height+"). Resized to "+d.width+"x"+d.height,a);return d}return a} +function G(a,b){m.bindRenderbuffer(m.RENDERBUFFER,a);b.depthBuffer&&!b.stencilBuffer?(m.renderbufferStorage(m.RENDERBUFFER,m.DEPTH_COMPONENT16,b.width,b.height),m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a)):b.depthBuffer&&b.stencilBuffer?(m.renderbufferStorage(m.RENDERBUFFER,m.DEPTH_STENCIL,b.width,b.height),m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a)):m.renderbufferStorage(m.RENDERBUFFER,m.RGBA4,b.width,b.height)}function F(a){a instanceof +THREE.WebGLRenderTargetCube?(m.bindTexture(m.TEXTURE_CUBE_MAP,a.__webglTexture),m.generateMipmap(m.TEXTURE_CUBE_MAP),m.bindTexture(m.TEXTURE_CUBE_MAP,null)):(m.bindTexture(m.TEXTURE_2D,a.__webglTexture),m.generateMipmap(m.TEXTURE_2D),m.bindTexture(m.TEXTURE_2D,null))}function z(a){return a===THREE.NearestFilter||a===THREE.NearestMipMapNearestFilter||a===THREE.NearestMipMapLinearFilter?m.NEAREST:m.LINEAR}function I(a){var b;if(a===THREE.RepeatWrapping)return m.REPEAT;if(a===THREE.ClampToEdgeWrapping)return m.CLAMP_TO_EDGE; +if(a===THREE.MirroredRepeatWrapping)return m.MIRRORED_REPEAT;if(a===THREE.NearestFilter)return m.NEAREST;if(a===THREE.NearestMipMapNearestFilter)return m.NEAREST_MIPMAP_NEAREST;if(a===THREE.NearestMipMapLinearFilter)return m.NEAREST_MIPMAP_LINEAR;if(a===THREE.LinearFilter)return m.LINEAR;if(a===THREE.LinearMipMapNearestFilter)return m.LINEAR_MIPMAP_NEAREST;if(a===THREE.LinearMipMapLinearFilter)return m.LINEAR_MIPMAP_LINEAR;if(a===THREE.UnsignedByteType)return m.UNSIGNED_BYTE;if(a===THREE.UnsignedShort4444Type)return m.UNSIGNED_SHORT_4_4_4_4; +if(a===THREE.UnsignedShort5551Type)return m.UNSIGNED_SHORT_5_5_5_1;if(a===THREE.UnsignedShort565Type)return m.UNSIGNED_SHORT_5_6_5;if(a===THREE.ByteType)return m.BYTE;if(a===THREE.ShortType)return m.SHORT;if(a===THREE.UnsignedShortType)return m.UNSIGNED_SHORT;if(a===THREE.IntType)return m.INT;if(a===THREE.UnsignedIntType)return m.UNSIGNED_INT;if(a===THREE.FloatType)return m.FLOAT;b=da.get("OES_texture_half_float");if(null!==b&&a===THREE.HalfFloatType)return b.HALF_FLOAT_OES;if(a===THREE.AlphaFormat)return m.ALPHA; +if(a===THREE.RGBFormat)return m.RGB;if(a===THREE.RGBAFormat)return m.RGBA;if(a===THREE.LuminanceFormat)return m.LUMINANCE;if(a===THREE.LuminanceAlphaFormat)return m.LUMINANCE_ALPHA;if(a===THREE.AddEquation)return m.FUNC_ADD;if(a===THREE.SubtractEquation)return m.FUNC_SUBTRACT;if(a===THREE.ReverseSubtractEquation)return m.FUNC_REVERSE_SUBTRACT;if(a===THREE.ZeroFactor)return m.ZERO;if(a===THREE.OneFactor)return m.ONE;if(a===THREE.SrcColorFactor)return m.SRC_COLOR;if(a===THREE.OneMinusSrcColorFactor)return m.ONE_MINUS_SRC_COLOR; +if(a===THREE.SrcAlphaFactor)return m.SRC_ALPHA;if(a===THREE.OneMinusSrcAlphaFactor)return m.ONE_MINUS_SRC_ALPHA;if(a===THREE.DstAlphaFactor)return m.DST_ALPHA;if(a===THREE.OneMinusDstAlphaFactor)return m.ONE_MINUS_DST_ALPHA;if(a===THREE.DstColorFactor)return m.DST_COLOR;if(a===THREE.OneMinusDstColorFactor)return m.ONE_MINUS_DST_COLOR;if(a===THREE.SrcAlphaSaturateFactor)return m.SRC_ALPHA_SATURATE;b=da.get("WEBGL_compressed_texture_s3tc");if(null!==b){if(a===THREE.RGB_S3TC_DXT1_Format)return b.COMPRESSED_RGB_S3TC_DXT1_EXT; +if(a===THREE.RGBA_S3TC_DXT1_Format)return b.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(a===THREE.RGBA_S3TC_DXT3_Format)return b.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(a===THREE.RGBA_S3TC_DXT5_Format)return b.COMPRESSED_RGBA_S3TC_DXT5_EXT}b=da.get("WEBGL_compressed_texture_pvrtc");if(null!==b){if(a===THREE.RGB_PVRTC_4BPPV1_Format)return b.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(a===THREE.RGB_PVRTC_2BPPV1_Format)return b.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(a===THREE.RGBA_PVRTC_4BPPV1_Format)return b.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; +if(a===THREE.RGBA_PVRTC_2BPPV1_Format)return b.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}b=da.get("EXT_blend_minmax");if(null!==b){if(a===THREE.MinEquation)return b.MIN_EXT;if(a===THREE.MaxEquation)return b.MAX_EXT}return 0}console.log("THREE.WebGLRenderer",THREE.REVISION);a=a||{};var U=void 0!==a.canvas?a.canvas:document.createElement("canvas"),M=void 0!==a.context?a.context:null,H=1,L=void 0!==a.precision?a.precision:"highp",P=void 0!==a.alpha?a.alpha:!1,N=void 0!==a.depth?a.depth:!0,R=void 0!==a.stencil? +a.stencil:!0,V=void 0!==a.antialias?a.antialias:!1,J=void 0!==a.premultipliedAlpha?a.premultipliedAlpha:!0,oa=void 0!==a.preserveDrawingBuffer?a.preserveDrawingBuffer:!1,ja=void 0!==a.logarithmicDepthBuffer?a.logarithmicDepthBuffer:!1,ha=new THREE.Color(0),O=0,ca=[],ba={},qa=[],Ka=[],Qa=[],Xa=[],Ya=[];this.domElement=U;this.context=null;this.sortObjects=this.autoClearStencil=this.autoClearDepth=this.autoClearColor=this.autoClear=!0;this.gammaFactor=2;this.shadowMapEnabled=this.gammaOutput=this.gammaInput= +!1;this.shadowMapType=THREE.PCFShadowMap;this.shadowMapCullFace=THREE.CullFaceFront;this.shadowMapCascade=this.shadowMapDebug=!1;this.maxMorphTargets=8;this.maxMorphNormals=4;this.autoScaleCubemaps=!0;this.info={memory:{programs:0,geometries:0,textures:0},render:{calls:0,vertices:0,faces:0,points:0}};var B=this,Pa=[],ob=null,ab=null,ub=-1,ta="",vb=null,Mb=0,ib=0,bb=0,pb=U.width,qb=U.height,Xb=0,fc=0,cb=new THREE.Frustum,db=new THREE.Matrix4;new THREE.Matrix4;var wa=new THREE.Vector3,pa=new THREE.Vector3, +Ob=!0,jc={ambient:[0,0,0],directional:{length:0,colors:[],positions:[]},point:{length:0,colors:[],positions:[],distances:[],decays:[]},spot:{length:0,colors:[],positions:[],distances:[],directions:[],anglesCos:[],exponents:[],decays:[]},hemi:{length:0,skyColors:[],groundColors:[],positions:[]}},m;try{var Yb={alpha:P,depth:N,stencil:R,antialias:V,premultipliedAlpha:J,preserveDrawingBuffer:oa};m=M||U.getContext("webgl",Yb)||U.getContext("experimental-webgl",Yb);if(null===m){if(null!==U.getContext("webgl"))throw"Error creating WebGL context with your selected attributes."; +throw"Error creating WebGL context.";}U.addEventListener("webglcontextlost",function(a){a.preventDefault();Zb();lc();ba={}},!1)}catch(rc){THREE.error("THREE.WebGLRenderer: "+rc)}var W=new THREE.WebGLState(m,I);void 0===m.getShaderPrecisionFormat&&(m.getShaderPrecisionFormat=function(){return{rangeMin:1,rangeMax:1,precision:1}});var da=new THREE.WebGLExtensions(m);da.get("OES_texture_float");da.get("OES_texture_float_linear");da.get("OES_texture_half_float");da.get("OES_texture_half_float_linear"); +da.get("OES_standard_derivatives");ja&&da.get("EXT_frag_depth");var rb=function(a,b,c,d){!0===J&&(a*=d,b*=d,c*=d);m.clearColor(a,b,c,d)},lc=function(){m.clearColor(0,0,0,1);m.clearDepth(1);m.clearStencil(0);m.enable(m.DEPTH_TEST);m.depthFunc(m.LEQUAL);m.frontFace(m.CCW);m.cullFace(m.BACK);m.enable(m.CULL_FACE);m.enable(m.BLEND);m.blendEquation(m.FUNC_ADD);m.blendFunc(m.SRC_ALPHA,m.ONE_MINUS_SRC_ALPHA);m.viewport(ib,bb,pb,qb);rb(ha.r,ha.g,ha.b,O)},Zb=function(){vb=ob=null;ta="";ub=-1;Ob=!0;W.reset()}; +lc();this.context=m;this.state=W;var Wb=m.getParameter(m.MAX_TEXTURE_IMAGE_UNITS),sc=m.getParameter(m.MAX_VERTEX_TEXTURE_IMAGE_UNITS),tc=m.getParameter(m.MAX_TEXTURE_SIZE),qc=m.getParameter(m.MAX_CUBE_MAP_TEXTURE_SIZE),Vb=0h.length&&(console.warn("THREE.WebGLRenderer: Influences array is bigger than morphTargets array."),n.length=h.length);h=0;for(l=n.length;hd.numSupportedMorphTargets? -(k.sort(g),k.length=d.numSupportedMorphTargets):k.length>d.numSupportedMorphNormals?k.sort(g):0===k.length&&k.push([0,0]);for(var h=0,p=d.numSupportedMorphTargets;hf;f++){a.__webglFramebuffer[f]= -m.createFramebuffer();a.__webglRenderbuffer[f]=m.createRenderbuffer();m.texImage2D(m.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=m.TEXTURE_CUBE_MAP_POSITIVE_X+f;m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer[f]);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,h,g.__webglTexture,0);G(a.__webglRenderbuffer[f],a)}c&&m.generateMipmap(m.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=m.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer: -m.createRenderbuffer(),m.bindTexture(m.TEXTURE_2D,a.__webglTexture),A(m.TEXTURE_2D,a,c),m.texImage2D(m.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=m.TEXTURE_2D,m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,d,a.__webglTexture,0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&m.framebufferRenderbuffer(m.FRAMEBUFFER, -m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):G(a.__webglRenderbuffer,a),c&&m.generateMipmap(m.TEXTURE_2D);b?m.bindTexture(m.TEXTURE_CUBE_MAP,null):m.bindTexture(m.TEXTURE_2D,null);m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null)}a?(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=pb,a=qb,d=ib,e=bb);b!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,b),m.viewport(d,e,c,a),ab=b);Xb=c;fc=a};this.readRenderTargetPixels= -function(a,b,c,d,e,f){if(!(a instanceof THREE.WebGLRenderTarget))console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");else if(a.__webglFramebuffer)if(a.format!==THREE.RGBAFormat)console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format.");else{var g=!1;a.__webglFramebuffer!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),g=!0);m.checkFramebufferStatus(m.FRAMEBUFFER)=== -m.FRAMEBUFFER_COMPLETE?m.readPixels(b,c,d,e,m.RGBA,m.UNSIGNED_BYTE,f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.");g&&m.bindFramebuffer(m.FRAMEBUFFER,ab)}};this.initMaterial=function(){THREE.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")};this.addPrePlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")};this.addPostPlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")}; -this.updateShadowMap=function(){THREE.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")}}; +a.positionArray,m.DYNAMIC_DRAW),W.enableAttribute(b.attributes.position),m.vertexAttribPointer(b.attributes.position,3,m.FLOAT,!1,0,0));if(a.hasNormals){m.bindBuffer(m.ARRAY_BUFFER,a.__webglNormalBuffer);if(!1===c instanceof THREE.MeshPhongMaterial&&c.shading===THREE.FlatShading){var d,e,f,g,h,k,n,l,p,q,r,s=3*a.count;for(r=0;rh.length&&(console.warn("THREE.WebGLRenderer: Influences array is bigger than morphTargets array."), +n.length=h.length);h=0;for(l=n.length;hd.numSupportedMorphTargets?(k.sort(g),k.length=d.numSupportedMorphTargets):k.length>d.numSupportedMorphNormals?k.sort(g):0===k.length&&k.push([0,0]);for(var h=0,p=d.numSupportedMorphTargets;hf;f++){a.__webglFramebuffer[f]=m.createFramebuffer();a.__webglRenderbuffer[f]=m.createRenderbuffer();m.texImage2D(m.TEXTURE_CUBE_MAP_POSITIVE_X+f,0,d,a.width,a.height,0,d,e,null);var g=a,h=m.TEXTURE_CUBE_MAP_POSITIVE_X+f;m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer[f]);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0, +h,g.__webglTexture,0);G(a.__webglRenderbuffer[f],a)}c&&m.generateMipmap(m.TEXTURE_CUBE_MAP)}else a.__webglFramebuffer=m.createFramebuffer(),a.__webglRenderbuffer=a.shareDepthFrom?a.shareDepthFrom.__webglRenderbuffer:m.createRenderbuffer(),m.bindTexture(m.TEXTURE_2D,a.__webglTexture),A(m.TEXTURE_2D,a,c),m.texImage2D(m.TEXTURE_2D,0,d,a.width,a.height,0,d,e,null),d=m.TEXTURE_2D,m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,d,a.__webglTexture, +0),a.shareDepthFrom?a.depthBuffer&&!a.stencilBuffer?m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):a.depthBuffer&&a.stencilBuffer&&m.framebufferRenderbuffer(m.FRAMEBUFFER,m.DEPTH_STENCIL_ATTACHMENT,m.RENDERBUFFER,a.__webglRenderbuffer):G(a.__webglRenderbuffer,a),c&&m.generateMipmap(m.TEXTURE_2D);b?m.bindTexture(m.TEXTURE_CUBE_MAP,null):m.bindTexture(m.TEXTURE_2D,null);m.bindRenderbuffer(m.RENDERBUFFER,null);m.bindFramebuffer(m.FRAMEBUFFER,null)}a? +(b=b?a.__webglFramebuffer[a.activeCubeFace]:a.__webglFramebuffer,c=a.width,a=a.height,e=d=0):(b=null,c=pb,a=qb,d=ib,e=bb);b!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,b),m.viewport(d,e,c,a),ab=b);Xb=c;fc=a};this.readRenderTargetPixels=function(a,b,c,d,e,f){if(!(a instanceof THREE.WebGLRenderTarget))console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");else if(a.__webglFramebuffer)if(a.format!==THREE.RGBAFormat)console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA format. readPixels can read only RGBA format."); +else{var g=!1;a.__webglFramebuffer!==ab&&(m.bindFramebuffer(m.FRAMEBUFFER,a.__webglFramebuffer),g=!0);m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?m.readPixels(b,c,d,e,m.RGBA,m.UNSIGNED_BYTE,f):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.");g&&m.bindFramebuffer(m.FRAMEBUFFER,ab)}};this.initMaterial=function(){THREE.warn("THREE.WebGLRenderer: .initMaterial() has been removed.")};this.addPrePlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPrePlugin() has been removed.")}; +this.addPostPlugin=function(){THREE.warn("THREE.WebGLRenderer: .addPostPlugin() has been removed.")};this.updateShadowMap=function(){THREE.warn("THREE.WebGLRenderer: .updateShadowMap() has been removed.")}}; THREE.WebGLRenderTarget=function(a,b,c){this.width=a;this.height=b;c=c||{};this.wrapS=void 0!==c.wrapS?c.wrapS:THREE.ClampToEdgeWrapping;this.wrapT=void 0!==c.wrapT?c.wrapT:THREE.ClampToEdgeWrapping;this.magFilter=void 0!==c.magFilter?c.magFilter:THREE.LinearFilter;this.minFilter=void 0!==c.minFilter?c.minFilter:THREE.LinearMipMapLinearFilter;this.anisotropy=void 0!==c.anisotropy?c.anisotropy:1;this.offset=new THREE.Vector2(0,0);this.repeat=new THREE.Vector2(1,1);this.format=void 0!==c.format?c.format: THREE.RGBAFormat;this.type=void 0!==c.type?c.type:THREE.UnsignedByteType;this.depthBuffer=void 0!==c.depthBuffer?c.depthBuffer:!0;this.stencilBuffer=void 0!==c.stencilBuffer?c.stencilBuffer:!0;this.generateMipmaps=!0;this.shareDepthFrom=void 0!==c.shareDepthFrom?c.shareDepthFrom:null}; THREE.WebGLRenderTarget.prototype={constructor:THREE.WebGLRenderTarget,setSize:function(a,b){this.width=a;this.height=b},clone:function(){var a=new THREE.WebGLRenderTarget(this.width,this.height);a.wrapS=this.wrapS;a.wrapT=this.wrapT;a.magFilter=this.magFilter;a.minFilter=this.minFilter;a.anisotropy=this.anisotropy;a.offset.copy(this.offset);a.repeat.copy(this.repeat);a.format=this.format;a.type=this.type;a.depthBuffer=this.depthBuffer;a.stencilBuffer=this.stencilBuffer;a.generateMipmaps=this.generateMipmaps; @@ -577,50 +579,50 @@ THREE.WebGLExtensions=function(a){var b={};this.get=function(c){if(void 0!==b[c] break;case "WEBGL_compressed_texture_pvrtc":d=a.getExtension("WEBGL_compressed_texture_pvrtc")||a.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;default:d=a.getExtension(c)}null===d&&THREE.warn("THREE.WebGLRenderer: "+c+" extension not supported.");return b[c]=d}}; THREE.WebGLProgram=function(){var a=0;return function(b,c,d,e){var f=b.context,g=d.defines,h=d.__webglShader.uniforms,k=d.attributes,l=d.__webglShader.vertexShader,p=d.__webglShader.fragmentShader,q=d.index0AttributeName;void 0===q&&!0===e.morphTargets&&(q="position");var n="SHADOWMAP_TYPE_BASIC";e.shadowMapType===THREE.PCFShadowMap?n="SHADOWMAP_TYPE_PCF":e.shadowMapType===THREE.PCFSoftShadowMap&&(n="SHADOWMAP_TYPE_PCF_SOFT");var t="ENVMAP_TYPE_CUBE",s="ENVMAP_MODE_REFLECTION",r="ENVMAP_BLENDING_MULTIPLY"; if(e.envMap){switch(d.envMap.mapping){case THREE.CubeReflectionMapping:case THREE.CubeRefractionMapping:t="ENVMAP_TYPE_CUBE";break;case THREE.EquirectangularReflectionMapping:case THREE.EquirectangularRefractionMapping:t="ENVMAP_TYPE_EQUIREC";break;case THREE.SphericalReflectionMapping:t="ENVMAP_TYPE_SPHERE"}switch(d.envMap.mapping){case THREE.CubeRefractionMapping:case THREE.EquirectangularRefractionMapping:s="ENVMAP_MODE_REFRACTION"}switch(d.combine){case THREE.MultiplyOperation:r="ENVMAP_BLENDING_MULTIPLY"; -break;case THREE.MixOperation:r="ENVMAP_BLENDING_MIX";break;case THREE.AddOperation:r="ENVMAP_BLENDING_ADD"}}var u=0L;L++)I[L]=new THREE.Vector3,z[L]=new THREE.Vector3;I=D.shadowCascadeNearZ[H];D=D.shadowCascadeFarZ[H];z[0].set(-1,-1,I);z[1].set(1,-1,I);z[2].set(-1,1,I);z[3].set(1,1,I);z[4].set(-1,-1,D);z[5].set(1,-1,D);z[6].set(-1,1,D);z[7].set(1,1,D);M.originalCamera=u;z=new THREE.Gyroscope;z.position.copy(A.shadowCascadeOffset);z.add(M);z.add(M.target);u.add(z);A.shadowCascadeArray[G]=M}H=A;I=G;D=H.shadowCascadeArray[I];D.position.copy(H.position); -D.target.position.copy(H.target.position);D.lookAt(D.target);D.shadowCameraVisible=H.shadowCameraVisible;D.shadowDarkness=H.shadowDarkness;D.shadowBias=H.shadowCascadeBias[I];z=H.shadowCascadeNearZ[I];H=H.shadowCascadeFarZ[I];D=D.pointsFrustum;D[0].z=z;D[1].z=z;D[2].z=z;D[3].z=z;D[4].z=H;D[5].z=H;D[6].z=H;D[7].z=H;U[E]=M;E++}else U[E]=A,E++;v=0;for(y=U.length;vL;L++)I[L]=new THREE.Vector3,F[L]=new THREE.Vector3;I=z.shadowCascadeNearZ[H];z=z.shadowCascadeFarZ[H];F[0].set(-1,-1,I);F[1].set(1,-1,I);F[2].set(-1,1,I);F[3].set(1,1,I);F[4].set(-1,-1,z);F[5].set(1,-1,z);F[6].set(-1,1,z);F[7].set(1,1,z);M.originalCamera=v;F=new THREE.Gyroscope;F.position.copy(A.shadowCascadeOffset);F.add(M);F.add(M.target);v.add(F);A.shadowCascadeArray[G]=M}H=A;I=G;z=H.shadowCascadeArray[I];z.position.copy(H.position); +z.target.position.copy(H.target.position);z.lookAt(z.target);z.shadowCameraVisible=H.shadowCameraVisible;z.shadowDarkness=H.shadowDarkness;z.shadowBias=H.shadowCascadeBias[I];F=H.shadowCascadeNearZ[I];H=H.shadowCascadeFarZ[I];z=z.pointsFrustum;z[0].z=F;z[1].z=F;z[2].z=F;z[3].z=F;z[4].z=H;z[5].z=H;z[6].z=H;z[7].z=H;U[E]=M;E++}else U[E]=A,E++;u=0;for(y=U.length;u -H;H++)I=D[H],I.copy(z[H]),I.unproject(G),I.applyMatrix4(E.matrixWorldInverse),I.xt.x&&(t.x=I.x),I.yt.y&&(t.y=I.y),I.zt.z&&(t.z=I.z);E.left=n.x;E.right=t.x;E.top=t.y;E.bottom=n.y;E.updateProjectionMatrix()}E=A.shadowMap;z=A.shadowMatrix;G=A.shadowCamera;G.position.setFromMatrixPosition(A.matrixWorld);s.setFromMatrixPosition(A.target.matrixWorld);G.lookAt(s);G.updateMatrixWorld();G.matrixWorldInverse.getInverse(G.matrixWorld);A.cameraHelper&& -(A.cameraHelper.visible=A.shadowCameraVisible);A.shadowCameraVisible&&A.cameraHelper.update();z.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1);z.multiply(G.projectionMatrix);z.multiply(G.matrixWorldInverse);q.multiplyMatrices(G.projectionMatrix,G.matrixWorldInverse);p.setFromMatrix(q);a.setRenderTarget(E);a.clear();r.length=0;e(c,c,G);A=0;for(E=r.length;A +H;H++)I=z[H],I.copy(F[H]),I.unproject(G),I.applyMatrix4(E.matrixWorldInverse),I.xt.x&&(t.x=I.x),I.yt.y&&(t.y=I.y),I.zt.z&&(t.z=I.z);E.left=n.x;E.right=t.x;E.top=t.y;E.bottom=n.y;E.updateProjectionMatrix()}E=A.shadowMap;F=A.shadowMatrix;G=A.shadowCamera;G.position.setFromMatrixPosition(A.matrixWorld);s.setFromMatrixPosition(A.target.matrixWorld);G.lookAt(s);G.updateMatrixWorld();G.matrixWorldInverse.getInverse(G.matrixWorld);A.cameraHelper&& +(A.cameraHelper.visible=A.shadowCameraVisible);A.shadowCameraVisible&&A.cameraHelper.update();F.set(.5,0,0,.5,0,.5,0,.5,0,0,.5,.5,0,0,0,1);F.multiply(G.projectionMatrix);F.multiply(G.matrixWorldInverse);q.multiplyMatrices(G.projectionMatrix,G.matrixWorldInverse);p.setFromMatrix(q);a.setRenderTarget(E);a.clear();r.length=0;e(c,c,G);A=0;for(E=r.length;A 0 ) {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat fogFactor = 0.0;\nif ( fogType == 1 ) {\nfogFactor = smoothstep( fogNear, fogFar, depth );\n} else {\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n}\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );\n}\n}"].join("\n")); w.compileShader(L);w.compileShader(P);w.attachShader(H,L);w.attachShader(H,P);w.linkProgram(H);E=H;v=w.getAttribLocation(E,"position");x=w.getAttribLocation(E,"uv");c=w.getUniformLocation(E,"uvOffset");d=w.getUniformLocation(E,"uvScale");e=w.getUniformLocation(E,"rotation");f=w.getUniformLocation(E,"scale");g=w.getUniformLocation(E,"color");h=w.getUniformLocation(E,"map");k=w.getUniformLocation(E,"opacity");l=w.getUniformLocation(E,"modelViewMatrix");p=w.getUniformLocation(E,"projectionMatrix");q= w.getUniformLocation(E,"fogType");n=w.getUniformLocation(E,"fogDensity");t=w.getUniformLocation(E,"fogNear");s=w.getUniformLocation(E,"fogFar");r=w.getUniformLocation(E,"fogColor");u=w.getUniformLocation(E,"alphaTest");H=document.createElement("canvas");H.width=8;H.height=8;L=H.getContext("2d");L.fillStyle="white";L.fillRect(0,0,8,8);G=new THREE.Texture(H);G.needsUpdate=!0}w.useProgram(E);w.enableVertexAttribArray(v);w.enableVertexAttribArray(x);w.disable(w.CULL_FACE);w.enable(w.BLEND);w.bindBuffer(w.ARRAY_BUFFER, y);w.vertexAttribPointer(v,2,w.FLOAT,!1,16,0);w.vertexAttribPointer(x,2,w.FLOAT,!1,16,8);w.bindBuffer(w.ELEMENT_ARRAY_BUFFER,A);w.uniformMatrix4fv(p,!1,M.projectionMatrix.elements);w.activeTexture(w.TEXTURE0);w.uniform1i(h,0);L=H=0;(P=U.fog)?(w.uniform3f(r,P.color.r,P.color.g,P.color.b),P instanceof THREE.Fog?(w.uniform1f(t,P.near),w.uniform1f(s,P.far),w.uniform1i(q,1),L=H=1):P instanceof THREE.FogExp2&&(w.uniform1f(n,P.density),w.uniform1i(q,2),L=H=2)):(w.uniform1i(q,0),L=H=0);for(var P=0,N=b.length;P< -N;P++){var R=b[P];R._modelViewMatrix.multiplyMatrices(M.matrixWorldInverse,R.matrixWorld);R.z=-R._modelViewMatrix.elements[14]}b.sort(F);for(var V=[],P=0,N=b.length;Pe)return null;var f=[],g=[],h=[],k,l,p;if(0=q--){THREE.warn("THREE.FontUtils: Warning, unable to triangulate polygon! in Triangulate.process()");break}k=l;e<=k&&(k=0);l=k+1;e<=l&&(l=0);p=l+1;e<=p&&(p=0);var n;a:{var t=n=void 0,s=void 0,r=void 0, -u=void 0,v=void 0,x=void 0,F=void 0,w=void 0,t=a[g[k]].x,s=a[g[k]].y,r=a[g[l]].x,u=a[g[l]].y,v=a[g[p]].x,x=a[g[p]].y;if(1E-10>(r-t)*(x-s)-(u-s)*(v-t))n=!1;else{var y=void 0,A=void 0,E=void 0,G=void 0,z=void 0,D=void 0,I=void 0,U=void 0,M=void 0,H=void 0,M=U=I=w=F=void 0,y=v-r,A=x-u,E=t-v,G=s-x,z=r-t,D=u-s;for(n=0;n(r-t)*(x-s)-(u-s)*(v-t))n=!1;else{var y=void 0,A=void 0,E=void 0,G=void 0,F=void 0,z=void 0,I=void 0,U=void 0,M=void 0,H=void 0,M=U=I=w=D=void 0,y=v-r,A=x-u,E=t-v,G=s-x,F=r-t,z=u-s;for(n=0;nG||G>E)return[];k=l*p-k*q;if(0>k||k>E)return[]}else{if(0d?[]:k==d?f?[]:[g]:a<=d?[g,h]: [g,l]}function e(a,b,c,d){var e=b.x-a.x,f=b.y-a.y;b=c.x-a.x;c=c.y-a.y;var g=d.x-a.x;d=d.y-a.y;a=e*c-f*b;e=e*d-f*g;return 1E-10f&&(f=d);var g=a+1;g>d&&(g=0);d=e(h[a],h[f],h[g],k[b]); -if(!d)return!1;d=k.length-1;f=b-1;0>f&&(f=d);g=b+1;g>d&&(g=0);return(d=e(k[b],k[f],k[g],h[a]))?!0:!1}function f(a,b){var c,e;for(c=0;c -H){console.log("Infinite Loop! Holes left:"+l.length+", Probably Hole outside Shape!");break}for(q=D;qf&&(f=d);g=b+1;g>d&&(g=0);return(d=e(k[b],k[f],k[g],h[a]))?!0:!1}function f(a,b){var c,e;for(c=0;c +H){console.log("Infinite Loop! Holes left:"+l.length+", Probably Hole outside Shape!");break}for(q=z;qh;h++)l=k[h].x+":"+k[h].y,l=p[l],void 0!==l&&(k[h]=l);return q.concat()},isClockWise:function(a){return 0>THREE.FontUtils.Triangulate.area(a)},b2p0:function(a,b){var c=1-a;return c*c*b},b2p1:function(a,b){return 2*(1-a)*a*b},b2p2:function(a,b){return a*a*b},b2:function(a,b,c,d){return this.b2p0(a,b)+this.b2p1(a,c)+this.b2p2(a,d)},b3p0:function(a,b){var c=1-a;return c*c*c*b},b3p1:function(a,b){var c=1-a;return 3*c*c*a*b},b3p2:function(a,b){return 3*(1-a)*a*a*b},b3p3:function(a,b){return a* a*a*b},b3:function(a,b,c,d,e){return this.b3p0(a,b)+this.b3p1(a,c)+this.b3p2(a,d)+this.b3p3(a,e)}};THREE.LineCurve=function(a,b){this.v1=a;this.v2=b};THREE.LineCurve.prototype=Object.create(THREE.Curve.prototype);THREE.LineCurve.prototype.constructor=THREE.LineCurve;THREE.LineCurve.prototype.getPoint=function(a){var b=this.v2.clone().sub(this.v1);b.multiplyScalar(a).add(this.v1);return b};THREE.LineCurve.prototype.getPointAt=function(a){return this.getPoint(a)}; THREE.LineCurve.prototype.getTangent=function(a){return this.v2.clone().sub(this.v1).normalize()};THREE.QuadraticBezierCurve=function(a,b,c){this.v0=a;this.v1=b;this.v2=c};THREE.QuadraticBezierCurve.prototype=Object.create(THREE.Curve.prototype);THREE.QuadraticBezierCurve.prototype.constructor=THREE.QuadraticBezierCurve; @@ -715,27 +717,27 @@ f;d.nextKey=g}g.time>=this.currentTime?f.interpolate(g,this.currentTime):f.inter THREE.KeyFrameAnimation.prototype.getPrevKeyWith=function(a,b,c){b=this.data.hierarchy[b].keys;for(c=0<=c?c:c+b.length;0<=c;c--)if(b[c].hasTarget(a))return b[c];return b[b.length-1]};THREE.MorphAnimation=function(a){this.mesh=a;this.frames=a.morphTargetInfluences.length;this.currentTime=0;this.duration=1E3;this.loop=!0;this.currentFrame=this.lastFrame=0;this.isPlaying=!1}; THREE.MorphAnimation.prototype={constructor:THREE.MorphAnimation,play:function(){this.isPlaying=!0},pause:function(){this.isPlaying=!1},update:function(a){if(!1!==this.isPlaying){this.currentTime+=a;!0===this.loop&&this.currentTime>this.duration&&(this.currentTime%=this.duration);this.currentTime=Math.min(this.currentTime,this.duration);a=this.duration/this.frames;var b=Math.floor(this.currentTime/a);b!=this.currentFrame&&(this.mesh.morphTargetInfluences[this.lastFrame]=0,this.mesh.morphTargetInfluences[this.currentFrame]= 1,this.mesh.morphTargetInfluences[b]=0,this.lastFrame=this.currentFrame,this.currentFrame=b);this.mesh.morphTargetInfluences[b]=this.currentTime%a/a;this.mesh.morphTargetInfluences[this.lastFrame]=1-this.mesh.morphTargetInfluences[b]}}}; -THREE.BoxGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,r){var u,v=h.widthSegments,x=h.heightSegments,F=e/2,w=f/2,y=h.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)u="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)u="y",x=h.depthSegments;else if("z"===a&&"y"===b||"y"===a&&"z"===b)u="x",v=h.depthSegments;var A=v+1,E=x+1,G=e/v,z=f/x,D=new THREE.Vector3;D[u]=0=d)return new THREE.Vector2(c,a);d=Math.sqrt(d/2)}else a=!1,1E-10d?-1E-10>f&&(a=!0):Math.sign(e)==Math.sign(g)&&(a=!0),a?(c=-e,a=d,d=Math.sqrt(h)):(c=d,a=e,d=Math.sqrt(h/2));return new THREE.Vector2(c/d,a/d)}function e(a,b){var c,d;for(O=a.length;0<=--O;){c=O;d=O-1;0>d&&(d=a.length-1);for(var e=0,f=t+2*p,e=0;ed?-1E-10>f&&(a=!0):Math.sign(e)==Math.sign(g)&&(a=!0),a?(c=-e,a=d,d=Math.sqrt(h)):(c=d,a=e,d=Math.sqrt(h/2));return new THREE.Vector2(c/d,a/d)}function e(a,b){var c,d;for(O=a.length;0<=--O;){c=O;d=O-1;0>d&&(d=a.length-1);for(var e=0,f=t+2*p,e=0;eMath.abs(b.y-c.y)?[new THREE.Vector2(b.x,1-b.z),new THREE.Vector2(c.x,1-c.z),new THREE.Vector2(d.x,1-d.z),new THREE.Vector2(e.x,1-e.z)]:[new THREE.Vector2(b.y,1-b.z),new THREE.Vector2(c.y,1-c.z),new THREE.Vector2(d.y, 1-d.z),new THREE.Vector2(e.y,1-e.z)]}};THREE.ShapeGeometry=function(a,b){THREE.Geometry.call(this);this.type="ShapeGeometry";!1===a instanceof Array&&(a=[a]);this.addShapeList(a,b);this.computeFaceNormals()};THREE.ShapeGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.ShapeGeometry.prototype.constructor=THREE.ShapeGeometry;THREE.ShapeGeometry.prototype.addShapeList=function(a,b){for(var c=0,d=a.length;cb;b++)a.faces[b].color=this.colors[4>b?0:1];b=new THREE.MeshBasicMaterial({vertexColors:THREE.FaceColors,wireframe:!0});this.lightSphere=new THREE.Mesh(a,b);this.add(this.lightSphere); +THREE.HemisphereLightHelper=function(a,b){THREE.Object3D.call(this);this.light=a;this.light.updateMatrixWorld();this.matrix=a.matrixWorld;this.matrixAutoUpdate=!1;this.colors=[new THREE.Color,new THREE.Color];var c=new THREE.SphereGeometry(b,4,2);c.applyMatrix((new THREE.Matrix4).makeRotationX(-Math.PI/2));for(var d=0;8>d;d++)c.faces[d].color=this.colors[4>d?0:1];d=new THREE.MeshBasicMaterial({vertexColors:THREE.FaceColors,wireframe:!0});this.lightSphere=new THREE.Mesh(c,d);this.add(this.lightSphere); this.update()};THREE.HemisphereLightHelper.prototype=Object.create(THREE.Object3D.prototype);THREE.HemisphereLightHelper.prototype.constructor=THREE.HemisphereLightHelper;THREE.HemisphereLightHelper.prototype.dispose=function(){this.lightSphere.geometry.dispose();this.lightSphere.material.dispose()}; THREE.HemisphereLightHelper.prototype.update=function(){var a=new THREE.Vector3;return function(){this.colors[0].copy(this.light.color).multiplyScalar(this.light.intensity);this.colors[1].copy(this.light.groundColor).multiplyScalar(this.light.intensity);this.lightSphere.lookAt(a.setFromMatrixPosition(this.light.matrixWorld).negate());this.lightSphere.geometry.colorsNeedUpdate=!0}}(); THREE.PointLightHelper=function(a,b){this.light=a;this.light.updateMatrixWorld();var c=new THREE.SphereGeometry(b,4,2),d=new THREE.MeshBasicMaterial({wireframe:!0,fog:!1});d.color.copy(this.light.color).multiplyScalar(this.light.intensity);THREE.Mesh.call(this,c,d);this.matrix=this.light.matrixWorld;this.matrixAutoUpdate=!1};THREE.PointLightHelper.prototype=Object.create(THREE.Mesh.prototype);THREE.PointLightHelper.prototype.constructor=THREE.PointLightHelper; diff --git a/docs/api/extras/helpers/CameraHelper.html b/docs/api/extras/helpers/CameraHelper.html index 1a6fd9f1f246bc..64d74380d55082 100644 --- a/docs/api/extras/helpers/CameraHelper.html +++ b/docs/api/extras/helpers/CameraHelper.html @@ -45,7 +45,7 @@

[property:Camera camera]

Methods

-

[method:todo update]()

+

[method:null update]()

Updates the helper based on the projectionMatrix of the camera.
diff --git a/docs/api/extras/helpers/DirectionalLightHelper.html b/docs/api/extras/helpers/DirectionalLightHelper.html index 4b1d62f0972d96..80aa9e095a4e4c 100644 --- a/docs/api/extras/helpers/DirectionalLightHelper.html +++ b/docs/api/extras/helpers/DirectionalLightHelper.html @@ -17,7 +17,7 @@

[name]

Constructor

-

[name]([DirectionalLight:todo light], [page:Number size])

+

[name]([page:DirectionalLight light], [page:Number size])

light -- [page:DirectionalLight] -- Light to visualize
size -- dimensions of the plane @@ -32,18 +32,18 @@

Properties

[property:Line lightPlane]

- todo + Contains the line mesh showing the location of the directional light.

[property:DirectionalLight light]

- todo + Contains the directionalLight.

[property:Line targetLine]

- todo -
+ Contains the line mesh that shows the direction of the light. +

Methods

diff --git a/docs/api/extras/helpers/HemisphereLightHelper.html b/docs/api/extras/helpers/HemisphereLightHelper.html index 52987be41530bd..070a2ae2735941 100644 --- a/docs/api/extras/helpers/HemisphereLightHelper.html +++ b/docs/api/extras/helpers/HemisphereLightHelper.html @@ -11,20 +11,18 @@

[name]

-
todo
+
Creates a visual aid for a [page:HemisphereLight HemisphereLight].

Constructor

-

[name]([page:todo light], [page:todo sphereSize], [page:todo arrowLength], [page:todo domeSize])

+

[name]([page:HemisphereLight light], [page:Number sphereSize])

- light -- todo
- sphereSize -- todo
- arrowLength -- todo
- domeSize -- todo + light -- The HemisphereLight.
+ sphereSize -- The size of the sphere that shows the location.
- todo + Creates an helper for the hemispherelight.
@@ -32,20 +30,20 @@

Properties

[property:Mesh lightSphere]

- todo + The sphere mesh that shows the location of the hemispherelight.

[property:HemisphereLight light]

- todo + Contains the HemisphereLight.

Methods

-

[method:todo update]()

+

[method:null update]()

- todo + Updates the helper to match the position and direction of the [page:.light].
diff --git a/docs/api/materials/MeshNormalMaterial.html b/docs/api/materials/MeshNormalMaterial.html index 37ca144e1b2e17..80b32009d5fad7 100644 --- a/docs/api/materials/MeshNormalMaterial.html +++ b/docs/api/materials/MeshNormalMaterial.html @@ -12,7 +12,7 @@

[name]

A material that maps the normal vectors to RGB colors.
- + @@ -21,10 +21,9 @@

Constructor

[name]([page:Object parameters])

- parameters is an object with one or more properties defining the material's appearance. + parameters is an object with one or more properties defining the material's appearance.
- shading -- How the triangles of a curved surface are rendered. Default is [page:Materials THREE.FlatShading].
wireframe -- Render geometry as wireframe. Default is false (i.e. render as smooth shaded).
wireframeLinewidth -- Controls wireframe thickness. Default is 1.
morphTargets -- Define whether the material uses morphTargets. Default is false.
@@ -34,25 +33,19 @@

[name]([page:Object parameters])

Properties

-

[property:number shading]

+

[property:boolean wireframe]

- How the triangles of a curved surface are rendered: as a smooth surface, as flat separate facets, or no shading at all.

- Options are [page:Materials THREE.SmoothShading], [page:Materials THREE.FlatShading](default) + Render geometry as wireframe. Default is false (i.e. render as smooth shaded).
-

[property:boolean wireframe]

-
- Render geometry as wireframe. Default is false (i.e. render as smooth shaded). -
-

[property:number wireframeLinewidth]

Controls wireframe thickness. Default is 1.

Due to limitations in the ANGLE layer, on Windows platforms linewidth will always be 1 regardless of the set value. -
+

[property:boolean morphTargets]

-
Define whether the material uses morphTargets. Default is false.
+
Define whether the material uses morphTargets. Default is false.

Methods

diff --git a/docs/index.html b/docs/index.html index b2d1624f909ffa..5b2f85dee1bb19 100644 --- a/docs/index.html +++ b/docs/index.html @@ -406,10 +406,10 @@

three.js / docs

if ( window.location.hash.length > 0 ) goToHash(); console.log([ - '_______ __', - '/ _______\\/ __\\__ ____ _____ _____', - '\\/__ __/ / /___\\/ ____\\/ _____\\/ _____\\', - ' / / / / / _ / / __/ / __ / / __ /_ __ _____', + ' __ __', + ' __/ __\\ / __\\__ ____ _____ _____', + '/ __/ /\\/ / /___\\/ ____\\/ _____\\/ _____\\', + '\\/_ __/ / _ / / __/ / __ / / __ /_ __ _____', '/ / / / / / / / / / / / ___/ / ___/\\ _\\/ __\\/ _____\\', '\\/__/ \\/__/\\/__/\\/__/ \\/_____/\\/_____/\\/__/ / / / ___/', ' / __/ / \\__ \\', diff --git a/editor/css/main.css b/editor/css/main.css index 59d7904c66c9ed..8e4319c37717d1 100644 --- a/editor/css/main.css +++ b/editor/css/main.css @@ -67,6 +67,8 @@ textarea, input { outline: none; } /* osx */ display: none; } +/* CodeMirror */ + .CodeMirror { position: absolute !important; @@ -76,6 +78,20 @@ textarea, input { outline: none; } /* osx */ } + .CodeMirror .errorLine { + + background: rgba(255,0,0,0.25); + + } + + .CodeMirror .esprima-error { + + color: #f00; + text-align: right; + padding: 0px 20px; + + } + /* scene types */ .type { diff --git a/editor/examples/arkanoid.app.json b/editor/examples/arkanoid.app.json index b643cba08c2e34..0273a34e73a9e2 100755 --- a/editor/examples/arkanoid.app.json +++ b/editor/examples/arkanoid.app.json @@ -162,7 +162,7 @@ "31517222-A9A7-4EAF-B5F6-60751C0BABA3": [ { "name": "Game Logic", - "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.material = material;\n\t\tobject.position.x = i * 22 - 120;\n\t\tobject.position.z = j * 14 - 120;\n\t\tgroup.add( object );\n\t\t\n\t}\n\t\n}\n\nbrick.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 150 || ball.position.x > 150 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 200 || ball.position.z > 200 ) direction.z = - direction.z;\n\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 4 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}" + "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.material = material;\n\t\tobject.position.x = i * 22 - 120;\n\t\tobject.position.z = j * 14 - 120;\n\t\tgroup.add( object );\n\t\t\n\t}\n\t\n}\n\nbrick.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 150 || ball.position.x > 150 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 200 || ball.position.z > 200 ) direction.z = - direction.z;\n\n\tball.position.x = Math.max( - 150, Math.min( 150, ball.position.x ) );\n\tball.position.z = Math.max( - 200, Math.min( 200, ball.position.z ) );\n\t\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 4 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}" }] } } \ No newline at end of file diff --git a/editor/examples/camera.app.json b/editor/examples/camera.app.json old mode 100644 new mode 100755 index 1ff8d5252c4338..e4c7905d84db2c --- a/editor/examples/camera.app.json +++ b/editor/examples/camera.app.json @@ -6,14 +6,14 @@ "generator": "ObjectExporter" }, "object": { - "uuid": "F0D8434F-4603-415B-8024-792FE97B9600", + "uuid": "C7FB195B-270E-47B4-95C9-1754652A9D11", "type": "PerspectiveCamera", "name": "Camera", "fov": 50, "aspect": 1.2252042007001167, "near": 0.1, "far": 100000, - "matrix": [0.9700406789779663,-5.500052080442686e-10,-0.24294254183769226,0,-0.04822639003396034,0.9800989627838135,-0.19256223738193512,0,0.23810774087905884,0.19850945472717285,0.950735867023468,0,159.0158233642578,132.5708465576172,634.9312744140625,1] + "matrix": [0.9700406789779663,-2.851828329042405e-9,-0.24294254183769226,0,-0.04822639003396034,0.9800989627838135,-0.1925622522830963,0,0.23810774087905884,0.19850945472717285,0.950735867023468,0,154.7735595703125,129.03408813476562,617.992431640625,1] } }, "scene": { @@ -23,6 +23,14 @@ "generator": "ObjectExporter" }, "geometries": [ + { + "uuid": "51BB3E54-D2DF-4576-9953-FB8E940588B5", + "type": "PlaneGeometry", + "width": 1000, + "height": 1000, + "widthSegments": 1, + "heightSegments": 1 + }, { "uuid": "D8E200D3-27BC-49F8-A5C5-7384206E70FE", "type": "BoxGeometry", @@ -43,14 +51,6 @@ "heightSegments": 1, "openEnded": false }, - { - "uuid": "51BB3E54-D2DF-4576-9953-FB8E940588B5", - "type": "PlaneGeometry", - "width": 1000, - "height": 1000, - "widthSegments": 1, - "heightSegments": 1 - }, { "uuid": "4DECFAB5-6FD1-4D84-9A29-565807B074EA", "type": "IcosahedronGeometry", @@ -59,25 +59,25 @@ }], "materials": [ { - "uuid": "B5943856-E404-45D9-A427-4774202C2CD0", + "uuid": "4AE8130E-B6A8-47BC-ACCF-060973C74044", "type": "MeshPhongMaterial", - "color": 37119, + "color": 16777215, "emissive": 0, "specular": 1118481, "shininess": 30 }, { - "uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E", + "uuid": "B5943856-E404-45D9-A427-4774202C2CD0", "type": "MeshPhongMaterial", - "color": 15859456, + "color": 37119, "emissive": 0, "specular": 1118481, "shininess": 30 }, { - "uuid": "4AE8130E-B6A8-47BC-ACCF-060973C74044", + "uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E", "type": "MeshPhongMaterial", - "color": 16777215, + "color": 15859456, "emissive": 0, "specular": 1118481, "shininess": 30 @@ -97,19 +97,34 @@ "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1], "children": [ { - "uuid": "60B69C58-4201-43FD-815E-AD2EDFBBD0CE", - "type": "PerspectiveCamera", - "name": "PerspectiveCamera 1", - "fov": 50, - "aspect": 1, - "near": 100, - "far": 10000, - "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,100,400,1] + "uuid": "B7CBBC6F-EC26-49B5-8D0D-67D9C535924B", + "type": "Group", + "name": "Dummy", + "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,100,400,1], + "children": [ + { + "uuid": "60B69C58-4201-43FD-815E-AD2EDFBBD0CE", + "type": "PerspectiveCamera", + "name": "PerspectiveCamera", + "fov": 50, + "aspect": 1, + "near": 100, + "far": 10000, + "matrix": [-1,0,-1.2246468525851679e-16,0,0,1,0,0,1.2246468525851679e-16,0,-1,0,0,0,0,1] + }] + }, + { + "uuid": "A460C230-DC88-4A8F-A3FB-AA0FE735F3ED", + "type": "Mesh", + "name": "Plane", + "geometry": "51BB3E54-D2DF-4576-9953-FB8E940588B5", + "material": "4AE8130E-B6A8-47BC-ACCF-060973C74044", + "matrix": [1,0,0,0,0,0.040785226970911026,-0.9991679191589355,0,0,0.9991679191589355,0.040785226970911026,0,0,-50,0,1] }, { "uuid": "26DAAD69-725D-43B7-AF9D-990A99DEF8C5", "type": "Mesh", - "name": "Box 1", + "name": "Box", "geometry": "D8E200D3-27BC-49F8-A5C5-7384206E70FE", "material": "B5943856-E404-45D9-A427-4774202C2CD0", "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1] @@ -117,27 +132,18 @@ { "uuid": "AAAFF2D6-4725-4AFC-A9FE-26419B11011F", "type": "Mesh", - "name": "Cylinder 3", + "name": "Cylinder", "geometry": "25BA32DB-8B02-4ABA-A77C-69868C464A1A", "material": "3F872310-2067-4BE4-9250-5B3F4E43797E", "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-130,-15,0,1] }, { - "uuid": "A460C230-DC88-4A8F-A3FB-AA0FE735F3ED", + "uuid": "B855E267-A266-4098-ACD6-6A1FDE7B88BA", "type": "Mesh", - "name": "Plane 4", - "geometry": "51BB3E54-D2DF-4576-9953-FB8E940588B5", - "material": "4AE8130E-B6A8-47BC-ACCF-060973C74044", - "matrix": [1,0,0,0,0,0.040785059332847595,-0.9991679191589355,0,0,0.9991679191589355,0.040785059332847595,0,0,-50,0,1] - }, - { - "uuid": "3412781E-27CC-43C3-A5DB-54C0C8E42ED6", - "type": "PointLight", - "name": "PointLight 2", - "color": 12773063, - "intensity": 1, - "distance": 0, - "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,88.12999725341797,8.3100004196167,125.44999694824219,1] + "name": "Icosahedron", + "geometry": "4DECFAB5-6FD1-4D84-9A29-565807B074EA", + "material": "E1826901-7922-4584-A25D-6D487E2C9BBD", + "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,130,-10,0,1] }, { "uuid": "E2939A7B-5E40-438A-8C1B-32126FBC6892", @@ -146,23 +152,31 @@ "color": 9474221, "intensity": 0.75, "distance": 0, + "decay": 1, "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-93.86000061035156,127.12999725341797,-114.30000305175781,1] }, { - "uuid": "B855E267-A266-4098-ACD6-6A1FDE7B88BA", - "type": "Mesh", - "name": "Icosahedron 1", - "geometry": "4DECFAB5-6FD1-4D84-9A29-565807B074EA", - "material": "E1826901-7922-4584-A25D-6D487E2C9BBD", - "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,130,-10,0,1] + "uuid": "3412781E-27CC-43C3-A5DB-54C0C8E42ED6", + "type": "PointLight", + "name": "PointLight 2", + "color": 12773063, + "intensity": 1, + "distance": 0, + "decay": 1, + "matrix": [1,0,0,0,0,1,0,0,0,0,1,0,88.12999725341797,8.3100004196167,125.44999694824219,1] }] } }, "scripts": { "60B69C58-4201-43FD-815E-AD2EDFBBD0CE": [ { - "name": "Camera Orbit", - "source": "player.setCamera( this );\n\nfunction update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 400;\n\tthis.position.z = Math.cos( time ) * 400;\n\tthis.lookAt( scene.position );\n\n}" + "name": "Player Camera", + "source": "player.setCamera( this );" + }], + "B7CBBC6F-EC26-49B5-8D0D-67D9C535924B": [ + { + "name": "Orbit", + "source": "function update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 400;\n\tthis.position.z = Math.cos( time ) * 400;\n\tthis.lookAt( scene.position );\n\n}" }] } -} +} \ No newline at end of file diff --git a/editor/examples/pong.app.json b/editor/examples/pong.app.json index fd04fc724049eb..9b8a983c54e653 100755 --- a/editor/examples/pong.app.json +++ b/editor/examples/pong.app.json @@ -128,7 +128,7 @@ "31517222-A9A7-4EAF-B5F6-60751C0BABA3": [ { "name": "Game logic", - "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize();\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 300 - 150;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\n\tif ( position.x < -300 || position.x > 300 ) {\n\t\t\n\t\tdirection.x = - direction.x;\n\t\t\n\t}\n\n\tif ( position.z < -200 || position.z > 200 ) {\n\t\t\n\t\tdirection.z = - direction.z;\n\t\t\n\t}\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 10 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 2 ) );\n\n}" + "source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize();\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 300 - 150;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\t\n\tif ( position.x < -300 || position.x > 300 ) direction.x = - direction.x;\n\tif ( position.z < -200 || position.z > 200 ) direction.z = - direction.z;\n\t\n\tposition.x = Math.max( - 300, Math.min( 300, position.x ) );\n\tposition.z = Math.max( - 200, Math.min( 200, position.z ) );\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 10 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 2 ) );\n\n}" }] } } \ No newline at end of file diff --git a/editor/index.html b/editor/index.html index 51544dfce46c3c..4ac1c041e8cd8b 100644 --- a/editor/index.html +++ b/editor/index.html @@ -41,6 +41,7 @@ + diff --git a/editor/js/Editor.js b/editor/js/Editor.js index d5a45fa20601e9..34412e6561f3ad 100644 --- a/editor/js/Editor.js +++ b/editor/js/Editor.js @@ -470,6 +470,9 @@ Editor.prototype = { return { + project: { + vr: this.config.getKey( 'project/vr' ) + }, camera: this.camera.toJSON(), scene: this.scene.toJSON(), scripts: this.scripts diff --git a/editor/js/Menubar.Edit.js b/editor/js/Menubar.Edit.js index 246713c83d0a6c..dbe75877094dcb 100644 --- a/editor/js/Menubar.Edit.js +++ b/editor/js/Menubar.Edit.js @@ -53,38 +53,6 @@ Menubar.Edit = function ( editor ) { } ); options.add( option ); - // - - options.add( new UI.HorizontalRule() ); - - // Flatten - - var option = new UI.Panel(); - option.setClass( 'option' ); - option.setTextContent( 'Flatten' ); - option.onClick( function () { - - var object = editor.selected; - - if ( object.parent === undefined ) return; // avoid flattening the camera or scene - - if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return; - - var geometry = object.geometry; - - geometry.applyMatrix( object.matrix ); - geometry.verticesNeedUpdate = true; - geometry.normalsNeedUpdate = true; - - object.position.set( 0, 0, 0 ); - object.rotation.set( 0, 0, 0 ); - object.scale.set( 1, 1, 1 ); - - editor.signals.objectChanged.dispatch( object ); - - } ); - options.add( option ); - return container; }; diff --git a/editor/js/Player.js b/editor/js/Player.js index 72194b8a00242e..3b8fe27fe35c85 100644 --- a/editor/js/Player.js +++ b/editor/js/Player.js @@ -19,7 +19,7 @@ var Player = function ( editor ) { if ( player.dom === undefined ) return; - player.setSize( container.dom.offsetWidth, container.dom.offsetHeight ); + player.setSize( container.dom.clientWidth, container.dom.clientHeight ); } ); @@ -27,9 +27,8 @@ var Player = function ( editor ) { container.setDisplay( '' ); - player.setVR( editor.config.getKey( 'project/vr' ) ); player.load( editor.toJSON() ); - player.setSize( container.dom.offsetWidth, container.dom.offsetHeight ); + player.setSize( container.dom.clientWidth, container.dom.clientHeight ); player.play(); container.dom.appendChild( player.dom ); diff --git a/editor/js/Script.js b/editor/js/Script.js index 80fa696be5449b..abcb6d24924543 100644 --- a/editor/js/Script.js +++ b/editor/js/Script.js @@ -15,7 +15,7 @@ var Script = function ( editor ) { var header = new UI.Panel(); header.setPadding( '10px' ); container.add( header ); - + var title = new UI.Text().setColor( '#fff' ); header.add( title ); @@ -59,16 +59,101 @@ var Script = function ( editor ) { clearTimeout( delay ); delay = setTimeout( function () { - currentScript.source = codemirror.getValue(); + var value = codemirror.getValue(); + + if ( validate( value ) ) { + + currentScript.source = value; + signals.scriptChanged.dispatch( currentScript ); - signals.scriptChanged.dispatch( currentScript ); + } }, 300 ); }); + // validate + + var errorLines = []; + var widgets = []; + + var validate = function ( string ) { + + var syntax, errors; + + return codemirror.operation( function () { + + while ( errorLines.length > 0 ) { + + codemirror.removeLineClass( errorLines.shift(), 'background', 'errorLine' ); + + } + + for ( var i = 0; i < widgets.length; i ++ ) { + + codemirror.removeLineWidget( widgets[ i ] ); + + } + + widgets.length = 0; + + // + + try { + + syntax = esprima.parse( string, { tolerant: true } ); + errors = syntax.errors; + + for ( var i = 0; i < errors.length; i ++ ) { + + var error = errors[ i ]; + + var message = document.createElement( 'div' ); + message.className = 'esprima-error'; + message.textContent = error.message.replace(/Line [0-9]+: /, ''); + + var lineNumber = error.lineNumber - 1; + errorLines.push( lineNumber ); + + codemirror.addLineClass( lineNumber, 'background', 'errorLine' ); + + var widget = codemirror.addLineWidget( + lineNumber, + message + ); + + widgets.push( widget ); + + } + + } catch ( error ) { + + var message = document.createElement( 'div' ); + message.className = 'esprima-error'; + message.textContent = error.message.replace(/Line [0-9]+: /, ''); + + var lineNumber = error.lineNumber - 1; + errorLines.push( lineNumber ); + + codemirror.addLineClass( lineNumber, 'background', 'errorLine' ); + + var widget = codemirror.addLineWidget( + lineNumber, + message + ); + + widgets.push( widget ); + + } + + return errorLines.length === 0; + + }); + + }; + // - + signals.editorCleared.add( function () { container.setDisplay( 'none' ); diff --git a/editor/js/Sidebar.Geometry.js b/editor/js/Sidebar.Geometry.js index 1fd62143bef2ad..bc3efd9e40e1be 100644 --- a/editor/js/Sidebar.Geometry.js +++ b/editor/js/Sidebar.Geometry.js @@ -17,6 +17,56 @@ Sidebar.Geometry = function ( editor ) { var geometryType = new UI.Text().setTextTransform( 'uppercase' ); container.addStatic( geometryType ); + + // Actions + + var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' ); + objectActions.setOptions( { + + 'Actions': 'Actions', + 'Flatten': 'Flatten' + + } ); + objectActions.onClick( function ( event ) { + + event.stopPropagation(); // Avoid panel collapsing + + } ); + objectActions.onChange( function ( event ) { + + var object = editor.selected; + + switch ( this.getValue() ) { + + case 'Flatten': + + var object = editor.selected; + + if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return; + + var geometry = object.geometry; + + geometry.applyMatrix( object.matrix ); + geometry.verticesNeedUpdate = true; + geometry.normalsNeedUpdate = true; + + object.position.set( 0, 0, 0 ); + object.rotation.set( 0, 0, 0 ); + object.scale.set( 1, 1, 1 ); + + editor.signals.objectChanged.dispatch( object ); + + break; + + } + + this.setValue( 'Actions' ); + + signals.objectChanged.dispatch( object ); + + } ); + container.addStatic( objectActions ); + container.add( new UI.Break() ); // uuid diff --git a/editor/js/Sidebar.Object3D.js b/editor/js/Sidebar.Object3D.js index 4bea46dc1ed46b..0aae11c0e456f6 100644 --- a/editor/js/Sidebar.Object3D.js +++ b/editor/js/Sidebar.Object3D.js @@ -18,6 +18,8 @@ Sidebar.Object3D = function ( editor ) { var objectType = new UI.Text().setTextTransform( 'uppercase' ); container.addStatic( objectType ); + // Actions + var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' ); objectActions.setOptions( { diff --git a/editor/js/libs/app.js b/editor/js/libs/app.js index 5e1bbdd389fa8b..04ec67ca354e3d 100644 --- a/editor/js/libs/app.js +++ b/editor/js/libs/app.js @@ -22,12 +22,15 @@ var APP = { this.load = function ( json ) { + vr = json.project.vr; + renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setClearColor( 0x000000 ); renderer.setPixelRatio( window.devicePixelRatio ); + this.dom = renderer.domElement; - camera = loader.parse( json.camera ); - scene = loader.parse( json.scene ); + this.setScene( loader.parse( json.scene ) ); + this.setCamera( loader.parse( json.camera ) ); events = { keydown: [], @@ -72,42 +75,62 @@ var APP = { } - this.dom = renderer.domElement; + }; + + this.setCamera = function ( value ) { + + camera = value; + camera.aspect = this.width / this.height; + camera.updateProjectionMatrix(); + if ( vr === true ) { + if ( camera.parent === undefined ) { + + // camera needs to be in the scene so camera2 matrix updates + + scene.add( camera ); + + } + + var camera2 = camera.clone(); + camera.add( camera2 ); + + camera = camera2; + controls = new THREE.VRControls( camera ); renderer = new THREE.VREffect( renderer ); - this.dom.addEventListener( 'dblclick', function () { + document.addEventListener( 'keyup', function ( event ) { - renderer.setFullScreen( true ); + switch ( event.keyCode ) { + case 90: + controls.zeroSensor(); + break; + } } ); - } - }; + this.dom.addEventListener( 'dblclick', function () { - this.setCamera = function ( value ) { + renderer.setFullScreen( true ); - camera = value; - camera.aspect = this.width / this.height; - camera.updateProjectionMatrix(); + } ); + + } }; - this.setVR = function ( value ) { + this.setScene = function ( value ) { - vr = value; + scene = value; - }; + }, this.setSize = function ( width, height ) { - if ( vr ) { - width = 1280; - height = 800; - } + if ( renderer._fullScreen ) return; this.width = width; this.height = height; diff --git a/editor/js/libs/esprima.js b/editor/js/libs/esprima.js new file mode 100644 index 00000000000000..a1f80c83e13445 --- /dev/null +++ b/editor/js/libs/esprima.js @@ -0,0 +1,4156 @@ +/* + Copyright (C) 2013 Ariya Hidayat + Copyright (C) 2013 Thaddee Tyl + Copyright (C) 2013 Mathias Bynens + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + + /* istanbul ignore next */ + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PlaceHolders, + PropertyKind, + Messages, + Regex, + source, + strict, + index, + lineNumber, + lineStart, + length, + lookahead, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + + // A function following one of those tokens is an expression. + FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new', + 'return', 'case', 'delete', 'throw', 'void', + // assignment operators + '=', '+=', '-=', '*=', '/=', '%=', '<<=', '>>=', '>>>=', + '&=', '|=', '^=', ',', + // binary/unary operators + '+', '-', '*', '/', '%', '++', '--', '<<', '>>', '>>>', '&', + '|', '^', '!', '~', '&&', '||', '?', ':', '===', '==', '>=', + '<=', '<', '>', '!=', '!==']; + + Syntax = { + AssignmentExpression: 'AssignmentExpression', + ArrayExpression: 'ArrayExpression', + ArrowFunctionExpression: 'ArrowFunctionExpression', + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DoWhileStatement: 'DoWhileStatement', + DebuggerStatement: 'DebuggerStatement', + EmptyStatement: 'EmptyStatement', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement' + }; + + PlaceHolders = { + ArrowParameterPlaceHolder: { + type: 'ArrowParameterPlaceHolder' + } + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalReturn: 'Illegal return statement', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]'), + NonAsciiIdentifierPart: new RegExp('[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19D9\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u2E2F\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099\u309A\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + /* istanbul ignore if */ + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 0x30 && ch <= 0x39); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) || + (ch >= 0x1680 && [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) >= 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 0x24) || (ch === 0x5F) || // $ (dollar) and _ (underscore) + (ch >= 0x41 && ch <= 0x5A) || // A..Z + (ch >= 0x61 && ch <= 0x7A) || // a..z + (ch >= 0x30 && ch <= 0x39) || // 0..9 + (ch === 0x5C) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + // 'const' is specialized as Keyword in V8. + // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next. + // Some others are from future reserved words. + + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // 7.4 Comments + + function addComment(type, value, start, end, loc) { + var comment; + + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (state.lastCommentStart >= start) { + return; + } + state.lastCommentStart = start; + + comment = { + type: type, + value: value + }; + if (extra.range) { + comment.range = [start, end]; + } + if (extra.loc) { + comment.loc = loc; + } + extra.comments.push(comment); + if (extra.attachComment) { + extra.leadingComments.push(comment); + extra.trailingComments.push(comment); + } + } + + function skipSingleLineComment(offset) { + var start, loc, ch, comment; + + start = index - offset; + loc = { + start: { + line: lineNumber, + column: index - lineStart - offset + } + }; + + while (index < length) { + ch = source.charCodeAt(index); + ++index; + if (isLineTerminator(ch)) { + if (extra.comments) { + comment = source.slice(start + offset, index - 1); + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + addComment('Line', comment, start, index - 1, loc); + } + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + return; + } + } + + if (extra.comments) { + comment = source.slice(start + offset, index); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Line', comment, start, index, loc); + } + } + + function skipMultiLineComment() { + var start, loc, ch, comment; + + if (extra.comments) { + start = index - 2; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (isLineTerminator(ch)) { + if (ch === 0x0D && source.charCodeAt(index + 1) === 0x0A) { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwUnexpectedToken(); + } + } else if (ch === 0x2A) { + // Block comment ends with '*/'. + if (source.charCodeAt(index + 1) === 0x2F) { + ++index; + ++index; + if (extra.comments) { + comment = source.slice(start + 2, index - 2); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + } + return; + } + ++index; + } else { + ++index; + } + } + + throwUnexpectedToken(); + } + + function skipComment() { + var ch, start; + + start = (index === 0); + while (index < length) { + ch = source.charCodeAt(index); + + if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === 0x0D && source.charCodeAt(index) === 0x0A) { + ++index; + } + ++lineNumber; + lineStart = index; + start = true; + } else if (ch === 0x2F) { // U+002F is '/' + ch = source.charCodeAt(index + 1); + if (ch === 0x2F) { + ++index; + ++index; + skipSingleLineComment(2); + start = true; + } else if (ch === 0x2A) { // U+002A is '*' + ++index; + ++index; + skipMultiLineComment(); + } else { + break; + } + } else if (start && ch === 0x2D) { // U+002D is '-' + // U+003E is '>' + if ((source.charCodeAt(index + 1) === 0x2D) && (source.charCodeAt(index + 2) === 0x3E)) { + // '-->' is a single-line comment + index += 3; + skipSingleLineComment(3); + } else { + break; + } + } else if (ch === 0x3C) { // U+003C is '<' + if (source.slice(index + 1, index + 4) === '!--') { + ++index; // `<` + ++index; // `!` + ++index; // `-` + ++index; // `-` + skipSingleLineComment(4); + } else { + break; + } + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code, cu1, cu2; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwUnexpectedToken(); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwUnexpectedToken(); + } + + // UTF-16 Encoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } + cu1 = ((code - 0x10000) >> 10) + 0xD800; + cu2 = ((code - 0x10000) & 1023) + 0xDC00; + return String.fromCharCode(cu1, cu2); + } + + function getEscapedIdentifier() { + var ch, id; + + ch = source.charCodeAt(index++); + id = String.fromCharCode(ch); + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (ch === 0x5C) { + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { + throwUnexpectedToken(); + } + id = ch; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (!isIdentifierPart(ch)) { + break; + } + ++index; + id += String.fromCharCode(ch); + + // '\u' (U+005C, U+0075) denotes an escaped character. + if (ch === 0x5C) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 0x75) { + throwUnexpectedToken(); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { + throwUnexpectedToken(); + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 0x5C) { + // Blackslash (U+005C) marks Unicode escape sequence. + index = start; + return getEscapedIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (U+005C) starts an escaped character. + id = (source.charCodeAt(index) === 0x5C) ? getEscapedIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + code = source.charCodeAt(index), + code2, + ch1 = source[index], + ch2, + ch3, + ch4; + + switch (code) { + + // Check for most common single-character punctuators. + case 0x2E: // . dot + case 0x28: // ( open bracket + case 0x29: // ) close bracket + case 0x3B: // ; semicolon + case 0x2C: // , comma + case 0x7B: // { open curly brace + case 0x7D: // } close curly brace + case 0x5B: // [ + case 0x5D: // ] + case 0x3A: // : + case 0x3F: // ? + case 0x7E: // ~ + ++index; + if (extra.tokenize) { + if (code === 0x28) { + extra.openParenToken = extra.tokens.length; + } else if (code === 0x7B) { + extra.openCurlyToken = extra.tokens.length; + } + } + return { + type: Token.Punctuator, + value: String.fromCharCode(code), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + + default: + code2 = source.charCodeAt(index + 1); + + // '=' (U+003D) marks an assignment or comparison operator. + if (code2 === 0x3D) { + switch (code) { + case 0x2B: // + + case 0x2D: // - + case 0x2F: // / + case 0x3C: // < + case 0x3E: // > + case 0x5E: // ^ + case 0x7C: // | + case 0x25: // % + case 0x26: // & + case 0x2A: // * + index += 2; + return { + type: Token.Punctuator, + value: String.fromCharCode(code) + String.fromCharCode(code2), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + + case 0x21: // ! + case 0x3D: // = + index += 2; + + // !== and === + if (source.charCodeAt(index) === 0x3D) { + ++index; + } + return { + type: Token.Punctuator, + value: source.slice(start, index), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + } + } + + // 4-character punctuator: >>>= + + ch4 = source.substr(index, 4); + + if (ch4 === '>>>=') { + index += 4; + return { + type: Token.Punctuator, + value: ch4, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // 3-character punctuators: === !== >>> <<= >>= + + ch3 = ch4.substr(0, 3); + + if (ch3 === '>>>' || ch3 === '<<=' || ch3 === '>>=') { + index += 3; + return { + type: Token.Punctuator, + value: ch3, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // Other 2-character punctuators: ++ -- << >> && || + ch2 = ch3.substr(0, 2); + + if ((ch1 === ch2[1] && ('+-<>&|'.indexOf(ch1) >= 0)) || ch2 === '=>') { + index += 2; + return { + type: Token.Punctuator, + value: ch2, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // 1-character punctuators: < > = ! + - * % & | ^ / + + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + throwUnexpectedToken(); + } + + // 7.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanBinaryLiteral(start) { + var ch, number; + + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwUnexpectedToken(); + } + + if (index < length) { + ch = source.charCodeAt(index); + /* istanbul ignore else */ + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwUnexpectedToken(); + } + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwUnexpectedToken(); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function isImplicitOctalLiteral() { + var i, ch; + + // Implicit octal, unless there is a non-octal digit. + // (Annex B.1.1 on Numeric Literals) + for (i = index + 1; i < length; ++i) { + ch = source[i]; + if (ch === '8' || ch === '9') { + return false; + } + if (!isOctalDigit(ch)) { + return true; + } + } + + return true; + } + + function scanNumericLiteral() { + var number, start, ch; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + return scanBinaryLiteral(start); + } + if (ch === 'o' || ch === 'O') { + return scanOctalLiteral(ch, start); + } + + if (isOctalDigit(ch)) { + if (isImplicitOctalLiteral()) { + return scanOctalLiteral(ch, start); + } + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwUnexpectedToken(); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwUnexpectedToken(); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false, startLineNumber, startLineStart; + startLineNumber = lineNumber; + startLineStart = lineStart; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + } + break; + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + lineStart = index; + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwUnexpectedToken(); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + startLineNumber: startLineNumber, + startLineStart: startLineStart, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + function testRegExp(pattern, flags) { + var tmp = pattern, + value; + + if (flags.indexOf('u') >= 0) { + // Replace each astral symbol and every Unicode code point + // escape sequence with a single ASCII symbol to avoid throwing on + // regular expressions that are only valid in combination with the + // `/u` flag. + // Note: replacing with the ASCII symbol `x` might cause false + // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a + // perfectly valid pattern that is equivalent to `[a-b]`, but it + // would be replaced by `[x-b]` which throws an error. + tmp = tmp + .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) { + if (parseInt($1, 16) <= 0x10FFFF) { + return 'x'; + } + throwError(Messages.InvalidRegExp); + }) + .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x'); + } + + // First, detect invalid regular expressions. + try { + value = new RegExp(tmp); + } catch (e) { + throwError(Messages.InvalidRegExp); + } + + // Return a regular expression object for this pattern-flag pair, or + // `null` in case the current environment doesn't support the flags it + // uses. + try { + return new RegExp(pattern, flags); + } catch (exception) { + return null; + } + } + + function scanRegExpBody() { + var ch, str, classMarker, terminated, body; + + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + classMarker = false; + terminated = false; + while (index < length) { + ch = source[index++]; + str += ch; + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwError(Messages.UnterminatedRegExp); + } + str += ch; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwError(Messages.UnterminatedRegExp); + } else if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } + } + } + + if (!terminated) { + throwError(Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + body = str.substr(1, str.length - 2); + return { + value: body, + literal: str + }; + } + + function scanRegExpFlags() { + var ch, str, flags, restore; + + str = ''; + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + tolerateUnexpectedToken(); + } else { + str += '\\'; + tolerateUnexpectedToken(); + } + } else { + flags += ch; + str += ch; + } + } + + return { + value: flags, + literal: str + }; + } + + function scanRegExp() { + var start, body, flags, value; + + lookahead = null; + skipComment(); + start = index; + + body = scanRegExpBody(); + flags = scanRegExpFlags(); + value = testRegExp(body.value, flags.value); + + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + lineNumber: lineNumber, + lineStart: lineStart, + start: start, + end: index + }; + } + + return { + literal: body.literal + flags.literal, + value: value, + regex: { + pattern: body.value, + flags: flags.value + }, + start: start, + end: index + }; + } + + function collectRegex() { + var pos, loc, regex, token; + + skipComment(); + + pos = index; + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + regex = scanRegExp(); + + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + /* istanbul ignore next */ + if (!extra.tokenize) { + // Pop the previous token, which is likely '/' or '/=' + if (extra.tokens.length > 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + regex: regex.regex, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advanceSlash() { + var prevToken, + checkToken; + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + prevToken = extra.tokens[extra.tokens.length - 1]; + if (!prevToken) { + // Nothing before that: it cannot be a division. + return collectRegex(); + } + if (prevToken.type === 'Punctuator') { + if (prevToken.value === ']') { + return scanPunctuator(); + } + if (prevToken.value === ')') { + checkToken = extra.tokens[extra.openParenToken - 1]; + if (checkToken && + checkToken.type === 'Keyword' && + (checkToken.value === 'if' || + checkToken.value === 'while' || + checkToken.value === 'for' || + checkToken.value === 'with')) { + return collectRegex(); + } + return scanPunctuator(); + } + if (prevToken.value === '}') { + // Dividing a function by anything makes little sense, + // but we have to check for that. + if (extra.tokens[extra.openCurlyToken - 3] && + extra.tokens[extra.openCurlyToken - 3].type === 'Keyword') { + // Anonymous function. + checkToken = extra.tokens[extra.openCurlyToken - 4]; + if (!checkToken) { + return scanPunctuator(); + } + } else if (extra.tokens[extra.openCurlyToken - 4] && + extra.tokens[extra.openCurlyToken - 4].type === 'Keyword') { + // Named function. + checkToken = extra.tokens[extra.openCurlyToken - 5]; + if (!checkToken) { + return collectRegex(); + } + } else { + return scanPunctuator(); + } + // checkToken determines whether the function is + // a declaration or an expression. + if (FnExprTokens.indexOf(checkToken.value) >= 0) { + // It is an expression. + return scanPunctuator(); + } + // It is a declaration. + return collectRegex(); + } + return collectRegex(); + } + if (prevToken.type === 'Keyword' && prevToken.value !== 'this') { + return collectRegex(); + } + return scanPunctuator(); + } + + function advance() { + var ch; + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + start: index, + end: index + }; + } + + ch = source.charCodeAt(index); + + if (isIdentifierStart(ch)) { + return scanIdentifier(); + } + + // Very common: ( and ) and ; + if (ch === 0x28 || ch === 0x29 || ch === 0x3B) { + return scanPunctuator(); + } + + // String literal starts with single quote (U+0027) or double quote (U+0022). + if (ch === 0x27 || ch === 0x22) { + return scanStringLiteral(); + } + + + // Dot (.) U+002E can also start a floating-point number, hence the need + // to check the next character. + if (ch === 0x2E) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + // Slash (/) U+002F can also start a regex. + if (extra.tokenize && ch === 0x2F) { + return advanceSlash(); + } + + return scanPunctuator(); + } + + function collectToken() { + var loc, token, value, entry; + + skipComment(); + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + + token = advance(); + loc.end = { + line: lineNumber, + column: index - lineStart + }; + + if (token.type !== Token.EOF) { + value = source.slice(token.start, token.end); + entry = { + type: TokenName[token.type], + value: value, + range: [token.start, token.end], + loc: loc + }; + if (token.regex) { + entry.regex = { + pattern: token.regex.pattern, + flags: token.regex.flags + }; + } + extra.tokens.push(entry); + } + + return token; + } + + function lex() { + var token; + + token = lookahead; + index = token.end; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + + index = token.end; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + return token; + } + + function peek() { + var pos, line, start; + + pos = index; + line = lineNumber; + start = lineStart; + lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance(); + index = pos; + lineNumber = line; + lineStart = start; + } + + function Position() { + this.line = lineNumber; + this.column = index - lineStart; + } + + function SourceLocation() { + this.start = new Position(); + this.end = null; + } + + function WrappingSourceLocation(startToken) { + if (startToken.type === Token.StringLiteral) { + this.start = { + line: startToken.startLineNumber, + column: startToken.start - startToken.startLineStart + }; + } else { + this.start = { + line: startToken.lineNumber, + column: startToken.start - startToken.lineStart + }; + } + this.end = null; + } + + function Node() { + // Skip comment. + index = lookahead.start; + if (lookahead.type === Token.StringLiteral) { + lineNumber = lookahead.startLineNumber; + lineStart = lookahead.startLineStart; + } else { + lineNumber = lookahead.lineNumber; + lineStart = lookahead.lineStart; + } + if (extra.range) { + this.range = [index, 0]; + } + if (extra.loc) { + this.loc = new SourceLocation(); + } + } + + function WrappingNode(startToken) { + if (extra.range) { + this.range = [startToken.start, 0]; + } + if (extra.loc) { + this.loc = new WrappingSourceLocation(startToken); + } + } + + WrappingNode.prototype = Node.prototype = { + + processComment: function () { + var lastChild, + leadingComments, + trailingComments, + bottomRight = extra.bottomRightStack, + i, + comment, + last = bottomRight[bottomRight.length - 1]; + + if (this.type === Syntax.Program) { + if (this.body.length > 0) { + return; + } + } + + if (extra.trailingComments.length > 0) { + trailingComments = []; + for (i = extra.trailingComments.length - 1; i >= 0; --i) { + comment = extra.trailingComments[i]; + if (comment.range[0] >= this.range[1]) { + trailingComments.unshift(comment); + extra.trailingComments.splice(i, 1); + } + } + extra.trailingComments = []; + } else { + if (last && last.trailingComments && last.trailingComments[0].range[0] >= this.range[1]) { + trailingComments = last.trailingComments; + delete last.trailingComments; + } + } + + // Eating the stack. + if (last) { + while (last && last.range[0] >= this.range[0]) { + lastChild = last; + last = bottomRight.pop(); + } + } + + if (lastChild) { + if (lastChild.leadingComments && lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] <= this.range[0]) { + this.leadingComments = lastChild.leadingComments; + lastChild.leadingComments = undefined; + } + } else if (extra.leadingComments.length > 0) { + leadingComments = []; + for (i = extra.leadingComments.length - 1; i >= 0; --i) { + comment = extra.leadingComments[i]; + if (comment.range[1] <= this.range[0]) { + leadingComments.unshift(comment); + extra.leadingComments.splice(i, 1); + } + } + } + + + if (leadingComments && leadingComments.length > 0) { + this.leadingComments = leadingComments; + } + if (trailingComments && trailingComments.length > 0) { + this.trailingComments = trailingComments; + } + + bottomRight.push(this); + }, + + finish: function () { + if (extra.range) { + this.range[1] = index; + } + if (extra.loc) { + this.loc.end = new Position(); + if (extra.source) { + this.loc.source = extra.source; + } + } + + if (extra.attachComment) { + this.processComment(); + } + }, + + finishArrayExpression: function (elements) { + this.type = Syntax.ArrayExpression; + this.elements = elements; + this.finish(); + return this; + }, + + finishArrowFunctionExpression: function (params, defaults, body, expression) { + this.type = Syntax.ArrowFunctionExpression; + this.id = null; + this.params = params; + this.defaults = defaults; + this.body = body; + this.rest = null; + this.generator = false; + this.expression = expression; + this.finish(); + return this; + }, + + finishAssignmentExpression: function (operator, left, right) { + this.type = Syntax.AssignmentExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBinaryExpression: function (operator, left, right) { + this.type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : Syntax.BinaryExpression; + this.operator = operator; + this.left = left; + this.right = right; + this.finish(); + return this; + }, + + finishBlockStatement: function (body) { + this.type = Syntax.BlockStatement; + this.body = body; + this.finish(); + return this; + }, + + finishBreakStatement: function (label) { + this.type = Syntax.BreakStatement; + this.label = label; + this.finish(); + return this; + }, + + finishCallExpression: function (callee, args) { + this.type = Syntax.CallExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishCatchClause: function (param, body) { + this.type = Syntax.CatchClause; + this.param = param; + this.body = body; + this.finish(); + return this; + }, + + finishConditionalExpression: function (test, consequent, alternate) { + this.type = Syntax.ConditionalExpression; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishContinueStatement: function (label) { + this.type = Syntax.ContinueStatement; + this.label = label; + this.finish(); + return this; + }, + + finishDebuggerStatement: function () { + this.type = Syntax.DebuggerStatement; + this.finish(); + return this; + }, + + finishDoWhileStatement: function (body, test) { + this.type = Syntax.DoWhileStatement; + this.body = body; + this.test = test; + this.finish(); + return this; + }, + + finishEmptyStatement: function () { + this.type = Syntax.EmptyStatement; + this.finish(); + return this; + }, + + finishExpressionStatement: function (expression) { + this.type = Syntax.ExpressionStatement; + this.expression = expression; + this.finish(); + return this; + }, + + finishForStatement: function (init, test, update, body) { + this.type = Syntax.ForStatement; + this.init = init; + this.test = test; + this.update = update; + this.body = body; + this.finish(); + return this; + }, + + finishForInStatement: function (left, right, body) { + this.type = Syntax.ForInStatement; + this.left = left; + this.right = right; + this.body = body; + this.each = false; + this.finish(); + return this; + }, + + finishFunctionDeclaration: function (id, params, defaults, body) { + this.type = Syntax.FunctionDeclaration; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.rest = null; + this.generator = false; + this.expression = false; + this.finish(); + return this; + }, + + finishFunctionExpression: function (id, params, defaults, body) { + this.type = Syntax.FunctionExpression; + this.id = id; + this.params = params; + this.defaults = defaults; + this.body = body; + this.rest = null; + this.generator = false; + this.expression = false; + this.finish(); + return this; + }, + + finishIdentifier: function (name) { + this.type = Syntax.Identifier; + this.name = name; + this.finish(); + return this; + }, + + finishIfStatement: function (test, consequent, alternate) { + this.type = Syntax.IfStatement; + this.test = test; + this.consequent = consequent; + this.alternate = alternate; + this.finish(); + return this; + }, + + finishLabeledStatement: function (label, body) { + this.type = Syntax.LabeledStatement; + this.label = label; + this.body = body; + this.finish(); + return this; + }, + + finishLiteral: function (token) { + this.type = Syntax.Literal; + this.value = token.value; + this.raw = source.slice(token.start, token.end); + if (token.regex) { + this.regex = token.regex; + } + this.finish(); + return this; + }, + + finishMemberExpression: function (accessor, object, property) { + this.type = Syntax.MemberExpression; + this.computed = accessor === '['; + this.object = object; + this.property = property; + this.finish(); + return this; + }, + + finishNewExpression: function (callee, args) { + this.type = Syntax.NewExpression; + this.callee = callee; + this.arguments = args; + this.finish(); + return this; + }, + + finishObjectExpression: function (properties) { + this.type = Syntax.ObjectExpression; + this.properties = properties; + this.finish(); + return this; + }, + + finishPostfixExpression: function (operator, argument) { + this.type = Syntax.UpdateExpression; + this.operator = operator; + this.argument = argument; + this.prefix = false; + this.finish(); + return this; + }, + + finishProgram: function (body) { + this.type = Syntax.Program; + this.body = body; + this.finish(); + return this; + }, + + finishProperty: function (kind, key, value, method, shorthand) { + this.type = Syntax.Property; + this.key = key; + this.value = value; + this.kind = kind; + this.method = method; + this.shorthand = shorthand; + this.finish(); + return this; + }, + + finishReturnStatement: function (argument) { + this.type = Syntax.ReturnStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishSequenceExpression: function (expressions) { + this.type = Syntax.SequenceExpression; + this.expressions = expressions; + this.finish(); + return this; + }, + + finishSwitchCase: function (test, consequent) { + this.type = Syntax.SwitchCase; + this.test = test; + this.consequent = consequent; + this.finish(); + return this; + }, + + finishSwitchStatement: function (discriminant, cases) { + this.type = Syntax.SwitchStatement; + this.discriminant = discriminant; + this.cases = cases; + this.finish(); + return this; + }, + + finishThisExpression: function () { + this.type = Syntax.ThisExpression; + this.finish(); + return this; + }, + + finishThrowStatement: function (argument) { + this.type = Syntax.ThrowStatement; + this.argument = argument; + this.finish(); + return this; + }, + + finishTryStatement: function (block, guardedHandlers, handlers, finalizer) { + this.type = Syntax.TryStatement; + this.block = block; + this.guardedHandlers = guardedHandlers; + this.handlers = handlers; + this.finalizer = finalizer; + this.finish(); + return this; + }, + + finishUnaryExpression: function (operator, argument) { + this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression; + this.operator = operator; + this.argument = argument; + this.prefix = true; + this.finish(); + return this; + }, + + finishVariableDeclaration: function (declarations, kind) { + this.type = Syntax.VariableDeclaration; + this.declarations = declarations; + this.kind = kind; + this.finish(); + return this; + }, + + finishVariableDeclarator: function (id, init) { + this.type = Syntax.VariableDeclarator; + this.id = id; + this.init = init; + this.finish(); + return this; + }, + + finishWhileStatement: function (test, body) { + this.type = Syntax.WhileStatement; + this.test = test; + this.body = body; + this.finish(); + return this; + }, + + finishWithStatement: function (object, body) { + this.type = Syntax.WithStatement; + this.object = object; + this.body = body; + this.finish(); + return this; + } + }; + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + function createError(line, pos, description) { + var error = new Error('Line ' + line + ': ' + description); + error.index = pos; + error.lineNumber = line; + error.column = pos - lineStart + 1; + error.description = description; + return error; + } + + // Throw an exception + + function throwError(messageFormat) { + var args, msg; + + args = Array.prototype.slice.call(arguments, 1); + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + throw createError(lineNumber, index, msg); + } + + function tolerateError(messageFormat) { + var args, msg, error; + + args = Array.prototype.slice.call(arguments, 1); + /* istanbul ignore next */ + msg = messageFormat.replace(/%(\d)/g, + function (whole, idx) { + assert(idx < args.length, 'Message reference must be in range'); + return args[idx]; + } + ); + + error = createError(lineNumber, index, msg); + if (extra.errors) { + extra.errors.push(error); + } else { + throw error; + } + } + + // Throw an exception because of the token. + + function unexpectedTokenError(token, message) { + var msg = Messages.UnexpectedToken; + + if (token) { + msg = message ? message : + (token.type === Token.EOF) ? Messages.UnexpectedEOS : + (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier : + (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber : + (token.type === Token.StringLiteral) ? Messages.UnexpectedString : + Messages.UnexpectedToken; + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + msg = Messages.UnexpectedReserved; + } else if (strict && isStrictModeReservedWord(token.value)) { + msg = Messages.StrictReservedWord; + } + } + } + + msg = msg.replace('%0', token ? token.value : 'ILLEGAL'); + + return (token && typeof token.lineNumber === 'number') ? + createError(token.lineNumber, token.start, msg) : + createError(lineNumber, index, msg); + } + + function throwUnexpectedToken(token, message) { + throw unexpectedTokenError(token, message); + } + + function tolerateUnexpectedToken(token, message) { + var error = unexpectedTokenError(token, message); + if (extra.errors) { + extra.errors.push(error); + } else { + throw error; + } + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpectedToken(token); + } + } + + /** + * @name expectCommaSeparator + * @description Quietly expect a comma when in tolerant mode, otherwise delegates + * to expect(value) + * @since 2.0 + */ + function expectCommaSeparator() { + var token; + + if (extra.errors) { + token = lookahead; + if (token.type === Token.Punctuator && token.value === ',') { + lex(); + } else if (token.type === Token.Punctuator && token.value === ';') { + lex(); + tolerateUnexpectedToken(token); + } else { + tolerateUnexpectedToken(token, Messages.UnexpectedToken); + } + } else { + expect(','); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpectedToken(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var line, oldIndex = index, oldLineNumber = lineNumber, + oldLineStart = lineStart, oldLookahead = lookahead; + + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(index) === 0x3B || match(';')) { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + index = oldIndex; + lineNumber = oldLineNumber; + lineStart = oldLineStart; + lookahead = oldLookahead; + return; + } + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpectedToken(lookahead); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = [], node = new Node(); + + expect('['); + + while (!match(']')) { + if (match(',')) { + lex(); + elements.push(null); + } else { + elements.push(parseAssignmentExpression()); + + if (!match(']')) { + expect(','); + } + } + } + + lex(); + + return node.finishArrayExpression(elements); + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(param, first) { + var previousStrict, body, node = new Node(); + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (first && strict && isRestrictedWord(param[0].name)) { + tolerateUnexpectedToken(first, Messages.StrictParamName); + } + strict = previousStrict; + return node.finishFunctionExpression(null, param, [], body); + } + + function parsePropertyMethodFunction() { + var previousStrict, param, method; + + previousStrict = strict; + strict = true; + param = parseParams(); + method = parsePropertyFunction(param.params); + strict = previousStrict; + + return method; + } + + function parseObjectPropertyKey() { + var token, node = new Node(); + + token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + tolerateUnexpectedToken(token, Messages.StrictOctalLiteral); + } + return node.finishLiteral(token); + } + + return node.finishIdentifier(token.value); + } + + function parseObjectProperty() { + var token, key, id, value, param, node = new Node(); + + token = lookahead; + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + value = parsePropertyFunction([]); + return node.finishProperty('get', key, value, false, false); + } + if (token.value === 'set' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead; + if (token.type !== Token.Identifier) { + expect(')'); + tolerateUnexpectedToken(token); + value = parsePropertyFunction([]); + } else { + param = [ parseVariableIdentifier() ]; + expect(')'); + value = parsePropertyFunction(param, token); + } + return node.finishProperty('set', key, value, false, false); + } + if (match(':')) { + lex(); + value = parseAssignmentExpression(); + return node.finishProperty('init', id, value, false, false); + } + if (match('(')) { + value = parsePropertyMethodFunction(); + return node.finishProperty('init', id, value, true, false); + } + + value = id; + return node.finishProperty('init', id, value, false, true); + } + if (token.type === Token.EOF || token.type === Token.Punctuator) { + throwUnexpectedToken(token); + } else { + key = parseObjectPropertyKey(); + if (match(':')) { + lex(); + value = parseAssignmentExpression(); + return node.finishProperty('init', key, value, false, false); + } + if (match('(')) { + value = parsePropertyMethodFunction(); + return node.finishProperty('init', key, value, true, false); + } + throwUnexpectedToken(lex()); + } + } + + function parseObjectInitialiser() { + var properties = [], property, name, key, kind, map = {}, toString = String, node = new Node(); + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + + key = '$' + name; + if (Object.prototype.hasOwnProperty.call(map, key)) { + if (map[key] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + tolerateError(Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + tolerateError(Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + tolerateError(Messages.AccessorDataProperty); + } else if (map[key] & kind) { + tolerateError(Messages.AccessorGetSet); + } + } + map[key] |= kind; + } else { + map[key] = kind; + } + + properties.push(property); + + if (!match('}')) { + expectCommaSeparator(); + } + } + + expect('}'); + + return node.finishObjectExpression(properties); + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + if (match(')')) { + lex(); + return PlaceHolders.ArrowParameterPlaceHolder; + } + + ++state.parenthesisCount; + + expr = parseExpression(); + + expect(')'); + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var type, token, expr, node; + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + type = lookahead.type; + node = new Node(); + + if (type === Token.Identifier) { + expr = node.finishIdentifier(lex().value); + } else if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && lookahead.octal) { + tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral); + } + expr = node.finishLiteral(lex()); + } else if (type === Token.Keyword) { + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + if (matchKeyword('this')) { + lex(); + expr = node.finishThisExpression(); + } else { + throwUnexpectedToken(lex()); + } + } else if (type === Token.BooleanLiteral) { + token = lex(); + token.value = (token.value === 'true'); + expr = node.finishLiteral(token); + } else if (type === Token.NullLiteral) { + token = lex(); + token.value = null; + expr = node.finishLiteral(token); + } else if (match('/') || match('/=')) { + if (typeof extra.tokens !== 'undefined') { + expr = node.finishLiteral(collectRegex()); + } else { + expr = node.finishLiteral(scanRegExp()); + } + peek(); + } else { + throwUnexpectedToken(lex()); + } + + return expr; + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = []; + + expect('('); + + if (!match(')')) { + while (index < length) { + args.push(parseAssignmentExpression()); + if (match(')')) { + break; + } + expectCommaSeparator(); + } + } + + expect(')'); + + return args; + } + + function parseNonComputedProperty() { + var token, node = new Node(); + + token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpectedToken(token); + } + + return node.finishIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var callee, args, node = new Node(); + + expectKeyword('new'); + callee = parseLeftHandSideExpression(); + args = match('(') ? parseArguments() : []; + + return node.finishNewExpression(callee, args); + } + + function parseLeftHandSideExpressionAllowCall() { + var expr, args, property, startToken, previousAllowIn = state.allowIn; + + startToken = lookahead; + state.allowIn = true; + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + for (;;) { + if (match('.')) { + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else if (match('(')) { + args = parseArguments(); + expr = new WrappingNode(startToken).finishCallExpression(expr, args); + } else if (match('[')) { + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else { + break; + } + } + state.allowIn = previousAllowIn; + + return expr; + } + + function parseLeftHandSideExpression() { + var expr, property, startToken; + assert(state.allowIn, 'callee of new expression always allow in keyword.'); + + startToken = lookahead; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + for (;;) { + if (match('[')) { + property = parseComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property); + } else if (match('.')) { + property = parseNonComputedMember(); + expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property); + } else { + break; + } + } + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr, token, startToken = lookahead; + + expr = parseLeftHandSideExpressionAllowCall(); + + if (lookahead.type === Token.Punctuator) { + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPostfix); + } + + if (!isLeftHandSide(expr)) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + token = lex(); + expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr); + } + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr, startToken; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + expr = parsePostfixExpression(); + } else if (match('++') || match('--')) { + startToken = lookahead; + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateError(Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + } else if (match('+') || match('-') || match('~') || match('!')) { + startToken = lookahead; + token = lex(); + expr = parseUnaryExpression(); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + startToken = lookahead; + token = lex(); + expr = parseUnaryExpression(); + expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + tolerateError(Messages.StrictDelete); + } + } else { + expr = parsePostfixExpression(); + } + + return expr; + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // 11.5 Multiplicative Operators + // 11.6 Additive Operators + // 11.7 Bitwise Shift Operators + // 11.8 Relational Operators + // 11.9 Equality Operators + // 11.10 Binary Bitwise Operators + // 11.11 Binary Logical Operators + + function parseBinaryExpression() { + var marker, markers, expr, token, prec, stack, right, operator, left, i; + + marker = lookahead; + left = parseUnaryExpression(); + if (left === PlaceHolders.ArrowParameterPlaceHolder) { + return left; + } + + token = lookahead; + prec = binaryPrecedence(token, state.allowIn); + if (prec === 0) { + return left; + } + token.prec = prec; + lex(); + + markers = [marker, lookahead]; + right = parseUnaryExpression(); + + stack = [left, token, right]; + + while ((prec = binaryPrecedence(lookahead, state.allowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + markers.pop(); + expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right); + stack.push(expr); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + markers.push(lookahead); + expr = parseUnaryExpression(); + stack.push(expr); + } + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + markers.pop(); + while (i > 1) { + expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + + return expr; + } + + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate, startToken; + + startToken = lookahead; + + expr = parseBinaryExpression(); + if (expr === PlaceHolders.ArrowParameterPlaceHolder) { + return expr; + } + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + alternate = parseAssignmentExpression(); + + expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate); + } + + return expr; + } + + // [ES6] 14.2 Arrow Function + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return parseAssignmentExpression(); + } + + function reinterpretAsCoverFormalsList(expressions) { + var i, len, param, params, defaults, defaultCount, options, rest, token; + + params = []; + defaults = []; + defaultCount = 0; + rest = null; + options = { + paramSet: {} + }; + + for (i = 0, len = expressions.length; i < len; i += 1) { + param = expressions[i]; + if (param.type === Syntax.Identifier) { + params.push(param); + defaults.push(null); + validateParam(options, param, param.name); + } else if (param.type === Syntax.AssignmentExpression) { + params.push(param.left); + defaults.push(param.right); + ++defaultCount; + validateParam(options, param.left, param.left.name); + } else { + return null; + } + } + + if (options.message === Messages.StrictParamDupe) { + token = strict ? options.stricted : options.firstRestricted; + throwUnexpectedToken(token, options.message); + } + + if (defaultCount === 0) { + defaults = []; + } + + return { + params: params, + defaults: defaults, + rest: rest, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseArrowFunctionExpression(options, node) { + var previousStrict, body; + + expect('=>'); + previousStrict = strict; + + body = parseConciseBody(); + + if (strict && options.firstRestricted) { + throwUnexpectedToken(options.firstRestricted, options.message); + } + if (strict && options.stricted) { + tolerateUnexpectedToken(options.stricted, options.message); + } + + strict = previousStrict; + + return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement); + } + + // 11.13 Assignment Operators + + function parseAssignmentExpression() { + var oldParenthesisCount, token, expr, right, list, startToken; + + oldParenthesisCount = state.parenthesisCount; + + startToken = lookahead; + token = lookahead; + + expr = parseConditionalExpression(); + + if (expr === PlaceHolders.ArrowParameterPlaceHolder || match('=>')) { + if (state.parenthesisCount === oldParenthesisCount || + state.parenthesisCount === (oldParenthesisCount + 1)) { + if (expr.type === Syntax.Identifier) { + list = reinterpretAsCoverFormalsList([ expr ]); + } else if (expr.type === Syntax.AssignmentExpression) { + list = reinterpretAsCoverFormalsList([ expr ]); + } else if (expr.type === Syntax.SequenceExpression) { + list = reinterpretAsCoverFormalsList(expr.expressions); + } else if (expr === PlaceHolders.ArrowParameterPlaceHolder) { + list = reinterpretAsCoverFormalsList([]); + } + if (list) { + return parseArrowFunctionExpression(list, new WrappingNode(startToken)); + } + } + } + + if (matchAssign()) { + // LeftHandSideExpression + if (!isLeftHandSide(expr)) { + tolerateError(Messages.InvalidLHSInAssignment); + } + + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + tolerateUnexpectedToken(token, Messages.StrictLHSAssignment); + } + + token = lex(); + right = parseAssignmentExpression(); + expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right); + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr, startToken = lookahead, expressions; + + expr = parseAssignmentExpression(); + + if (match(',')) { + expressions = [expr]; + + while (index < length) { + if (!match(',')) { + break; + } + lex(); + expressions.push(parseAssignmentExpression()); + } + + expr = new WrappingNode(startToken).finishSequenceExpression(expressions); + } + + return expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block, node = new Node(); + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return node.finishBlockStatement(block); + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token, node = new Node(); + + token = lex(); + + if (token.type !== Token.Identifier) { + if (strict && token.type === Token.Keyword && isStrictModeReservedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictReservedWord); + } else { + throwUnexpectedToken(token); + } + } + + return node.finishIdentifier(token.value); + } + + function parseVariableDeclaration(kind) { + var init = null, id, node = new Node(); + + id = parseVariableIdentifier(); + + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + tolerateError(Messages.StrictVarName); + } + + if (kind === 'const') { + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return node.finishVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement(node) { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return node.finishVariableDeclaration(declarations, 'var'); + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations, node = new Node(); + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return node.finishVariableDeclaration(declarations, kind); + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + var node = new Node(); + expect(';'); + return node.finishEmptyStatement(); + } + + // 12.4 Expression Statement + + function parseExpressionStatement(node) { + var expr = parseExpression(); + consumeSemicolon(); + return node.finishExpressionStatement(expr); + } + + // 12.5 If statement + + function parseIfStatement(node) { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return node.finishIfStatement(test, consequent, alternate); + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement(node) { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return node.finishDoWhileStatement(body, test); + } + + function parseWhileStatement(node) { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return node.finishWhileStatement(test, body); + } + + function parseForVariableDeclaration() { + var token, declarations, node = new Node(); + + token = lex(); + declarations = parseVariableDeclarationList(); + + return node.finishVariableDeclaration(declarations, token.value); + } + + function parseForStatement(node) { + var init, test, update, left, right, body, oldInIteration, previousAllowIn = state.allowIn; + + init = test = update = null; + + expectKeyword('for'); + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = previousAllowIn; + + if (init.declarations.length === 1 && matchKeyword('in')) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = previousAllowIn; + + if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isLeftHandSide(init)) { + tolerateError(Messages.InvalidLHSInForIn); + } + + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return (typeof left === 'undefined') ? + node.finishForStatement(init, test, update, body) : + node.finishForInStatement(left, right, body); + } + + // 12.7 The continue statement + + function parseContinueStatement(node) { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(index) === 0x3B) { + lex(); + + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError(Messages.IllegalContinue); + } + + return node.finishContinueStatement(label); + } + + // 12.8 The break statement + + function parseBreakStatement(node) { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (U+003B). + if (source.charCodeAt(index) === 0x3B) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(null); + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError(Messages.IllegalBreak); + } + + return node.finishBreakStatement(label); + } + + // 12.9 The return statement + + function parseReturnStatement(node) { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + tolerateError(Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(index) === 0x20) { + if (isIdentifierStart(source.charCodeAt(index + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return node.finishReturnStatement(argument); + } + } + + if (peekLineTerminator()) { + return node.finishReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return node.finishReturnStatement(argument); + } + + // 12.10 The with statement + + function parseWithStatement(node) { + var object, body; + + if (strict) { + // TODO(ikarienator): Should we update the test cases instead? + skipComment(); + tolerateError(Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return node.finishWithStatement(object, body); + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, consequent = [], statement, node = new Node(); + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + statement = parseStatement(); + consequent.push(statement); + } + + return node.finishSwitchCase(test, consequent); + } + + function parseSwitchStatement(node) { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return node.finishSwitchStatement(discriminant, cases); + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError(Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return node.finishSwitchStatement(discriminant, cases); + } + + // 12.13 The throw statement + + function parseThrowStatement(node) { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError(Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return node.finishThrowStatement(argument); + } + + // 12.14 The try statement + + function parseCatchClause() { + var param, body, node = new Node(); + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpectedToken(lookahead); + } + + param = parseVariableIdentifier(); + // 12.14.1 + if (strict && isRestrictedWord(param.name)) { + tolerateError(Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return node.finishCatchClause(param, body); + } + + function parseTryStatement(node) { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError(Messages.NoCatchOrFinally); + } + + return node.finishTryStatement(block, [], handlers, finalizer); + } + + // 12.15 The debugger statement + + function parseDebuggerStatement(node) { + expectKeyword('debugger'); + + consumeSemicolon(); + + return node.finishDebuggerStatement(); + } + + // 12 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key, + node; + + if (type === Token.EOF) { + throwUnexpectedToken(lookahead); + } + + if (type === Token.Punctuator && lookahead.value === '{') { + return parseBlock(); + } + + node = new Node(); + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(node); + case '(': + return parseExpressionStatement(node); + default: + break; + } + } else if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(node); + case 'continue': + return parseContinueStatement(node); + case 'debugger': + return parseDebuggerStatement(node); + case 'do': + return parseDoWhileStatement(node); + case 'for': + return parseForStatement(node); + case 'function': + return parseFunctionDeclaration(node); + case 'if': + return parseIfStatement(node); + case 'return': + return parseReturnStatement(node); + case 'switch': + return parseSwitchStatement(node); + case 'throw': + return parseThrowStatement(node); + case 'try': + return parseTryStatement(node); + case 'var': + return parseVariableStatement(node); + case 'while': + return parseWhileStatement(node); + case 'with': + return parseWithStatement(node); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError(Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return node.finishLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return node.finishExpressionStatement(expr); + } + + // 13 Function Definition + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount, + node = new Node(); + + expect('{'); + + while (index < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + oldParenthesisCount = state.parenthesizedCount; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + state.parenthesizedCount = 0; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + state.parenthesizedCount = oldParenthesisCount; + + return node.finishBlockStatement(sourceElements); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.firstRestricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, param, def; + + token = lookahead; + param = parseVariableIdentifier(); + validateParam(options, token, token.value); + if (match('=')) { + lex(); + def = parseAssignmentExpression(); + ++options.defaultCount; + } + + options.params.push(param); + options.defaults.push(def); + + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + defaultCount: 0, + defaults: [], + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (index < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + if (options.defaultCount === 0) { + options.defaults = []; + } + + return { + params: options.params, + defaults: options.defaults, + stricted: options.stricted, + firstRestricted: options.firstRestricted, + message: options.message + }; + } + + function parseFunctionDeclaration() { + var id, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict, node = new Node(); + + expectKeyword('function'); + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + strict = previousStrict; + + return node.finishFunctionDeclaration(id, params, defaults, body); + } + + function parseFunctionExpression() { + var token, id = null, stricted, firstRestricted, message, tmp, + params = [], defaults = [], body, previousStrict, node = new Node(); + + expectKeyword('function'); + + if (!match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + tolerateUnexpectedToken(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + params = tmp.params; + defaults = tmp.defaults; + stricted = tmp.stricted; + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + body = parseFunctionSourceElements(); + if (strict && firstRestricted) { + throwUnexpectedToken(firstRestricted, message); + } + if (strict && stricted) { + tolerateUnexpectedToken(stricted, message); + } + strict = previousStrict; + + return node.finishFunctionExpression(id, params, defaults, body); + } + + // 14 Program + + function parseSourceElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(lookahead.value); + case 'function': + return parseFunctionDeclaration(); + default: + return parseStatement(); + } + } + + if (lookahead.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.start + 1, token.end - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseSourceElement(); + /* istanbul ignore if */ + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseProgram() { + var body, node; + + skipComment(); + peek(); + node = new Node(); + strict = false; + + body = parseSourceElements(); + return node.finishProgram(body); + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (entry.regex) { + token.regex = { + pattern: entry.regex.pattern, + flags: entry.regex.flags + }; + } + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function tokenize(code, options) { + var toString, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1 + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenize = true; + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + lex(); + while (lookahead.type !== Token.EOF) { + try { + lex(); + } catch (lexError) { + if (extra.errors) { + extra.errors.push(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + filterTokenLocation(); + tokens = extra.tokens; + if (typeof extra.comments !== 'undefined') { + tokens.comments = extra.comments; + } + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowIn: true, + labelSet: {}, + parenthesisCount: 0, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + lastCommentStart: -1 + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + extra.attachComment = (typeof options.attachComment === 'boolean') && options.attachComment; + + if (extra.loc && options.source !== null && options.source !== undefined) { + extra.source = toString(options.source); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + if (extra.attachComment) { + extra.range = true; + extra.comments = []; + extra.bottomRightStack = []; + extra.trailingComments = []; + extra.leadingComments = []; + } + } + + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + extra = {}; + } + + return program; + } + + // Sync with *.json manifests. + exports.version = '2.0.0'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + /* istanbul ignore next */ + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ diff --git a/examples/js/controls/OrbitControls.js b/examples/js/controls/OrbitControls.js index be5f768ec88da4..e150b589c64711 100644 --- a/examples/js/controls/OrbitControls.js +++ b/examples/js/controls/OrbitControls.js @@ -37,10 +37,14 @@ THREE.OrbitControls = function ( object, domElement ) { this.noZoom = false; this.zoomSpeed = 1.0; - // Limits to how far you can dolly in and out + // Limits to how far you can dolly in and out ( PerspectiveCamera only ) this.minDistance = 0; this.maxDistance = Infinity; + // Limits to how far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + // Set to true to disable this control this.noRotate = false; this.rotateSpeed = 1.0; @@ -112,6 +116,7 @@ THREE.OrbitControls = function ( object, domElement ) { this.target0 = this.target.clone(); this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; // so camera.up is the orbit axis @@ -180,7 +185,7 @@ THREE.OrbitControls = function ( object, domElement ) { var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - if ( scope.object.fov !== undefined ) { + if ( scope.object instanceof THREE.PerspectiveCamera ) { // perspective var position = scope.object.position; @@ -194,7 +199,7 @@ THREE.OrbitControls = function ( object, domElement ) { scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight ); scope.panUp( 2 * deltaY * targetDistance / element.clientHeight ); - } else if ( scope.object.top !== undefined ) { + } else if ( scope.object instanceof THREE.OrthographicCamera ) { // orthographic scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth ); @@ -217,7 +222,21 @@ THREE.OrbitControls = function ( object, domElement ) { } - scale /= dollyScale; + if ( scope.object instanceof THREE.PerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object instanceof THREE.OrthographicCamera ) { + + scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + + } }; @@ -229,7 +248,21 @@ THREE.OrbitControls = function ( object, domElement ) { } - scale *= dollyScale; + if ( scope.object instanceof THREE.PerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object instanceof THREE.OrthographicCamera ) { + + scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + scope.dispatchEvent( changeEvent ); + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + + } }; @@ -315,6 +348,10 @@ THREE.OrbitControls = function ( object, domElement ) { this.target.copy( this.target0 ); this.object.position.copy( this.position0 ); + this.object.zoom = this.zoom0; + + this.object.updateProjectionMatrix(); + this.dispatchEvent( changeEvent ); this.update(); @@ -414,7 +451,7 @@ THREE.OrbitControls = function ( object, domElement ) { scope.dollyIn(); - } else { + } else if ( dollyDelta.y < 0 ) { scope.dollyOut(); @@ -473,7 +510,7 @@ THREE.OrbitControls = function ( object, domElement ) { scope.dollyOut(); - } else { + } else if ( delta < 0 ) { scope.dollyIn(); @@ -606,7 +643,7 @@ THREE.OrbitControls = function ( object, domElement ) { scope.dollyOut(); - } else { + } else if ( dollyDelta.y < 0 ) { scope.dollyIn(); diff --git a/examples/js/controls/TrackballControls.js b/examples/js/controls/TrackballControls.js index 241df9a8ee27df..4525da14a1d3e5 100644 --- a/examples/js/controls/TrackballControls.js +++ b/examples/js/controls/TrackballControls.js @@ -26,11 +26,9 @@ THREE.TrackballControls = function ( object, domElement ) { this.noRotate = false; this.noZoom = false; this.noPan = false; - this.noRoll = false; this.staticMoving = false; this.dynamicDampingFactor = 0.2; - this.cylindricalRotation = true; this.minDistance = 0; this.maxDistance = Infinity; @@ -50,9 +48,6 @@ THREE.TrackballControls = function ( object, domElement ) { _eye = new THREE.Vector3(), - _rotateStart = new THREE.Vector3(), - _rotateEnd = new THREE.Vector3(), - _movePrev = new THREE.Vector2(), _moveCurr = new THREE.Vector2(), @@ -141,7 +136,7 @@ THREE.TrackballControls = function ( object, domElement ) { vector.set( ( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ), - ( ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / ( _this.screen.height * 0.5 ) / _this.screen.width * _this.screen.height ) + ( ( _this.screen.height + 2 * ( _this.screen.top - pageY ) ) / _this.screen.width ) // screen.width intentional ); return vector; @@ -149,56 +144,6 @@ THREE.TrackballControls = function ( object, domElement ) { }() ); - var getMouseProjectionOnBall = ( function () { - - var vector = new THREE.Vector3(); - var objectUp = new THREE.Vector3(); - var mouseOnBall = new THREE.Vector3(); - - return function ( pageX, pageY ) { - - mouseOnBall.set( - ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ), - ( _this.screen.height * 0.5 + _this.screen.top - pageY ) / ( _this.screen.height * 0.5 ), - 0.0 - ); - - var length = mouseOnBall.length(); - - if ( _this.noRoll ) { - - if ( length < Math.SQRT1_2 ) { - - mouseOnBall.z = Math.sqrt( 1.0 - length * length ); - - } else { - - mouseOnBall.z = 0.5 / length; - - } - - } else if ( length > 1.0 ) { - - mouseOnBall.normalize(); - - } else { - - mouseOnBall.z = Math.sqrt( 1.0 - length * length ); - - } - - _eye.copy( _this.object.position ).sub( _this.target ); - - vector.copy( _this.object.up ).setLength( mouseOnBall.y ); - vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) ); - vector.add( _eye.setLength( mouseOnBall.z ) ); - - return vector; - - }; - - }() ); - this.rotateCamera = (function() { var axis = new THREE.Vector3(), @@ -211,80 +156,47 @@ THREE.TrackballControls = function ( object, domElement ) { return function () { - if ( _this.cylindricalRotation ) { - - moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); - angle = moveDirection.length(); - - if ( angle ) { - - _eye.copy( _this.object.position ).sub( _this.target ); - - eyeDirection.copy( _eye ).normalize(); - objectUpDirection.copy( _this.object.up ).normalize(); - objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); - - objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); - objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); - - moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); - - axis.crossVectors( moveDirection, _eye ).normalize(); - - angle *= _this.rotateSpeed; - quaternion.setFromAxisAngle( axis, angle ); - - _eye.applyQuaternion( quaternion ); - _this.object.up.applyQuaternion( quaternion ); - - _lastAxis.copy( axis ); - _lastAngle = angle; - - } - else if ( !_this.staticMoving && _lastAngle ) { - - _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor ); - _eye.copy( _this.object.position ).sub( _this.target ); - quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); - _eye.applyQuaternion( quaternion ); - _this.object.up.applyQuaternion( quaternion ); - - } - - _movePrev.copy( _moveCurr ); - - } else { - - angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() ); + moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 ); + angle = moveDirection.length(); - if ( angle ) { + if ( angle ) { - axis.crossVectors( _rotateStart, _rotateEnd ).normalize(); + _eye.copy( _this.object.position ).sub( _this.target ); - angle *= _this.rotateSpeed; + eyeDirection.copy( _eye ).normalize(); + objectUpDirection.copy( _this.object.up ).normalize(); + objectSidewaysDirection.crossVectors( objectUpDirection, eyeDirection ).normalize(); - quaternion.setFromAxisAngle( axis, -angle ); + objectUpDirection.setLength( _moveCurr.y - _movePrev.y ); + objectSidewaysDirection.setLength( _moveCurr.x - _movePrev.x ); - _eye.applyQuaternion( quaternion ); - _this.object.up.applyQuaternion( quaternion ); + moveDirection.copy( objectUpDirection.add( objectSidewaysDirection ) ); - _rotateEnd.applyQuaternion( quaternion ); + axis.crossVectors( moveDirection, _eye ).normalize(); - if ( _this.staticMoving ) { + angle *= _this.rotateSpeed; + quaternion.setFromAxisAngle( axis, angle ); - _rotateStart.copy( _rotateEnd ); + _eye.applyQuaternion( quaternion ); + _this.object.up.applyQuaternion( quaternion ); - } else { + _lastAxis.copy( axis ); + _lastAngle = angle; - quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) ); - _rotateStart.applyQuaternion( quaternion ); + } - } + else if ( !_this.staticMoving && _lastAngle ) { - } + _lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor ); + _eye.copy( _this.object.position ).sub( _this.target ); + quaternion.setFromAxisAngle( _lastAxis, _lastAngle ); + _eye.applyQuaternion( quaternion ); + _this.object.up.applyQuaternion( quaternion ); } + _movePrev.copy( _moveCurr ); + }; }()); @@ -491,17 +403,8 @@ THREE.TrackballControls = function ( object, domElement ) { if ( _state === STATE.ROTATE && !_this.noRotate ) { - if ( _this.cylindricalRotation ) { - - _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); - _movePrev.copy(_moveCurr); - - } else { - - _rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) ); - _rotateEnd.copy( _rotateStart ); - - } + _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); + _movePrev.copy(_moveCurr); } else if ( _state === STATE.ZOOM && !_this.noZoom ) { @@ -531,16 +434,8 @@ THREE.TrackballControls = function ( object, domElement ) { if ( _state === STATE.ROTATE && !_this.noRotate ) { - if ( _this.cylindricalRotation ) { - - _movePrev.copy(_moveCurr); - _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); - - } else { - - _rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) ); - - } + _movePrev.copy(_moveCurr); + _moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) ); } else if ( _state === STATE.ZOOM && !_this.noZoom ) { @@ -602,18 +497,8 @@ THREE.TrackballControls = function ( object, domElement ) { case 1: _state = STATE.TOUCH_ROTATE; - - if ( _this.cylindricalRotation ) { - - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - _movePrev.copy(_moveCurr); - - } else { - - _rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - _rotateEnd.copy( _rotateStart ); - - } + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); + _movePrev.copy(_moveCurr); break; case 2: @@ -647,16 +532,8 @@ THREE.TrackballControls = function ( object, domElement ) { switch ( event.touches.length ) { case 1: - if ( _this.cylindricalRotation ) { - - _movePrev.copy(_moveCurr); - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - - } else { - - _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - - } + _movePrev.copy(_moveCurr); + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); break; case 2: @@ -683,16 +560,8 @@ THREE.TrackballControls = function ( object, domElement ) { switch ( event.touches.length ) { case 1: - if ( _this.cylindricalRotation ) { - - _movePrev.copy(_moveCurr); - _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - - } else { - - _rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); - _rotateStart.copy( _rotateEnd ); - } + _movePrev.copy(_moveCurr); + _moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) ); break; case 2: diff --git a/examples/js/effects/VREffect.js b/examples/js/effects/VREffect.js index 1c48e2fedec66e..324862850128fe 100644 --- a/examples/js/effects/VREffect.js +++ b/examples/js/effects/VREffect.js @@ -82,8 +82,8 @@ THREE.VREffect = function ( renderer, done ) { var leftEyeTranslation = this.leftEyeTranslation; var rightEyeTranslation = this.rightEyeTranslation; var renderer = this._renderer; - var rendererWidth = renderer.domElement.clientWidth; - var rendererHeight = renderer.domElement.clientHeight; + var rendererWidth = renderer.context.drawingBufferWidth; + var rendererHeight = renderer.context.drawingBufferHeight; var eyeDivisionLine = rendererWidth / 2; renderer.enableScissorTest( true ); @@ -165,7 +165,7 @@ THREE.VREffect = function ( renderer, done ) { } if ( canvas.mozRequestFullScreen ) { canvas.mozRequestFullScreen( { vrDisplay: vrHMD } ); - } else { + } else if ( canvas.webkitRequestFullscreen ) { canvas.webkitRequestFullscreen( { vrDisplay: vrHMD } ); } }; diff --git a/examples/js/loaders/ColladaLoader.js b/examples/js/loaders/ColladaLoader.js index fe6918622c464f..353ad00f6f0e83 100644 --- a/examples/js/loaders/ColladaLoader.js +++ b/examples/js/loaders/ColladaLoader.js @@ -3035,9 +3035,9 @@ THREE.ColladaLoader = function () { } else if ( vcount === 4 ) { - faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ ns[0], ns[1], ns[3]], cs.length ? [ cs[0], cs[1], cs[3]] : new THREE.Color() ) ); + faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ 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[1], ns[2], ns[3]], cs.length ? [ cs[1], cs[2], cs[3]] : new THREE.Color() ) ); + faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ 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 ) { @@ -3048,9 +3048,7 @@ THREE.ColladaLoader = function () { for ( k = 1; k < vcount - 1; ) { - // FIXME: normals don't seem to be quite right - - faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], [ ns[0], ns[k ++], ns[k] ], clr ) ); + faces.push( new THREE.Face3( vs[0], vs[k], vs[k + 1], [ ns[0].clone(), ns[k ++].clone(), ns[k].clone() ], clr ) ); } diff --git a/examples/js/loaders/OBJLoader.js b/examples/js/loaders/OBJLoader.js index 01d4f4c91509d8..f66baddcf25121 100644 --- a/examples/js/loaders/OBJLoader.js +++ b/examples/js/loaders/OBJLoader.js @@ -87,11 +87,12 @@ THREE.OBJLoader.prototype = { } - function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) { + function addFace( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) { var ia = parseVertexIndex( a ); var ib = parseVertexIndex( b ); var ic = parseVertexIndex( c ); + var id; if ( d === undefined ) { @@ -99,7 +100,7 @@ THREE.OBJLoader.prototype = { } else { - var id = parseVertexIndex( d ); + id = parseVertexIndex( d ); addVertex( ia, ib, id ); addVertex( ib, ic, id ); @@ -108,9 +109,9 @@ THREE.OBJLoader.prototype = { if ( ua !== undefined ) { - var ia = parseUVIndex( ua ); - var ib = parseUVIndex( ub ); - var ic = parseUVIndex( uc ); + ia = parseUVIndex( ua ); + ib = parseUVIndex( ub ); + ic = parseUVIndex( uc ); if ( d === undefined ) { @@ -118,7 +119,7 @@ THREE.OBJLoader.prototype = { } else { - var id = parseUVIndex( ud ); + id = parseUVIndex( ud ); addUV( ia, ib, id ); addUV( ib, ic, id ); @@ -129,9 +130,9 @@ THREE.OBJLoader.prototype = { if ( na !== undefined ) { - var ia = parseNormalIndex( na ); - var ib = parseNormalIndex( nb ); - var ic = parseNormalIndex( nc ); + ia = parseNormalIndex( na ); + ib = parseNormalIndex( nb ); + ic = parseNormalIndex( nc ); if ( d === undefined ) { @@ -139,7 +140,7 @@ THREE.OBJLoader.prototype = { } else { - var id = parseNormalIndex( nd ); + id = parseNormalIndex( nd ); addNormal( ia, ib, id ); addNormal( ib, ic, id ); @@ -202,7 +203,7 @@ THREE.OBJLoader.prototype = { var face_pattern3 = /f( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))( +(-?\d+)\/(-?\d+)\/(-?\d+))?/; - // f vertex//normal vertex//normal vertex//normal ... + // f vertex//normal vertex//normal vertex//normal ... var face_pattern4 = /f( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))( +(-?\d+)\/\/(-?\d+))?/ @@ -261,7 +262,7 @@ THREE.OBJLoader.prototype = { } else if ( ( result = face_pattern2.exec( line ) ) !== null ) { // ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined] - + addFace( result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ], result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ] @@ -337,8 +338,8 @@ THREE.OBJLoader.prototype = { for ( var i = 0, l = objects.length; i < l; i ++ ) { - var object = objects[ i ]; - var geometry = object.geometry; + object = objects[ i ]; + geometry = object.geometry; var buffergeometry = new THREE.BufferGeometry(); @@ -352,7 +353,7 @@ THREE.OBJLoader.prototype = { buffergeometry.addAttribute( 'uv', new THREE.BufferAttribute( new Float32Array( geometry.uvs ), 2 ) ); } - var material = new THREE.MeshLambertMaterial(); + material = new THREE.MeshLambertMaterial(); material.name = object.material.name; var mesh = new THREE.Mesh( buffergeometry, material ); diff --git a/examples/js/loaders/PLYLoader.js b/examples/js/loaders/PLYLoader.js index da547209b1151f..d0734fe9c0cc6a 100644 --- a/examples/js/loaders/PLYLoader.js +++ b/examples/js/loaders/PLYLoader.js @@ -116,14 +116,17 @@ THREE.PLYLoader.prototype = { var patternHeader = /ply([\s\S]*)end_header\s/; var headerText = ""; - if ( ( result = patternHeader.exec( data ) ) !== null ) { + var headerLength = 0; + var result = patternHeader.exec( data ); + if ( result !== null ) { headerText = result [ 1 ]; + headerLength = result[ 0 ].length; } var header = { comments: [], elements: [], - headerLength: result[ 0 ].length + headerLength: headerLength }; var lines = headerText.split( '\n' ); @@ -241,7 +244,7 @@ THREE.PLYLoader.prototype = { parseASCIIElement: function ( properties, line ) { - values = line.split( /\s+/ ); + var values = line.split( /\s+/ ); var element = Object(); @@ -252,7 +255,7 @@ THREE.PLYLoader.prototype = { var list = []; var n = this.parseASCIINumber( values.shift(), properties[i].countType ); - for ( j = 0; j < n; j ++ ) { + for ( var j = 0; j < n; j ++ ) { list.push( this.parseASCIINumber( values.shift(), properties[i].itemType ) ); @@ -354,7 +357,7 @@ THREE.PLYLoader.prototype = { geometry.useColor = true; - color = new THREE.Color(); + var color = new THREE.Color(); color.setRGB( element.red / 255.0, element.green / 255.0, element.blue / 255.0 ); geometry.colors.push( color ); @@ -423,7 +426,7 @@ THREE.PLYLoader.prototype = { var n = result[0]; read += result[1]; - for ( j = 0; j < n; j ++ ) { + for ( var j = 0; j < n; j ++ ) { result = this.binaryRead( dataview, at + read, properties[i].itemType, little_endian ); list.push( result[0] ); diff --git a/examples/js/renderers/RaytracingRenderer.js b/examples/js/renderers/RaytracingRenderer.js index 6c75c6090d5fa2..78a5b1ea02eb1b 100644 --- a/examples/js/renderers/RaytracingRenderer.js +++ b/examples/js/renderers/RaytracingRenderer.js @@ -9,6 +9,8 @@ THREE.RaytracingRenderer = function ( parameters ) { parameters = parameters || {}; + var scope = this; + var canvas = document.createElement( 'canvas' ); var context = canvas.getContext( '2d', { alpha: parameters.alpha === true @@ -458,7 +460,12 @@ THREE.RaytracingRenderer = function ( parameters ) { blockX = 0; blockY += blockSize; - if ( blockY >= canvasHeight ) return; + if ( blockY >= canvasHeight ) { + + scope.dispatchEvent( { type: "complete" } ); + return; + + } } @@ -535,3 +542,5 @@ THREE.RaytracingRenderer = function ( parameters ) { }; }; + +THREE.EventDispatcher.prototype.apply(THREE.RaytracingRenderer.prototype); diff --git a/examples/js/shaders/ColorCorrectionShader.js b/examples/js/shaders/ColorCorrectionShader.js index 20da4696f7f9bc..5d5253df2e7732 100644 --- a/examples/js/shaders/ColorCorrectionShader.js +++ b/examples/js/shaders/ColorCorrectionShader.js @@ -10,7 +10,8 @@ THREE.ColorCorrectionShader = { "tDiffuse": { type: "t", value: null }, "powRGB": { type: "v3", value: new THREE.Vector3( 2, 2, 2 ) }, - "mulRGB": { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) } + "mulRGB": { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }, + "addRGB": { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) } }, @@ -33,13 +34,14 @@ THREE.ColorCorrectionShader = { "uniform sampler2D tDiffuse;", "uniform vec3 powRGB;", "uniform vec3 mulRGB;", + "uniform vec3 addRGB;", "varying vec2 vUv;", "void main() {", "gl_FragColor = texture2D( tDiffuse, vUv );", - "gl_FragColor.rgb = mulRGB * pow( gl_FragColor.rgb, powRGB );", + "gl_FragColor.rgb = mulRGB * pow( ( gl_FragColor.rgb + addRGB ), powRGB );", "}" diff --git a/examples/misc_controls_trackball.html b/examples/misc_controls_trackball.html index d6a7dd4687b89b..910491a311c209 100644 --- a/examples/misc_controls_trackball.html +++ b/examples/misc_controls_trackball.html @@ -35,8 +35,7 @@
three.js - trackball controls example
- MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
- R: switch from cylindrical (default) to spherical rotation + MOVE mouse & press LEFT/A: rotate, MIDDLE/S: zoom, RIGHT/D: pan
@@ -134,24 +133,12 @@ // window.addEventListener( 'resize', onWindowResize, false ); - window.addEventListener( 'keypress', onKeyPress, true); - // render(); } - function onKeyPress ( e ) { - - if ( e.keyCode === 114 ) { - - controls.cylindricalRotation = !controls.cylindricalRotation; - - } - - } - function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; diff --git a/examples/models/skinned/marine/marine.js b/examples/models/skinned/marine/marine.js index c931fe8d1c0530..3f2d0263e6a117 100644 --- a/examples/models/skinned/marine/marine.js +++ b/examples/models/skinned/marine/marine.js @@ -30,7 +30,6 @@ "mapDiffuseWrap" : ["repeat", "repeat"], "shading" : "Lambert", "specularCoef" : 9, - "opacity" : 0.0, "transparent" : true, "vertexColors" : false }], diff --git a/examples/models/skinned/marine/marine_anims.js b/examples/models/skinned/marine/marine_anims.js index bba0b20a044c63..2070f187550643 100644 --- a/examples/models/skinned/marine/marine_anims.js +++ b/examples/models/skinned/marine/marine_anims.js @@ -30,7 +30,6 @@ "mapDiffuseWrap" : ["repeat", "repeat"], "shading" : "Lambert", "specularCoef" : 9, - "opacity" : 0.0, "transparent" : true, "vertexColors" : false }], diff --git a/examples/models/skinned/marine/marine_ikrig.js b/examples/models/skinned/marine/marine_ikrig.js index 98654f95333416..6a773b53e910f7 100644 --- a/examples/models/skinned/marine/marine_ikrig.js +++ b/examples/models/skinned/marine/marine_ikrig.js @@ -30,7 +30,6 @@ "mapDiffuseWrap" : ["repeat", "repeat"], "shading" : "Lambert", "specularCoef" : 9, - "opacity" : 0.0, "transparent" : true, "vertexColors" : false }], diff --git a/examples/obj/f50/F50NoUv_bin.js b/examples/obj/f50/F50NoUv_bin.js index 51bf1b79d91acb..8355760f08787d 100644 --- a/examples/obj/f50/F50NoUv_bin.js +++ b/examples/obj/f50/F50NoUv_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -60,8 +58,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -73,8 +70,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -86,8 +82,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -99,8 +94,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -112,8 +106,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -125,8 +118,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -138,8 +130,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -151,8 +142,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -164,8 +154,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -177,8 +166,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -190,8 +178,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -203,8 +190,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -216,8 +202,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -242,8 +227,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -281,8 +265,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -294,8 +277,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -307,8 +289,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -320,8 +301,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }, { @@ -333,8 +313,7 @@ "colorSpecular" : [0.025, 0.025, 0.025], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 98.039216, - "opacity" : 0.0 + "specularCoef" : 98.039216 }], "buffers": "F50NoUv_bin.bin" diff --git a/examples/obj/gallardo/GallardoNoUv_bin.js b/examples/obj/gallardo/GallardoNoUv_bin.js index 7755e32d22ded2..ff8fc9b3af4bb5 100644 --- a/examples/obj/gallardo/GallardoNoUv_bin.js +++ b/examples/obj/gallardo/GallardoNoUv_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 29.411765, - "opacity" : 0.0 + "specularCoef" : 29.411765 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 29.411765, - "opacity" : 0.0 + "specularCoef" : 29.411765 }, { @@ -47,8 +45,7 @@ "colorSpecular" : [0.0, 0.0, 0.0], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 7.843137, - "opacity" : 0.0 + "specularCoef" : 7.843137 }, { @@ -60,8 +57,7 @@ "colorSpecular" : [0.6525, 0.6525, 0.6525], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 25.490196, - "opacity" : 0.0 + "specularCoef" : 25.490196 }, { @@ -73,8 +69,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 29.411765, - "opacity" : 0.0 + "specularCoef" : 29.411765 }, { @@ -86,8 +81,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 29.411765, - "opacity" : 0.0 + "specularCoef" : 29.411765 }, { @@ -99,8 +93,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 29.411765, - "opacity" : 0.0 + "specularCoef" : 29.411765 }], "buffers": "GallardoNoUv_bin.bin" diff --git a/examples/obj/gallardo/parts/gallardo_body_bin.js b/examples/obj/gallardo/parts/gallardo_body_bin.js index 515dc7c1bc5e53..25cfa8613b8a12 100644 --- a/examples/obj/gallardo/parts/gallardo_body_bin.js +++ b/examples/obj/gallardo/parts/gallardo_body_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.6525, 0.6525, 0.6525], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 21.568627, - "opacity" : 0.0 + "specularCoef" : 21.568627 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }, { @@ -47,8 +45,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }, { @@ -60,8 +57,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }, { @@ -73,8 +69,7 @@ "colorSpecular" : [0.0, 0.0, 0.0], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 3.921569, - "opacity" : 0.0 + "specularCoef" : 3.921569 }, { @@ -86,8 +81,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }, { @@ -99,8 +93,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }], "buffers": "gallardo_body_bin.bin" diff --git a/examples/obj/gallardo/parts/gallardo_wheel_bin.js b/examples/obj/gallardo/parts/gallardo_wheel_bin.js index f70f26f4bb275f..e0944dd3d0dab1 100644 --- a/examples/obj/gallardo/parts/gallardo_wheel_bin.js +++ b/examples/obj/gallardo/parts/gallardo_wheel_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.175, 0.175, 0.175], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 27.45098, - "opacity" : 0.0 + "specularCoef" : 27.45098 }], "buffers": "gallardo_wheel_bin.bin" diff --git a/examples/obj/veyron/VeyronNoUv_bin.js b/examples/obj/veyron/VeyronNoUv_bin.js index 19728862376bbc..76b4f235e7f041 100644 --- a/examples/obj/veyron/VeyronNoUv_bin.js +++ b/examples/obj/veyron/VeyronNoUv_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.14825, 0.14825, 0.14825], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.6, 0.6, 0.6], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 37.254902, - "opacity" : 0.0 + "specularCoef" : 37.254902 }, { @@ -47,8 +45,7 @@ "colorSpecular" : [0.75, 0.75, 0.75], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 56.862745, - "opacity" : 0.0 + "specularCoef" : 56.862745 }, { @@ -73,8 +70,7 @@ "colorSpecular" : [0.75, 0.75, 0.75], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 56.862745, - "opacity" : 0.0 + "specularCoef" : 56.862745 }, { @@ -86,8 +82,7 @@ "colorSpecular" : [0.4, 0.4, 0.4], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 17.647059, - "opacity" : 0.0 + "specularCoef" : 17.647059 }, { diff --git a/examples/obj/veyron/parts/veyron_body_bin.js b/examples/obj/veyron/parts/veyron_body_bin.js index f8b36215ee8eb9..0aad247e742855 100644 --- a/examples/obj/veyron/parts/veyron_body_bin.js +++ b/examples/obj/veyron/parts/veyron_body_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.75, 0.75, 0.75], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 52.941176, - "opacity" : 0.0 + "specularCoef" : 52.941176 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.75, 0.75, 0.75], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 52.941176, - "opacity" : 0.0 + "specularCoef" : 52.941176 }, { @@ -47,8 +45,7 @@ "colorSpecular" : [0.4, 0.4, 0.4], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 15.686275, - "opacity" : 0.0 + "specularCoef" : 15.686275 }, { @@ -60,8 +57,7 @@ "colorSpecular" : [0.6, 0.6, 0.6], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 35.294118, - "opacity" : 0.0 + "specularCoef" : 35.294118 }, { @@ -99,8 +95,7 @@ "colorSpecular" : [0.14825, 0.14825, 0.14825], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 15.686275, - "opacity" : 0.0 + "specularCoef" : 15.686275 }, { diff --git a/examples/obj/veyron/parts/veyron_wheel_bin.js b/examples/obj/veyron/parts/veyron_wheel_bin.js index 758866d1e2927a..a4f75fd5d17990 100644 --- a/examples/obj/veyron/parts/veyron_wheel_bin.js +++ b/examples/obj/veyron/parts/veyron_wheel_bin.js @@ -21,8 +21,7 @@ "colorSpecular" : [0.6, 0.6, 0.6], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 35.294118, - "opacity" : 0.0 + "specularCoef" : 35.294118 }, { @@ -34,8 +33,7 @@ "colorSpecular" : [0.14825, 0.14825, 0.14825], "illumination" : 2, "opticalDensity" : 1.0, - "specularCoef" : 15.686275, - "opacity" : 0.0 + "specularCoef" : 15.686275 }], "buffers": "veyron_wheel_bin.bin" diff --git a/examples/webgl_lights_pointlights.html b/examples/webgl_lights_pointlights.html index b33b3cacb2dbb0..20a3903ec93478 100644 --- a/examples/webgl_lights_pointlights.html +++ b/examples/webgl_lights_pointlights.html @@ -73,7 +73,7 @@ var callback = function( geometry ) { - object = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0x555555, specular: 0xffffff, shininess: 50, shading: THREE.SmoothShading } ) ); + object = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial( { color: 0x555555, specular: 0xffffff, shininess: 50 } ) ); object.scale.x = object.scale.y = object.scale.z = 0.80; scene.add( object ); diff --git a/src/Three.js b/src/Three.js index f415783be585d3..61cb895796ca63 100644 --- a/src/Three.js +++ b/src/Three.js @@ -16,9 +16,11 @@ if ( typeof module === 'object' ) { if ( Math.sign === undefined ) { + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign + Math.sign = function ( x ) { - return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0; + return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : +x; }; diff --git a/src/core/BufferGeometry.js b/src/core/BufferGeometry.js index 3fe6a10ea000d6..fbf6968b1f9201 100644 --- a/src/core/BufferGeometry.js +++ b/src/core/BufferGeometry.js @@ -84,6 +84,18 @@ THREE.BufferGeometry.prototype = { } + if ( this.boundingBox instanceof THREE.Box3 ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere instanceof THREE.Sphere ) { + + this.computeBoundingSphere(); + + } + }, center: function () { @@ -884,13 +896,7 @@ THREE.BufferGeometry.prototype = { var attribute = attributes[ key ]; - var array = [], typeArray = attribute.array; - - for ( var i = 0, l = typeArray.length; i < l; i ++ ) { - - array[ i ] = typeArray[ i ]; - - } + var array = Array.prototype.slice.call( attribute.array ); output.data.attributes[ key ] = { itemSize: attribute.itemSize, diff --git a/src/core/Object3D.js b/src/core/Object3D.js index 46f92db63ce1db..1709671a3ad847 100644 --- a/src/core/Object3D.js +++ b/src/core/Object3D.js @@ -699,6 +699,8 @@ THREE.Object3D.prototype = { data.geometry = parseGeometry( object.geometry ); data.material = parseMaterial( object.material ); + if ( object instanceof THREE.Line ) data.mode = object.mode; + } else if ( object instanceof THREE.Sprite ) { data.material = parseMaterial( object.material ); diff --git a/src/extras/helpers/HemisphereLightHelper.js b/src/extras/helpers/HemisphereLightHelper.js index 5273af8300013f..469708f5cb1702 100644 --- a/src/extras/helpers/HemisphereLightHelper.js +++ b/src/extras/helpers/HemisphereLightHelper.js @@ -3,7 +3,7 @@ * @author mrdoob / http://mrdoob.com/ */ -THREE.HemisphereLightHelper = function ( light, sphereSize, arrowLength, domeSize ) { +THREE.HemisphereLightHelper = function ( light, sphereSize ) { THREE.Object3D.call( this ); diff --git a/src/loaders/Loader.js b/src/loaders/Loader.js index 4dd0f7c440acd3..c6b0e62182c1af 100644 --- a/src/loaders/Loader.js +++ b/src/loaders/Loader.js @@ -226,12 +226,18 @@ THREE.Loader.prototype = { } - if ( m.transparent !== undefined || m.opacity < 1.0 ) { + if ( m.transparent !== undefined ) { mpars.transparent = m.transparent; } + if ( m.opacity !== undefined && m.opacity < 1.0 ) { + + mpars.transparent = true; + + } + if ( m.depthTest !== undefined ) { mpars.depthTest = m.depthTest; @@ -308,14 +314,14 @@ THREE.Loader.prototype = { // modifiers - if ( m.transparency ) { + if ( m.transparency !== undefined ) { console.warn( 'THREE.Loader: transparency has been renamed to opacity' ); - mpars.opacity = m.transparency; + m.opacity = m.transparency; } - if ( m.opacity ) { + if ( m.opacity !== undefined ) { mpars.opacity = m.opacity; diff --git a/src/loaders/ObjectLoader.js b/src/loaders/ObjectLoader.js index 054af49d7d617e..378d59fee41cd2 100644 --- a/src/loaders/ObjectLoader.js +++ b/src/loaders/ObjectLoader.js @@ -5,6 +5,7 @@ THREE.ObjectLoader = function ( manager ) { this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager; + this.texturePath = ''; }; @@ -14,7 +15,7 @@ THREE.ObjectLoader.prototype = { load: function ( url, onLoad, onProgress, onError ) { - if ( this.texturePath === undefined ) { + if ( this.texturePath === '' ) { this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); @@ -48,7 +49,11 @@ THREE.ObjectLoader.prototype = { var geometries = this.parseGeometries( json.geometries ); - var images = this.parseImages( json.images, onLoad ); + var images = this.parseImages( json.images, function () { + + if ( onLoad !== undefined ) onLoad( object ); + + } ); var textures = this.parseTextures( json.textures, images ); var materials = this.parseMaterials( json.materials, textures ); var object = this.parseObject( json.object, geometries, materials ); @@ -241,6 +246,9 @@ THREE.ObjectLoader.prototype = { if ( data.bumpMap !== undefined ) { material.bumpMap = getTexture( data.bumpMap ); + if ( data.bumpScale ) { + material.bumpScale = new THREE.Vector2( data.bumpScale, data.bumpScale ); + } } @@ -259,6 +267,9 @@ THREE.ObjectLoader.prototype = { if ( data.normalMap !== undefined ) { material.normalMap = getTexture( data.normalMap ); + if ( data.normalScale ) { + material.normalScale = new THREE.Vector2( data.normalScale, data.normalScale ); + } } @@ -311,8 +322,9 @@ THREE.ObjectLoader.prototype = { for ( var i = 0, l = json.length; i < l; i ++ ) { var image = json[ i ]; + var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; - images[ image.uuid ] = loadImage( scope.texturePath + image.url ); + images[ image.uuid ] = loadImage( path ); } @@ -461,7 +473,7 @@ THREE.ObjectLoader.prototype = { case 'Line': - object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ) ); + object = new THREE.Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); break; diff --git a/src/materials/Material.js b/src/materials/Material.js index ee7fa97a088646..216c07b966a682 100644 --- a/src/materials/Material.js +++ b/src/materials/Material.js @@ -29,6 +29,8 @@ THREE.Material = function () { this.depthTest = true; this.depthWrite = true; + this.colorWrite = true; + this.polygonOffset = false; this.polygonOffsetFactor = 0; this.polygonOffsetUnits = 0; @@ -131,6 +133,7 @@ THREE.Material.prototype = { output.color = this.color.getHex(); output.emissive = this.emissive.getHex(); if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; @@ -141,12 +144,12 @@ THREE.Material.prototype = { output.specular = this.specular.getHex(); output.shininess = this.shininess; if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; + if ( this.shading !== THREE.SmoothShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; } else if ( this instanceof THREE.MeshNormalMaterial ) { - if ( this.shading !== THREE.FlatShading ) output.shading = this.shading; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; if ( this.side !== THREE.FrontSide ) output.side = this.side; @@ -160,10 +163,10 @@ THREE.Material.prototype = { output.size = this.size; output.sizeAttenuation = this.sizeAttenuation; output.color = this.color.getHex(); - + if ( this.vertexColors !== THREE.NoColors ) output.vertexColors = this.vertexColors; if ( this.blending !== THREE.NormalBlending ) output.blending = this.blending; - + } else if ( this instanceof THREE.ShaderMaterial ) { output.uniforms = this.uniforms; diff --git a/src/materials/MeshNormalMaterial.js b/src/materials/MeshNormalMaterial.js index 1839fc70394877..1895f002b59f5b 100644 --- a/src/materials/MeshNormalMaterial.js +++ b/src/materials/MeshNormalMaterial.js @@ -20,8 +20,6 @@ THREE.MeshNormalMaterial = function ( parameters ) { this.type = 'MeshNormalMaterial'; - this.shading = THREE.FlatShading; - this.wireframe = false; this.wireframeLinewidth = 1; @@ -40,8 +38,6 @@ THREE.MeshNormalMaterial.prototype.clone = function () { THREE.Material.prototype.clone.call( this, material ); - material.shading = this.shading; - material.wireframe = this.wireframe; material.wireframeLinewidth = this.wireframeLinewidth; diff --git a/src/objects/Line.js b/src/objects/Line.js index e622b31f45601c..dd3e792e954fa6 100644 --- a/src/objects/Line.js +++ b/src/objects/Line.js @@ -11,7 +11,7 @@ THREE.Line = function ( geometry, material, mode ) { this.geometry = geometry !== undefined ? geometry : new THREE.Geometry(); this.material = material !== undefined ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } ); - this.mode = ( mode !== undefined ) ? mode : THREE.LineStrip; + this.mode = mode !== undefined ? mode : THREE.LineStrip; }; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 9e20361669fd31..998bbaccd203a9 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -1179,13 +1179,13 @@ THREE.WebGLRenderer = function ( parameters ) { ? object.material.materials[ geometryGroup.materialIndex ] : object.material; - }; + } - function materialNeedsSmoothNormals ( material ) { + function materialNeedsFaceNormals ( material ) { - return material && material.shading !== undefined && material.shading === THREE.SmoothShading; + return material instanceof THREE.MeshPhongMaterial === false && material.shading === THREE.FlatShading; - }; + } // Buffer setting @@ -1526,7 +1526,7 @@ THREE.WebGLRenderer = function ( parameters ) { } - var needsSmoothNormals = materialNeedsSmoothNormals( material ); + var needsFaceNormals = materialNeedsFaceNormals( material ); var f, fl, fi, face, vertexNormals, faceNormal, normal, @@ -1671,7 +1671,13 @@ THREE.WebGLRenderer = function ( parameters ) { if ( material.morphNormals ) { - if ( needsSmoothNormals ) { + if ( needsFaceNormals ) { + + n1 = morphNormals[ vk ].faceNormals[ chf ]; + n2 = n1; + n3 = n1; + + } else { faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ]; @@ -1679,12 +1685,6 @@ THREE.WebGLRenderer = function ( parameters ) { n2 = faceVertexNormals.b; n3 = faceVertexNormals.c; - } else { - - n1 = morphNormals[ vk ].faceNormals[ chf ]; - n2 = n1; - n3 = n1; - } nka = morphNormalsArrays[ vk ]; @@ -1880,7 +1880,7 @@ THREE.WebGLRenderer = function ( parameters ) { vertexNormals = face.vertexNormals; faceNormal = face.normal; - if ( vertexNormals.length === 3 && needsSmoothNormals ) { + if ( vertexNormals.length === 3 && needsFaceNormals === false ) { for ( i = 0; i < 3; i ++ ) { @@ -2343,7 +2343,8 @@ THREE.WebGLRenderer = function ( parameters ) { _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer ); - if ( material.shading === THREE.FlatShading ) { + if ( material instanceof THREE.MeshPhongMaterial === false && + material.shading === THREE.FlatShading ) { var nx, ny, nz, nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz, @@ -3233,9 +3234,9 @@ THREE.WebGLRenderer = function ( parameters ) { function painterSortStable ( a, b ) { - if ( a.renderOrder !== b.renderOrder ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return a.renderOrder - b.renderOrder; + return a.object.renderOrder - b.object.renderOrder; } else if ( a.material.id !== b.material.id ) { @@ -3255,9 +3256,9 @@ THREE.WebGLRenderer = function ( parameters ) { function reversePainterSortStable ( a, b ) { - if ( a.renderOrder !== b.renderOrder ) { + if ( a.object.renderOrder !== b.object.renderOrder ) { - return a.renderOrder - b.renderOrder; + return a.object.renderOrder - b.object.renderOrder; } if ( a.z !== b.z ) { @@ -3417,6 +3418,7 @@ THREE.WebGLRenderer = function ( parameters ) { state.setDepthTest( true ); state.setDepthWrite( true ); + state.setColorWrite( true ); // _gl.finish(); @@ -4164,6 +4166,8 @@ THREE.WebGLRenderer = function ( parameters ) { useFog: material.fog, fogExp: fog instanceof THREE.FogExp2, + flatShading: material.shading === THREE.FlatShading, + sizeAttenuation: material.sizeAttenuation, logarithmicDepthBuffer: _logarithmicDepthBuffer, @@ -4330,6 +4334,7 @@ THREE.WebGLRenderer = function ( parameters ) { state.setDepthTest( material.depthTest ); state.setDepthWrite( material.depthWrite ); + state.setColorWrite( material.colorWrite ); state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); } diff --git a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl index 51a26a77428723..c901f0b0135cc5 100644 --- a/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl @@ -3,10 +3,10 @@ uniform sampler2D bumpMap; uniform float bumpScale; - // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen - // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html + // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen + // http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html - // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) + // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) vec2 dHdxy_fwd() { @@ -37,4 +37,4 @@ } -#endif \ No newline at end of file +#endif diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl index ddcbbdb00fd7d6..2ca32b93138b2d 100644 --- a/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl @@ -1,12 +1,23 @@ -vec3 normal = normalize( vNormal ); -vec3 viewPosition = normalize( vViewPosition ); +#ifndef FLAT_SHADED + + vec3 normal = normalize( vNormal ); + + #ifdef DOUBLE_SIDED + + normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) ); -#ifdef DOUBLE_SIDED + #endif - normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) ); +#else + + vec3 fdx = dFdx( vViewPosition ); + vec3 fdy = dFdy( vViewPosition ); + vec3 normal = normalize( cross( fdx, fdy ) ); #endif +vec3 viewPosition = normalize( vViewPosition ); + #ifdef USE_NORMALMAP normal = perturbNormal2Arb( -vViewPosition, normal ); diff --git a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl index cc78d8166e9cf8..28bb67544b1ffe 100644 --- a/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl @@ -50,4 +50,9 @@ uniform vec3 ambientLightColor; #endif varying vec3 vViewPosition; -varying vec3 vNormal; + +#ifndef FLAT_SHADED + + varying vec3 vNormal; + +#endif diff --git a/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl b/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl index 1cb3b42fcd1c86..54b93eb59fb3d4 100644 --- a/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl +++ b/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl @@ -3,8 +3,8 @@ uniform sampler2D normalMap; uniform vec2 normalScale; - // Per-Pixel Tangent Space Normal Mapping - // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html + // Per-Pixel Tangent Space Normal Mapping + // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) { diff --git a/src/renderers/shaders/ShaderLib.js b/src/renderers/shaders/ShaderLib.js index 4b64670e4f8bfb..0bf4b13e2ef8eb 100644 --- a/src/renderers/shaders/ShaderLib.js +++ b/src/renderers/shaders/ShaderLib.js @@ -252,7 +252,12 @@ THREE.ShaderLib = { "#define PHONG", "varying vec3 vViewPosition;", - "varying vec3 vNormal;", + + "#ifndef FLAT_SHADED", + + " varying vec3 vNormal;", + + "#endif", THREE.ShaderChunk[ "common" ], THREE.ShaderChunk[ "map_pars_vertex" ], @@ -276,8 +281,12 @@ THREE.ShaderLib = { THREE.ShaderChunk[ "skinnormal_vertex" ], THREE.ShaderChunk[ "defaultnormal_vertex" ], + "#ifndef FLAT_SHADED", + " vNormal = normalize( transformedNormal );", + "#endif", + THREE.ShaderChunk[ "morphtarget_vertex" ], THREE.ShaderChunk[ "skinning_vertex" ], THREE.ShaderChunk[ "default_vertex" ], @@ -692,7 +701,7 @@ THREE.ShaderLib = { "vec3 direction = normalize( vWorldPosition );", "vec2 sampleUV;", "sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );", - "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;", + "sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;", "gl_FragColor = texture2D( tEquirect, sampleUV );", THREE.ShaderChunk[ "logdepthbuf_fragment" ], diff --git a/src/renderers/webgl/WebGLProgram.js b/src/renderers/webgl/WebGLProgram.js index 7e50e996ff2a0f..e57ad9ced43401 100644 --- a/src/renderers/webgl/WebGLProgram.js +++ b/src/renderers/webgl/WebGLProgram.js @@ -188,6 +188,8 @@ THREE.WebGLProgram = ( function () { parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.flatShading ? '#define FLAT_SHADED': '', + parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', @@ -267,7 +269,7 @@ THREE.WebGLProgram = ( function () { 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', - ( parameters.bumpMap || parameters.normalMap ) ? '#extension GL_OES_standard_derivatives : enable' : '', + ( parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', customDefines, @@ -299,6 +301,8 @@ THREE.WebGLProgram = ( function () { parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', + parameters.flatShading ? '#define FLAT_SHADED': '', + parameters.metal ? '#define METAL' : '', parameters.wrapAround ? '#define WRAP_AROUND' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', @@ -345,7 +349,7 @@ THREE.WebGLProgram = ( function () { THREE.error( 'THREE.WebGLProgram: shader error: ' + _gl.getError(), 'gl.VALIDATE_STATUS', _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ), 'gl.getPRogramInfoLog', programLogInfo ); } - + if ( programLogInfo !== '' ) { THREE.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()' + programLogInfo ); diff --git a/src/renderers/webgl/WebGLState.js b/src/renderers/webgl/WebGLState.js index 2a706d2b84e3e1..ef0d534941e51f 100644 --- a/src/renderers/webgl/WebGLState.js +++ b/src/renderers/webgl/WebGLState.js @@ -18,6 +18,8 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { var currentDepthTest = null; var currentDepthWrite = null; + var currentColorWrite = null; + var currentDoubleSided = null; var currentFlipSided = null; @@ -179,6 +181,17 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { }; + this.setColorWrite = function ( colorWrite ) { + + if ( currentColorWrite !== colorWrite ) { + + gl.colorMask( colorWrite, colorWrite, colorWrite, colorWrite ); + currentColorWrite = colorWrite; + + } + + }; + this.setDoubleSided = function ( doubleSided ) { if ( currentDoubleSided !== doubleSided ) { @@ -271,6 +284,7 @@ THREE.WebGLState = function ( gl, paramThreeToGL ) { currentBlending = null; currentDepthTest = null; currentDepthWrite = null; + currentColorWrite = null; currentDoubleSided = null; currentFlipSided = null; diff --git a/test/unit/math/Math.js b/test/unit/math/Math.js new file mode 100644 index 00000000000000..24fab739537df9 --- /dev/null +++ b/test/unit/math/Math.js @@ -0,0 +1,35 @@ +/** + * @author humbletim / https://github.com/humbletim + */ + +module( "Math" ); + +//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign +//http://people.mozilla.org/~jorendorff/es6-draft.html#sec-math.sign +/* +20.2.2.29 Math.sign(x) + +Returns the sign of the x, indicating whether x is positive, negative or zero. + +If x is NaN, the result is NaN. +If x is -0, the result is -0. +If x is +0, the result is +0. +If x is negative and not -0, the result is -1. +If x is positive and not +0, the result is +1. +*/ + +test( "Math.sign/polyfill", function() { + + ok( isNaN( Math.sign(NaN) ) , "If x is NaN, the result is NaN."); + ok( isNaN( Math.sign(new THREE.Vector3()) ) , "If x is NaN, the result is NaN."); + ok( isNaN( Math.sign() ) , "If x is NaN, the result is NaN."); + ok( isNaN( Math.sign('--3') ) , "If x is NaN<'--3'>, the result is NaN."); + ok( Math.sign(-0) === -0 , "If x is -0, the result is -0."); + ok( Math.sign(+0) === +0 , "If x is +0, the result is +0."); + ok( Math.sign(-Infinity) === -1 , "If x is negative<-Infinity> and not -0, the result is -1."); + ok( Math.sign('-3') === -1 , "If x is negative<'-3'> and not -0, the result is -1."); + ok( Math.sign('-1e-10') === -1 , "If x is negative<'-1e-10'> and not -0, the result is -1."); + ok( Math.sign(+Infinity) === +1 , "If x is positive<+Infinity> and not +0, the result is +1."); + ok( Math.sign('+3') === +1 , "If x is positive<'+3'> and not +0, the result is +1."); + +}); diff --git a/test/unit/unittests_sources.html b/test/unit/unittests_sources.html index 82aabde1e81459..c92a60d9550926 100644 --- a/test/unit/unittests_sources.html +++ b/test/unit/unittests_sources.html @@ -45,6 +45,7 @@ + diff --git a/test/unit/unittests_three-math.html b/test/unit/unittests_three-math.html index 7bd8ac804f271f..5eaf7e6388e7ef 100644 --- a/test/unit/unittests_three-math.html +++ b/test/unit/unittests_three-math.html @@ -28,6 +28,7 @@ + diff --git a/test/unit/unittests_three.html b/test/unit/unittests_three.html index b02c16bec56ff9..e995d3025c5f5e 100644 --- a/test/unit/unittests_three.html +++ b/test/unit/unittests_three.html @@ -28,6 +28,7 @@ + diff --git a/test/unit/unittests_three.min.html b/test/unit/unittests_three.min.html index 5635fc5a0f5a95..34168123d13212 100644 --- a/test/unit/unittests_three.min.html +++ b/test/unit/unittests_three.min.html @@ -28,6 +28,7 @@ + diff --git a/utils/exporters/blender/addons/io_three/__init__.py b/utils/exporters/blender/addons/io_three/__init__.py index 2c6da580f331e8..b8a05893cb3158 100644 --- a/utils/exporters/blender/addons/io_three/__init__.py +++ b/utils/exporters/blender/addons/io_three/__init__.py @@ -26,7 +26,8 @@ EnumProperty, BoolProperty, FloatProperty, - IntProperty + IntProperty, + StringProperty ) from . import constants @@ -41,7 +42,7 @@ bl_info = { 'name': "Three.js Format", 'author': "repsac, mrdoob, yomotsu, mpk, jpweeks", - 'version': (1, 2, 3), + 'version': (1, 3, 1), 'blender': (2, 7, 3), 'location': "File > Export", 'description': "Export Three.js formatted JSON files.", @@ -295,12 +296,14 @@ def save_settings_export(properties): constants.COMPRESSION: properties.option_compression, constants.INDENT: properties.option_indent, constants.COPY_TEXTURES: properties.option_copy_textures, + constants.TEXTURE_FOLDER: properties.option_texture_folder, constants.SCENE: properties.option_export_scene, #constants.EMBED_GEOMETRY: properties.option_embed_geometry, constants.EMBED_ANIMATION: properties.option_embed_animation, constants.LIGHTS: properties.option_lights, constants.CAMERAS: properties.option_cameras, + constants.HIERARCHY: properties.option_hierarchy, constants.MORPH_TARGETS: properties.option_animation_morph, constants.ANIMATION: properties.option_animation_skeletal, @@ -420,6 +423,10 @@ def restore_settings_export(properties): constants.COPY_TEXTURES, constants.EXPORT_OPTIONS[constants.COPY_TEXTURES]) + properties.option_texture_folder = settings.get( + constants.TEXTURE_FOLDER, + constants.EXPORT_OPTIONS[constants.TEXTURE_FOLDER]) + properties.option_embed_animation = settings.get( constants.EMBED_ANIMATION, constants.EXPORT_OPTIONS[constants.EMBED_ANIMATION]) @@ -441,6 +448,10 @@ def restore_settings_export(properties): properties.option_cameras = settings.get( constants.CAMERAS, constants.EXPORT_OPTIONS[constants.CAMERAS]) + + properties.option_hierarchy = settings.get( + constants.HIERARCHY, + constants.EXPORT_OPTIONS[constants.HIERARCHY]) ## } ## Animation { @@ -617,6 +628,11 @@ class ExportThree(bpy.types.Operator, ExportHelper): description="Copy textures", default=constants.EXPORT_OPTIONS[constants.COPY_TEXTURES]) + option_texture_folder = StringProperty( + name="Texture folder", + description="add this folder to textures path", + default=constants.EXPORT_OPTIONS[constants.TEXTURE_FOLDER]) + option_lights = BoolProperty( name="Lights", description="Export default scene lights", @@ -627,6 +643,11 @@ class ExportThree(bpy.types.Operator, ExportHelper): description="Export default scene cameras", default=False) + option_hierarchy = BoolProperty( + name="Hierarchy", + description="Export object hierarchy", + default=False) + option_animation_morph = BoolProperty( name="Morph animation", description="Export animation (morphs)", @@ -800,6 +821,9 @@ def draw(self, context): row.prop(self.properties, 'option_cameras') ## } + row = layout.row() + row.prop(self.properties, 'option_hierarchy') + layout.separator() ## Settings { @@ -812,6 +836,9 @@ def draw(self, context): row = layout.row() row.prop(self.properties, 'option_copy_textures') + row = layout.row() + row.prop(self.properties, 'option_texture_folder') + row = layout.row() row.prop(self.properties, 'option_scale') diff --git a/utils/exporters/blender/addons/io_three/constants.py b/utils/exporters/blender/addons/io_three/constants.py index b183cf0c54d2fd..caa3d88ed6100c 100644 --- a/utils/exporters/blender/addons/io_three/constants.py +++ b/utils/exporters/blender/addons/io_three/constants.py @@ -60,9 +60,11 @@ LOGGING = 'logging' CAMERAS = 'cameras' LIGHTS = 'lights' +HIERARCHY = 'hierarchy' FACE_MATERIALS = 'faceMaterials' SKINNING = 'skinning' COPY_TEXTURES = 'copyTextures' +TEXTURE_FOLDER = 'textureFolder' ENABLE_PRECISION = 'enablePrecision' PRECISION = 'precision' DEFAULT_PRECISION = 6 @@ -91,8 +93,8 @@ EXPORT_OPTIONS = { FACES: True, VERTICES: True, - NORMALS: False, - UVS: False, + NORMALS: True, + UVS: True, COLORS: False, MATERIALS: False, FACE_MATERIALS: False, @@ -109,7 +111,9 @@ MORPH_TARGETS: False, CAMERAS: False, LIGHTS: False, + HIERARCHY: False, COPY_TEXTURES: True, + TEXTURE_FOLDER: '', LOGGING: DEBUG, ENABLE_PRECISION: True, PRECISION: DEFAULT_PRECISION, @@ -158,6 +162,7 @@ SPOT_LIGHT = 'SpotLight' HEMISPHERE_LIGHT = 'HemisphereLight' MESH = 'Mesh' +EMPTY = 'Empty' SPRITE = 'Sprite' DEFAULT_METADATA = { @@ -171,7 +176,7 @@ MATRIX = 'matrix' POSITION = 'position' QUATERNION = 'quaternion' -ROTATION ='rotation' +ROTATION = 'rotation' SCALE = 'scale' UV = 'uv' @@ -319,7 +324,8 @@ NORMAL_BLENDING = 'NormalBlending' -DBG_COLORS = (0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, 0xeeee00, 0x00eeee, 0xee00ee) +DBG_COLORS = (0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee, + 0xeeee00, 0x00eeee, 0xee00ee) DOUBLE_SIDED = 'doubleSided' diff --git a/utils/exporters/blender/addons/io_three/exporter/__init__.py b/utils/exporters/blender/addons/io_three/exporter/__init__.py index 2f0cba4d9bf879..90d6f871aad052 100644 --- a/utils/exporters/blender/addons/io_three/exporter/__init__.py +++ b/utils/exporters/blender/addons/io_three/exporter/__init__.py @@ -71,12 +71,12 @@ def export_geometry(filepath, options, node=None): logger.error(msg) exception = exceptions.GeometryError - if exception is not None: - if api.batch_mode(): - raise exception(msg) - else: - dialogs.error(msg) - return + if exception is not None: + if api.batch_mode(): + raise exception(msg) + else: + dialogs.error(msg) + return mesh = api.object.mesh(node, options) parent = base_classes.BaseScene(filepath, options) diff --git a/utils/exporters/blender/addons/io_three/exporter/api/__init__.py b/utils/exporters/blender/addons/io_three/exporter/api/__init__.py index a273c9d482eedc..c455561b1c8ab1 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/__init__.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/__init__.py @@ -23,6 +23,18 @@ def batch_mode(): return bpy.context.area is None +def data(node): + """ + + :param node: name of an object node + :returns: the data block of the node + + """ + try: + return bpy.data.objects[node].data + except KeyError: + pass + def init(): """Initializing the api module. Required first step before initializing the actual export process. diff --git a/utils/exporters/blender/addons/io_three/exporter/api/animation.py b/utils/exporters/blender/addons/io_three/exporter/api/animation.py index f51c085cffda9c..3d3551181488b6 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/animation.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/animation.py @@ -1,3 +1,4 @@ +import math import mathutils from bpy import data, context from .. import constants, logger, utilities @@ -88,6 +89,7 @@ def _parse_rest_action(action, armature, options, round_off, round_val): action, armature.matrix_world) rot, rchange = _rotation(bone, computed_frame, action, rotation_matrix) + rot = _normalize_quaternion(rot) if round_off: pos_x, pos_y, pos_z = utilities.round_off( @@ -274,6 +276,7 @@ def find_keyframe_at(channel, frame): bone_matrix = parent_matrix.inverted() * bone_matrix pos, rot, scl = bone_matrix.decompose() + rot = _normalize_quaternion(rot) pchange = True or has_keyframe_at( channels_location[bone_index], frame) @@ -569,3 +572,34 @@ def _handle_position_channel(channel, frame, position): position.z = value return change + + +def _quaternion_length(quat): + """Calculate the length of a quaternion + + :param quat: Blender quaternion object + :rtype: float + + """ + return math.sqrt(quat.x * quat.x + quat.y * quat.y + + quat.z * quat.z + quat.w * quat.w) + + +def _normalize_quaternion(quat): + """Normalize a quaternion + + :param quat: Blender quaternion object + :returns: generic quaternion enum object with normalized values + :rtype: object + + """ + enum = type('Enum', (), {'x': 0, 'y': 0, 'z': 0, 'w': 1}) + length = _quaternion_length(quat) + if length is not 0: + length = 1 / length + enum.x = quat.x * length + enum.y = quat.y * length + enum.z = quat.z * length + enum.w = quat.w * length + return enum + diff --git a/utils/exporters/blender/addons/io_three/exporter/api/material.py b/utils/exporters/blender/addons/io_three/exporter/api/material.py index 0f227049c87026..e2dbb5c9c24712 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/material.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/material.py @@ -380,7 +380,7 @@ def _valid_textures(material): for texture in material.texture_slots: if not texture: continue - if texture.texture.type != IMAGE: + if texture.texture.type != IMAGE or not texture.use: continue logger.debug("Valid texture found %s", texture) yield texture diff --git a/utils/exporters/blender/addons/io_three/exporter/api/mesh.py b/utils/exporters/blender/addons/io_three/exporter/api/mesh.py index f770a5792ec43c..b7e87f9e26d2a2 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/mesh.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/mesh.py @@ -340,7 +340,7 @@ def morph_targets(mesh, options): break else: logger.info("No valid morph data detected") - return + return [] manifest = [] for index, morph in enumerate(morphs): diff --git a/utils/exporters/blender/addons/io_three/exporter/api/object.py b/utils/exporters/blender/addons/io_three/exporter/api/object.py index 6e6934b48f886c..2e6c0cd5639516 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/object.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/object.py @@ -2,6 +2,7 @@ import mathutils import bpy from bpy import data, context, types +from bpy_extras.io_utils import axis_conversion from .. import constants, logger, utilities, exceptions from .constants import ( MESH, @@ -225,14 +226,8 @@ def position(obj, options): """ logger.debug('object.position(%s)', obj) - vector = _decompose_matrix(obj)[0] - vector = (vector.x, vector.y, vector.z) - - round_off, round_val = utilities.rounding(options) - if round_off: - vector = utilities.round_off(vector, round_val) - - return vector + vector = matrix(obj, options).to_translation() + return (vector.x, vector.y, vector.z) @_object @@ -250,23 +245,35 @@ def receive_shadow(obj): return False +AXIS_CONVERSION = axis_conversion(to_forward='Z', to_up='Y').to_4x4() + @_object -def rotation(obj, options): +def matrix(obj, options): """ :param obj: :param options: """ - logger.debug('object.rotation(%s)', obj) - vector = _decompose_matrix(obj)[1].to_euler(ZYX) - vector = (vector.x, vector.y, vector.z) + logger.debug('object.matrix(%s)', obj) + if options.get(constants.HIERARCHY, False) and obj.parent: + parent_inverted = obj.parent.matrix_world.inverted(mathutils.Matrix()) + return parent_inverted * obj.matrix_world + else: + return AXIS_CONVERSION * obj.matrix_world + - round_off, round_val = utilities.rounding(options) - if round_off: - vector = utilities.round_off(vector, round_val) +@_object +def rotation(obj, options): + """ - return vector + :param obj: + :param options: + + """ + logger.debug('object.rotation(%s)', obj) + vector = matrix(obj, options).to_euler(ZYX) + return (vector.x, vector.y, vector.z) @_object @@ -278,14 +285,8 @@ def scale(obj, options): """ logger.debug('object.scale(%s)', obj) - vector = _decompose_matrix(obj)[2] - vector = (vector.x, vector.y, vector.z) - - round_off, round_val = utilities.rounding(options) - if round_off: - vector = utilities.round_off(vector, round_val) - - return vector + vector = matrix(obj, options).to_scale() + return (vector.x, vector.y, vector.z) @_object @@ -477,24 +478,6 @@ def extracted_meshes(): return [key for key in _MESH_MAP.keys()] -def _decompose_matrix(obj, local=False): - """ - - :param obj: - :param local: (Default value = False) - - """ - rotate_x_pi2 = mathutils.Quaternion((1.0, 0.0, 0.0), - math.radians(-90.0)) - rotate_x_pi2 = rotate_x_pi2.to_matrix().to_4x4() - - if local: - matrix = rotate_x_pi2 * obj.matrix_local - else: - matrix = rotate_x_pi2 * obj.matrix_world - return matrix.decompose() - - def _on_visible_layer(obj, visible_layers): """ @@ -502,12 +485,15 @@ def _on_visible_layer(obj, visible_layers): :param visible_layers: """ - is_visible = True + is_visible = False for index, layer in enumerate(obj.layers): - if layer and index not in visible_layers: - logger.info('%s is on a hidden layer', obj.name) - is_visible = False + if layer and index in visible_layers: + is_visible = True break + + if not is_visible: + logger.info('%s is on a hidden layer', obj.name) + return is_visible diff --git a/utils/exporters/blender/addons/io_three/exporter/api/texture.py b/utils/exporters/blender/addons/io_three/exporter/api/texture.py index 7c020f59948fca..33088e9127a794 100644 --- a/utils/exporters/blender/addons/io_three/exporter/api/texture.py +++ b/utils/exporters/blender/addons/io_three/exporter/api/texture.py @@ -170,6 +170,9 @@ def textures(): """ logger.debug("texture.textures()") - for texture in data.textures: - if texture.type == IMAGE: - yield texture.name + for mat in data.materials: + if mat.users == 0: + continue + for slot in mat.texture_slots: + if slot and slot.use and slot.texture.type == IMAGE: + yield slot.texture.name diff --git a/utils/exporters/blender/addons/io_three/exporter/geometry.py b/utils/exporters/blender/addons/io_three/exporter/geometry.py index 72c514df1331cf..3c456e35da7d62 100644 --- a/utils/exporters/blender/addons/io_three/exporter/geometry.py +++ b/utils/exporters/blender/addons/io_three/exporter/geometry.py @@ -115,7 +115,7 @@ def metadata(self): def copy(self, scene=True): """Copy the geometry definitions to a standard dictionary. - :param scene: toggle for scene formatting + :param scene: toggle for scene formatting (Default value = True) :type scene: bool :rtype: dict @@ -135,16 +135,17 @@ def copy(self, scene=True): return data - def copy_textures(self): + def copy_textures(self, texture_folder=''): """Copy the textures to the destination directory.""" logger.debug("Geometry().copy_textures()") if self.options.get(constants.COPY_TEXTURES): texture_registration = self.register_textures() if texture_registration: logger.info("%s has registered textures", self.node) + dirname = os.path.dirname(self.scene.filepath) + full_path = os.path.join(dirname, texture_folder) io.copy_registered_textures( - os.path.dirname(self.scene.filepath), - texture_registration) + full_path, texture_registration) def parse(self): """Parse the current node""" @@ -169,7 +170,7 @@ def write(self, filepath=None): """Write the geometry definitions to disk. Uses the desitnation path of the scene. - :param filepath: optional output file path + :param filepath: optional output file path (Default value = None) :type filepath: str @@ -307,7 +308,8 @@ def _geometry_metadata(self, metadata): pass continue - if key in skip: continue + if key in skip: + continue metadata[key] = len(self[key]) @@ -333,7 +335,7 @@ def _scene_format(self): constants.METADATA: self.metadata }) else: - if self.options[constants.EMBED_GEOMETRY]: + if self.options.get(constants.EMBED_GEOMETRY, True): data[constants.DATA] = { constants.ATTRIBUTES: component_data } @@ -430,12 +432,12 @@ def _parse_geometry(self): self[constants.INFLUENCES_PER_VERTEX] = influences self[constants.SKIN_INDICES] = api.mesh.skin_indices( - self.node, bone_map, influences) + self.node, bone_map, influences) or [] self[constants.SKIN_WEIGHTS] = api.mesh.skin_weights( - self.node, bone_map, influences) + self.node, bone_map, influences) or [] if self.options.get(constants.MORPH_TARGETS): logger.info("Parsing %s", constants.MORPH_TARGETS) self[constants.MORPH_TARGETS] = api.mesh.morph_targets( - self.node, self.options) + self.node, self.options) or [] diff --git a/utils/exporters/blender/addons/io_three/exporter/image.py b/utils/exporters/blender/addons/io_three/exporter/image.py index 575b6506019b51..74f7a5b266463f 100644 --- a/utils/exporters/blender/addons/io_three/exporter/image.py +++ b/utils/exporters/blender/addons/io_three/exporter/image.py @@ -11,7 +11,8 @@ def __init__(self, node, parent): logger.debug("Image().__init__(%s)", node) base_classes.BaseNode.__init__(self, node, parent, constants.IMAGE) - self[constants.URL] = api.image.file_name(self.node) + texture_folder = self.scene.options.get(constants.TEXTURE_FOLDER, "") + self[constants.URL] = os.path.join(texture_folder, api.image.file_name(self.node)) @property def destination(self): diff --git a/utils/exporters/blender/addons/io_three/exporter/io.py b/utils/exporters/blender/addons/io_three/exporter/io.py index 69aab0e2502717..49231aa54f5ad9 100644 --- a/utils/exporters/blender/addons/io_three/exporter/io.py +++ b/utils/exporters/blender/addons/io_three/exporter/io.py @@ -14,6 +14,7 @@ def copy_registered_textures(dest, registration): """ logger.debug("io.copy_registered_textures(%s, %s)", dest, registration) + os.makedirs(dest, exist_ok=True) for value in registration.values(): copy(value['file_path'], dest) diff --git a/utils/exporters/blender/addons/io_three/exporter/object.py b/utils/exporters/blender/addons/io_three/exporter/object.py index 1e313d38b742ce..3da492f540f442 100644 --- a/utils/exporters/blender/addons/io_three/exporter/object.py +++ b/utils/exporters/blender/addons/io_three/exporter/object.py @@ -13,34 +13,44 @@ def __init__(self, node, parent=None, type=None): else: self._root_setup() + @property + def data(self): + """ + + :return: returns the data block of the node + + """ + return api.data(self.node) + + def _init_camera(self): """Initialize camera attributes""" logger.debug("Object()._init_camera()") - self[constants.FAR] = api.camera.far(self.node) - self[constants.NEAR] = api.camera.near(self.node) + self[constants.FAR] = api.camera.far(self.data) + self[constants.NEAR] = api.camera.near(self.data) if self[constants.TYPE] == constants.PERSPECTIVE_CAMERA: - self[constants.ASPECT] = api.camera.aspect(self.node) - self[constants.FOV] = api.camera.fov(self.node) + self[constants.ASPECT] = api.camera.aspect(self.data) + self[constants.FOV] = api.camera.fov(self.data) elif self[constants.TYPE] == constants.ORTHOGRAPHIC_CAMERA: - self[constants.LEFT] = api.camera.left(self.node) - self[constants.RIGHT] = api.camera.right(self.node) - self[constants.TOP] = api.camera.top(self.node) - self[constants.BOTTOM] = api.camera.bottom(self.node) + self[constants.LEFT] = api.camera.left(self.data) + self[constants.RIGHT] = api.camera.right(self.data) + self[constants.TOP] = api.camera.top(self.data) + self[constants.BOTTOM] = api.camera.bottom(self.data) #@TODO: need more light attributes. Some may have to come from # custom blender attributes. def _init_light(self): """Initialize light attributes""" logger.debug("Object()._init_light()") - self[constants.COLOR] = api.light.color(self.node) - self[constants.INTENSITY] = api.light.intensity(self.node) + self[constants.COLOR] = api.light.color(self.data) + self[constants.INTENSITY] = api.light.intensity(self.data) if self[constants.TYPE] != constants.DIRECTIONAL_LIGHT: - self[constants.DISTANCE] = api.light.distance(self.node) + self[constants.DISTANCE] = api.light.distance(self.data) if self[constants.TYPE] == constants.SPOT_LIGHT: - self[constants.ANGLE] = api.light.angle(self.node) + self[constants.ANGLE] = api.light.angle(self.data) def _init_mesh(self): """Initialize mesh attributes""" @@ -58,14 +68,13 @@ def _node_setup(self): logger.debug("Object()._node_setup()") self[constants.NAME] = api.object.name(self.node) - self[constants.POSITION] = api.object.position( - self.node, self.options) - - self[constants.ROTATION] = api.object.rotation( - self.node, self.options) + transform = api.object.matrix(self.node, self.options) + matrix = [] + for col in range(0, 4): + for row in range(0, 4): + matrix.append(transform[row][col]) - self[constants.SCALE] = api.object.scale( - self.node, self.options) + self[constants.MATRIX] = matrix self[constants.VISIBLE] = api.object.visible(self.node) @@ -110,11 +119,12 @@ def _node_setup(self): elif self[constants.TYPE] in lights: self._init_light() - #for child in api.object.children(self.node, self.scene.valid_types): - # if not self.get(constants.CHILDREN): - # self[constants.CHILDREN] = [Object(child, parent=self)] - # else: - # self[constants.CHILDREN].append(Object(child, parent=self)) + if self.options.get(constants.HIERARCHY, False): + for child in api.object.children(self.node, self.scene.valid_types): + if not self.get(constants.CHILDREN): + self[constants.CHILDREN] = [Object(child, parent=self)] + else: + self[constants.CHILDREN].append(Object(child, parent=self)) def _root_setup(self): """Applies to a root/scene object""" diff --git a/utils/exporters/blender/addons/io_three/exporter/scene.py b/utils/exporters/blender/addons/io_three/exporter/scene.py index c2521de5076f3b..cb78709ad703d3 100644 --- a/utils/exporters/blender/addons/io_three/exporter/scene.py +++ b/utils/exporters/blender/addons/io_three/exporter/scene.py @@ -39,6 +39,9 @@ def valid_types(self): """ valid_types = [api.constants.MESH] + if self.options.get(constants.HIERARCHY, False): + valid_types.append(api.constants.EMPTY) + if self.options.get(constants.CAMERAS): logger.info("Adding cameras to valid object types") valid_types.append(api.constants.CAMERA) @@ -159,9 +162,10 @@ def write(self): io.dump(self.filepath, data, options=self.options) if self.options.get(constants.COPY_TEXTURES): + texture_folder = self.options.get(constants.TEXTURE_FOLDER) for geo in self[constants.GEOMETRIES]: logger.info("Copying textures from %s", geo.node) - geo.copy_textures() + geo.copy_textures(texture_folder) def _parse_geometries(self): """Locate all geometry nodes and parse them""" @@ -206,7 +210,12 @@ def _parse_objects(self): self[constants.UUID] = utilities.id_from_name(scene_name) objects = [] - for node in api.object.nodes(self.valid_types, self.options): + if self.options.get(constants.HIERARCHY, False): + nodes = api.object.assemblies(self.valid_types, self.options) + else: + nodes = api.object.nodes(self.valid_types, self.options) + + for node in nodes: logger.info("Parsing object %s", node) obj = object_.Object(node, parent=self[constants.OBJECT]) objects.append(obj) diff --git a/utils/exporters/blender/addons/io_three/logger.py b/utils/exporters/blender/addons/io_three/logger.py index 5e15d265a433dd..0c888df86897ac 100644 --- a/utils/exporters/blender/addons/io_three/logger.py +++ b/utils/exporters/blender/addons/io_three/logger.py @@ -32,20 +32,21 @@ def init(filename, level=constants.DEBUG): LOGGER = logging.getLogger('Three.Export') LOGGER.setLevel(LEVELS[level]) - stream = logging.StreamHandler() - stream.setLevel(LEVELS[level]) + if not LOGGER.handlers: + stream = logging.StreamHandler() + stream.setLevel(LEVELS[level]) - format_ = '%(asctime)s - %(name)s - %(levelname)s: %(message)s' - formatter = logging.Formatter(format_) + format_ = '%(asctime)s - %(name)s - %(levelname)s: %(message)s' + formatter = logging.Formatter(format_) - stream.setFormatter(formatter) + stream.setFormatter(formatter) - file_handler = logging.FileHandler(LOG_FILE) - file_handler.setLevel(LEVELS[level]) - file_handler.setFormatter(formatter) + file_handler = logging.FileHandler(LOG_FILE) + file_handler.setLevel(LEVELS[level]) + file_handler.setFormatter(formatter) - LOGGER.addHandler(stream) - LOGGER.addHandler(file_handler) + LOGGER.addHandler(stream) + LOGGER.addHandler(file_handler) def info(*args): diff --git a/utils/exporters/blender/tests/blend/scene_orthographic_camera.blend b/utils/exporters/blender/tests/blend/scene_orthographic_camera.blend index 3e0bc12b353e76..4791a0547601ac 100644 Binary files a/utils/exporters/blender/tests/blend/scene_orthographic_camera.blend and b/utils/exporters/blender/tests/blend/scene_orthographic_camera.blend differ diff --git a/utils/exporters/blender/tests/blend/scene_perspective_camera.blend b/utils/exporters/blender/tests/blend/scene_perspective_camera.blend index 29e3e1e9677aa3..97e4fedb143a22 100644 Binary files a/utils/exporters/blender/tests/blend/scene_perspective_camera.blend and b/utils/exporters/blender/tests/blend/scene_perspective_camera.blend differ diff --git a/utils/exporters/blender/tests/blend/scene_spot_light.blend b/utils/exporters/blender/tests/blend/scene_spot_light.blend index 19b4b88e355730..c961989c6e406c 100644 Binary files a/utils/exporters/blender/tests/blend/scene_spot_light.blend and b/utils/exporters/blender/tests/blend/scene_spot_light.blend differ