(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) : (factory((global.BAS = {}),global.THREE)); }(this, (function (exports,three) { 'use strict'; function BaseAnimationMaterial(parameters, uniforms) { three.ShaderMaterial.call(this); var uniformValues = parameters.uniformValues; delete parameters.uniformValues; this.setValues(parameters); this.uniforms = three.UniformsUtils.merge([uniforms, this.uniforms]); this.setUniformValues(uniformValues); if (uniformValues) { uniformValues.map && (this.defines['USE_MAP'] = ''); uniformValues.normalMap && (this.defines['USE_NORMALMAP'] = ''); uniformValues.envMap && (this.defines['USE_ENVMAP'] = ''); uniformValues.aoMap && (this.defines['USE_AOMAP'] = ''); uniformValues.specularMap && (this.defines['USE_SPECULARMAP'] = ''); uniformValues.alphaMap && (this.defines['USE_ALPHAMAP'] = ''); uniformValues.lightMap && (this.defines['USE_LIGHTMAP'] = ''); uniformValues.emissiveMap && (this.defines['USE_EMISSIVEMAP'] = ''); uniformValues.bumpMap && (this.defines['USE_BUMPMAP'] = ''); uniformValues.displacementMap && (this.defines['USE_DISPLACEMENTMAP'] = ''); uniformValues.roughnessMap && (this.defines['USE_DISPLACEMENTMAP'] = ''); uniformValues.roughnessMap && (this.defines['USE_ROUGHNESSMAP'] = ''); uniformValues.metalnessMap && (this.defines['USE_METALNESSMAP'] = ''); if (uniformValues.envMap) { this.defines['USE_ENVMAP'] = ''; var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; switch (uniformValues.envMap.mapping) { case three.CubeReflectionMapping: case three.CubeRefractionMapping: envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; break; case three.CubeUVReflectionMapping: case three.CubeUVRefractionMapping: envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; break; case three.EquirectangularReflectionMapping: case three.EquirectangularRefractionMapping: envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; break; case three.SphericalReflectionMapping: envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; break; } switch (uniformValues.envMap.mapping) { case three.CubeRefractionMapping: case three.EquirectangularRefractionMapping: envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; break; } switch (uniformValues.combine) { case three.MixOperation: envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; break; case three.AddOperation: envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; break; case three.MultiplyOperation: default: envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; break; } this.defines[envMapTypeDefine] = ''; this.defines[envMapBlendingDefine] = ''; this.defines[envMapModeDefine] = ''; } } } BaseAnimationMaterial.prototype = Object.assign(Object.create(three.ShaderMaterial.prototype), { constructor: BaseAnimationMaterial, setUniformValues: function setUniformValues(values) { var _this = this; if (!values) return; var keys = Object.keys(values); keys.forEach(function (key) { key in _this.uniforms && (_this.uniforms[key].value = values[key]); }); }, stringifyChunk: function stringifyChunk(name) { var value = void 0; if (!this[name]) { value = ''; } else if (typeof this[name] === 'string') { value = this[name]; } else { value = this[name].join('\n'); } return value; } }); /** * Extends THREE.MeshBasicMaterial with custom shader chunks. * * @see http://three-bas-examples.surge.sh/examples/materials_basic/ * * @param {Object} parameters Object containing material properties and custom shader chunks. * @constructor */ function BasicAnimationMaterial(parameters) { this.varyingParameters = []; this.vertexParameters = []; this.vertexFunctions = []; this.vertexInit = []; this.vertexNormal = []; this.vertexPosition = []; this.vertexColor = []; this.vertexPostMorph = []; this.vertexPostSkinning = []; this.fragmentFunctions = []; this.fragmentParameters = []; this.fragmentInit = []; this.fragmentMap = []; this.fragmentDiffuse = []; BaseAnimationMaterial.call(this, parameters, three.ShaderLib['basic'].uniforms); this.lights = false; this.vertexShader = this.concatVertexShader(); this.fragmentShader = this.concatFragmentShader(); } BasicAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); BasicAnimationMaterial.prototype.constructor = BasicAnimationMaterial; BasicAnimationMaterial.prototype.concatVertexShader = function () { return '\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n\n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n #include \n #include \n #include \n \n #ifdef USE_ENVMAP\n \n #include \n \n ' + this.stringifyChunk('vertexNormal') + '\n \n #include \n #include \n #include \n \n #endif\n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n ' + this.stringifyChunk('vertexColor') + '\n \n #include \n \n ' + this.stringifyChunk('vertexPostMorph') + '\n \n #include \n\n ' + this.stringifyChunk('vertexPostSkinning') + '\n\n #include \n #include \n \n #include \n #include \n #include \n #include \n }'; }; BasicAnimationMaterial.prototype.concatFragmentShader = function () { return '\n uniform vec3 diffuse;\n uniform float opacity;\n \n ' + this.stringifyChunk('fragmentParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('fragmentFunctions') + '\n \n #ifndef FLAT_SHADED\n \n varying vec3 vNormal;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n void main() {\n \n ' + this.stringifyChunk('fragmentInit') + '\n \n #include \n\n vec4 diffuseColor = vec4( diffuse, opacity );\n\n ' + this.stringifyChunk('fragmentDiffuse') + '\n \n #include \n \n ' + (this.stringifyChunk('fragmentMap') || '#include ') + '\n \n #include \n #include \n #include \n #include \n \n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n \n // accumulation (baked indirect lighting only)\n #ifdef USE_LIGHTMAP\n \n reflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n \n #else\n \n reflectedLight.indirectDiffuse += vec3( 1.0 );\n \n #endif\n \n // modulation\n #include \n \n reflectedLight.indirectDiffuse *= diffuseColor.rgb;\n \n vec3 outgoingLight = reflectedLight.indirectDiffuse;\n \n #include \n \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n \n #include \n #include \n #include \n #include \n }'; }; /** * Extends THREE.MeshLambertMaterial with custom shader chunks. * * @see http://three-bas-examples.surge.sh/examples/materials_lambert/ * * @param {Object} parameters Object containing material properties and custom shader chunks. * @constructor */ function LambertAnimationMaterial(parameters) { this.varyingParameters = []; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexNormal = []; this.vertexPosition = []; this.vertexColor = []; this.vertexPostMorph = []; this.vertexPostSkinning = []; this.fragmentFunctions = []; this.fragmentParameters = []; this.fragmentInit = []; this.fragmentMap = []; this.fragmentDiffuse = []; this.fragmentEmissive = []; this.fragmentSpecular = []; BaseAnimationMaterial.call(this, parameters, three.ShaderLib['lambert'].uniforms); this.lights = true; this.vertexShader = this.concatVertexShader(); this.fragmentShader = this.concatFragmentShader(); } LambertAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); LambertAnimationMaterial.prototype.constructor = LambertAnimationMaterial; LambertAnimationMaterial.prototype.concatVertexShader = function () { return '\n #define LAMBERT\n\n varying vec3 vLightFront;\n \n #ifdef DOUBLE_SIDED\n \n varying vec3 vLightBack;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n #include \n #include \n \n #include \n \n ' + this.stringifyChunk('vertexNormal') + '\n \n #include \n #include \n #include \n #include \n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n ' + this.stringifyChunk('vertexColor') + '\n \n #include \n \n ' + this.stringifyChunk('vertexPostMorph') + '\n \n #include \n\n ' + this.stringifyChunk('vertexPostSkinning') + '\n \n #include \n #include \n #include \n \n #include \n #include \n #include \n #include \n #include \n }'; }; LambertAnimationMaterial.prototype.concatFragmentShader = function () { return '\n uniform vec3 diffuse;\n uniform vec3 emissive;\n uniform float opacity;\n \n varying vec3 vLightFront;\n \n #ifdef DOUBLE_SIDED\n \n varying vec3 vLightBack;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('fragmentFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('fragmentInit') + '\n \n #include \n\n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n\t\n ' + this.stringifyChunk('fragmentDiffuse') + '\n \n #include \n\n ' + (this.stringifyChunk('fragmentMap') || '#include ') + '\n\n #include \n #include \n #include \n #include \n\n ' + this.stringifyChunk('fragmentEmissive') + '\n\n #include \n \n // accumulation\n reflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n \n #include \n \n reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n \n #ifdef DOUBLE_SIDED\n \n reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n \n #else\n \n reflectedLight.directDiffuse = vLightFront;\n \n #endif\n \n reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n \n // modulation\n #include \n \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n \n #include \n \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n \n #include \n #include \n #include \n #include \n #include \n }'; }; /** * Extends THREE.MeshPhongMaterial with custom shader chunks. * * @see http://three-bas-examples.surge.sh/examples/materials_phong/ * * @param {Object} parameters Object containing material properties and custom shader chunks. * @constructor */ function PhongAnimationMaterial(parameters) { this.varyingParameters = []; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexNormal = []; this.vertexPosition = []; this.vertexColor = []; this.fragmentFunctions = []; this.fragmentParameters = []; this.fragmentInit = []; this.fragmentMap = []; this.fragmentDiffuse = []; this.fragmentEmissive = []; this.fragmentSpecular = []; BaseAnimationMaterial.call(this, parameters, three.ShaderLib['phong'].uniforms); this.lights = true; this.vertexShader = this.concatVertexShader(); this.fragmentShader = this.concatFragmentShader(); } PhongAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); PhongAnimationMaterial.prototype.constructor = PhongAnimationMaterial; PhongAnimationMaterial.prototype.concatVertexShader = function () { return '\n #define PHONG\n\n varying vec3 vViewPosition;\n \n #ifndef FLAT_SHADED\n \n varying vec3 vNormal;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n #include \n #include \n \n #include \n \n ' + this.stringifyChunk('vertexNormal') + '\n \n #include \n #include \n #include \n #include \n \n #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n \n vNormal = normalize( transformedNormal );\n \n #endif\n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n ' + this.stringifyChunk('vertexColor') + '\n \n #include \n #include \n #include \n #include \n #include \n #include \n \n vViewPosition = - mvPosition.xyz;\n \n #include \n #include \n #include \n #include \n }'; }; PhongAnimationMaterial.prototype.concatFragmentShader = function () { return '\n #define PHONG\n\n uniform vec3 diffuse;\n uniform vec3 emissive;\n uniform vec3 specular;\n uniform float shininess;\n uniform float opacity;\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('fragmentFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('fragmentInit') + '\n \n #include \n \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n \n ' + this.stringifyChunk('fragmentDiffuse') + '\n \n #include \n\n ' + (this.stringifyChunk('fragmentMap') || '#include ') + '\n\n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentEmissive') + '\n \n #include \n \n // accumulation\n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentSpecular') + '\n \n // modulation\n #include \n \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n \n #include \n \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n \n #include \n #include \n #include \n #include \n #include \n \n }'; }; /** * Extends THREE.MeshStandardMaterial with custom shader chunks. * * @see http://three-bas-examples.surge.sh/examples/materials_standard/ * * @param {Object} parameters Object containing material properties and custom shader chunks. * @constructor */ function StandardAnimationMaterial(parameters) { this.varyingParameters = []; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexNormal = []; this.vertexPosition = []; this.vertexColor = []; this.vertexPostMorph = []; this.vertexPostSkinning = []; this.fragmentFunctions = []; this.fragmentParameters = []; this.fragmentInit = []; this.fragmentMap = []; this.fragmentDiffuse = []; this.fragmentRoughness = []; this.fragmentMetalness = []; this.fragmentEmissive = []; BaseAnimationMaterial.call(this, parameters, three.ShaderLib['standard'].uniforms); this.lights = true; this.vertexShader = this.concatVertexShader(); this.fragmentShader = this.concatFragmentShader(); } StandardAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); StandardAnimationMaterial.prototype.constructor = StandardAnimationMaterial; StandardAnimationMaterial.prototype.concatVertexShader = function () { return '\n #define PHYSICAL\n\n varying vec3 vViewPosition;\n \n #ifndef FLAT_SHADED\n \n varying vec3 vNormal;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n\n ' + this.stringifyChunk('vertexInit') + '\n\n #include \n #include \n #include \n \n #include \n \n ' + this.stringifyChunk('vertexNormal') + '\n \n #include \n #include \n #include \n #include \n \n #ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n \n vNormal = normalize( transformedNormal );\n \n #endif\n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n ' + this.stringifyChunk('vertexColor') + '\n \n #include \n \n ' + this.stringifyChunk('vertexPostMorph') + '\n \n #include \n\n ' + this.stringifyChunk('vertexPostSkinning') + '\n \n #include \n #include \n #include \n #include \n \n vViewPosition = - mvPosition.xyz;\n \n #include \n #include \n #include \n }'; }; StandardAnimationMaterial.prototype.concatFragmentShader = function () { return '\n #define PHYSICAL\n \n uniform vec3 diffuse;\n uniform vec3 emissive;\n uniform float roughness;\n uniform float metalness;\n uniform float opacity;\n \n #ifndef STANDARD\n uniform float clearCoat;\n uniform float clearCoatRoughness;\n #endif\n \n varying vec3 vViewPosition;\n \n #ifndef FLAT_SHADED\n \n varying vec3 vNormal;\n \n #endif\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('fragmentFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('fragmentInit') + '\n \n #include \n \n vec4 diffuseColor = vec4( diffuse, opacity );\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n vec3 totalEmissiveRadiance = emissive;\n \n ' + this.stringifyChunk('fragmentDiffuse') + '\n \n #include \n\n ' + (this.stringifyChunk('fragmentMap') || '#include ') + '\n\n #include \n #include \n #include \n \n float roughnessFactor = roughness;\n ' + this.stringifyChunk('fragmentRoughness') + '\n #ifdef USE_ROUGHNESSMAP\n \n vec4 texelRoughness = texture2D( roughnessMap, vUv );\n \n // reads channel G, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n roughnessFactor *= texelRoughness.g;\n \n #endif\n \n float metalnessFactor = metalness;\n ' + this.stringifyChunk('fragmentMetalness') + '\n #ifdef USE_METALNESSMAP\n \n vec4 texelMetalness = texture2D( metalnessMap, vUv );\n metalnessFactor *= texelMetalness.b;\n \n #endif\n \n #include \n #include \n \n ' + this.stringifyChunk('fragmentEmissive') + '\n \n #include \n \n // accumulation\n #include \n #include \n #include \n #include \n \n // modulation\n #include \n \n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n \n #include \n #include \n #include \n #include \n #include \n \n }'; }; /** * Extends THREE.PointsMaterial with custom shader chunks. * * @param {Object} parameters Object containing material properties and custom shader chunks. * @constructor */ function PointsAnimationMaterial(parameters) { this.varyingParameters = []; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexPosition = []; this.vertexColor = []; this.fragmentFunctions = []; this.fragmentParameters = []; this.fragmentInit = []; this.fragmentMap = []; this.fragmentDiffuse = []; // use fragment shader to shape to point, reference: https://thebookofshaders.com/07/ this.fragmentShape = []; BaseAnimationMaterial.call(this, parameters, three.ShaderLib['points'].uniforms); this.vertexShader = this.concatVertexShader(); this.fragmentShader = this.concatFragmentShader(); } PointsAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); PointsAnimationMaterial.prototype.constructor = PointsAnimationMaterial; PointsAnimationMaterial.prototype.concatVertexShader = function () { return '\n uniform float size;\n uniform float scale;\n \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n ' + this.stringifyChunk('vertexColor') + '\n \n #include \n \n #ifdef USE_SIZEATTENUATION\n gl_PointSize = size * ( scale / - mvPosition.z );\n #else\n gl_PointSize = size;\n #endif\n \n #include \n #include \n #include \n #include \n #include \n }'; }; PointsAnimationMaterial.prototype.concatFragmentShader = function () { return '\n uniform vec3 diffuse;\n uniform float opacity;\n \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('fragmentParameters') + '\n ' + this.stringifyChunk('varyingParameters') + '\n ' + this.stringifyChunk('fragmentFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('fragmentInit') + '\n \n #include \n \n vec3 outgoingLight = vec3( 0.0 );\n vec4 diffuseColor = vec4( diffuse, opacity );\n \n ' + this.stringifyChunk('fragmentDiffuse') + '\n \n #include \n\n ' + (this.stringifyChunk('fragmentMap') || '#include ') + '\n\n #include \n #include \n \n outgoingLight = diffuseColor.rgb;\n \n gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n \n ' + this.stringifyChunk('fragmentShape') + '\n \n #include \n #include \n #include \n #include \n }'; }; function DepthAnimationMaterial(parameters) { this.depthPacking = three.RGBADepthPacking; this.clipping = true; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexPosition = []; this.vertexPostMorph = []; this.vertexPostSkinning = []; BaseAnimationMaterial.call(this, parameters); this.uniforms = three.UniformsUtils.merge([three.ShaderLib['depth'].uniforms, this.uniforms]); this.vertexShader = this.concatVertexShader(); this.fragmentShader = three.ShaderLib['depth'].fragmentShader; } DepthAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); DepthAnimationMaterial.prototype.constructor = DepthAnimationMaterial; DepthAnimationMaterial.prototype.concatVertexShader = function () { return '\n #include \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n \n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n \n #include \n \n #ifdef USE_DISPLACEMENTMAP\n \n #include \n #include \n #include \n \n #endif\n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n\n #include \n \n ' + this.stringifyChunk('vertexPostMorph') + '\n \n #include \n\n ' + this.stringifyChunk('vertexPostSkinning') + '\n \n #include \n #include \n #include \n #include \n }'; }; function DistanceAnimationMaterial(parameters) { this.depthPacking = three.RGBADepthPacking; this.clipping = true; this.vertexFunctions = []; this.vertexParameters = []; this.vertexInit = []; this.vertexPosition = []; this.vertexPostMorph = []; this.vertexPostSkinning = []; BaseAnimationMaterial.call(this, parameters); this.uniforms = three.UniformsUtils.merge([three.ShaderLib['distanceRGBA'].uniforms, this.uniforms]); this.vertexShader = this.concatVertexShader(); this.fragmentShader = three.ShaderLib['distanceRGBA'].fragmentShader; } DistanceAnimationMaterial.prototype = Object.create(BaseAnimationMaterial.prototype); DistanceAnimationMaterial.prototype.constructor = DistanceAnimationMaterial; DistanceAnimationMaterial.prototype.concatVertexShader = function () { return '\n #define DISTANCE\n\n varying vec3 vWorldPosition;\n \n #include \n #include \n #include \n #include \n #include \n #include \n \n ' + this.stringifyChunk('vertexParameters') + '\n ' + this.stringifyChunk('vertexFunctions') + '\n \n void main() {\n\n ' + this.stringifyChunk('vertexInit') + '\n \n #include \n \n #include \n \n #ifdef USE_DISPLACEMENTMAP\n \n #include \n #include \n #include \n \n #endif\n \n #include \n \n ' + this.stringifyChunk('vertexPosition') + '\n\n #include \n \n ' + this.stringifyChunk('vertexPostMorph') + '\n \n #include \n\n ' + this.stringifyChunk('vertexPostSkinning') + '\n \n #include \n #include \n #include \n #include \n \n vWorldPosition = worldPosition.xyz;\n \n }'; }; /** * A BufferGeometry where a 'prefab' geometry is repeated a number of times. * * @param {Geometry|BufferGeometry} prefab The Geometry instance to repeat. * @param {Number} count The number of times to repeat the geometry. * @constructor */ function PrefabBufferGeometry(prefab, count) { three.BufferGeometry.call(this); /** * A reference to the prefab geometry used to create this instance. * @type {Geometry|BufferGeometry} */ this.prefabGeometry = prefab; this.isPrefabBufferGeometry = prefab.isBufferGeometry; /** * Number of prefabs. * @type {Number} */ this.prefabCount = count; /** * Number of vertices of the prefab. * @type {Number} */ if (this.isPrefabBufferGeometry) { this.prefabVertexCount = prefab.attributes.position.count; } else { this.prefabVertexCount = prefab.vertices.length; } this.bufferIndices(); this.bufferPositions(); } PrefabBufferGeometry.prototype = Object.create(three.BufferGeometry.prototype); PrefabBufferGeometry.prototype.constructor = PrefabBufferGeometry; PrefabBufferGeometry.prototype.bufferIndices = function () { var prefabIndices = []; var prefabIndexCount = void 0; if (this.isPrefabBufferGeometry) { if (this.prefabGeometry.index) { prefabIndexCount = this.prefabGeometry.index.count; prefabIndices = this.prefabGeometry.index.array; } else { prefabIndexCount = this.prefabVertexCount; for (var i = 0; i < prefabIndexCount; i++) { prefabIndices.push(i); } } } else { var prefabFaceCount = this.prefabGeometry.faces.length; prefabIndexCount = prefabFaceCount * 3; for (var _i = 0; _i < prefabFaceCount; _i++) { var face = this.prefabGeometry.faces[_i]; prefabIndices.push(face.a, face.b, face.c); } } var indexBuffer = new Uint32Array(this.prefabCount * prefabIndexCount); this.setIndex(new three.BufferAttribute(indexBuffer, 1)); for (var _i2 = 0; _i2 < this.prefabCount; _i2++) { for (var k = 0; k < prefabIndexCount; k++) { indexBuffer[_i2 * prefabIndexCount + k] = prefabIndices[k] + _i2 * this.prefabVertexCount; } } }; PrefabBufferGeometry.prototype.bufferPositions = function () { var positionBuffer = this.createAttribute('position', 3).array; if (this.isPrefabBufferGeometry) { var positions = this.prefabGeometry.attributes.position.array; for (var i = 0, offset = 0; i < this.prefabCount; i++) { for (var j = 0; j < this.prefabVertexCount; j++, offset += 3) { positionBuffer[offset] = positions[j * 3]; positionBuffer[offset + 1] = positions[j * 3 + 1]; positionBuffer[offset + 2] = positions[j * 3 + 2]; } } } else { for (var _i3 = 0, _offset = 0; _i3 < this.prefabCount; _i3++) { for (var _j = 0; _j < this.prefabVertexCount; _j++, _offset += 3) { var prefabVertex = this.prefabGeometry.vertices[_j]; positionBuffer[_offset] = prefabVertex.x; positionBuffer[_offset + 1] = prefabVertex.y; positionBuffer[_offset + 2] = prefabVertex.z; } } } }; /** * Creates a BufferAttribute with UV coordinates. */ PrefabBufferGeometry.prototype.bufferUvs = function () { var prefabUvs = []; if (this.isPrefabBufferGeometry) { var uv = this.prefabGeometry.attributes.uv.array; for (var i = 0; i < this.prefabVertexCount; i++) { prefabUvs.push(new three.Vector2(uv[i * 2], uv[i * 2 + 1])); } } else { var prefabFaceCount = this.prefabGeometry.faces.length; for (var _i4 = 0; _i4 < prefabFaceCount; _i4++) { var face = this.prefabGeometry.faces[_i4]; var _uv = this.prefabGeometry.faceVertexUvs[0][_i4]; prefabUvs[face.a] = _uv[0]; prefabUvs[face.b] = _uv[1]; prefabUvs[face.c] = _uv[2]; } } var uvBuffer = this.createAttribute('uv', 2); for (var _i5 = 0, offset = 0; _i5 < this.prefabCount; _i5++) { for (var j = 0; j < this.prefabVertexCount; j++, offset += 2) { var prefabUv = prefabUvs[j]; uvBuffer.array[offset] = prefabUv.x; uvBuffer.array[offset + 1] = prefabUv.y; } } }; /** * Creates a BufferAttribute on this geometry instance. * * @param {String} name Name of the attribute. * @param {Number} itemSize Number of floats per vertex (typically 1, 2, 3 or 4). * @param {function=} factory Function that will be called for each prefab upon creation. Accepts 3 arguments: data[], index and prefabCount. Calls setPrefabData. * * @returns {BufferAttribute} */ PrefabBufferGeometry.prototype.createAttribute = function (name, itemSize, factory) { var buffer = new Float32Array(this.prefabCount * this.prefabVertexCount * itemSize); var attribute = new three.BufferAttribute(buffer, itemSize); this.addAttribute(name, attribute); if (factory) { var data = []; for (var i = 0; i < this.prefabCount; i++) { factory(data, i, this.prefabCount); this.setPrefabData(attribute, i, data); } } return attribute; }; /** * Sets data for all vertices of a prefab at a given index. * Usually called in a loop. * * @param {String|BufferAttribute} attribute The attribute or attribute name where the data is to be stored. * @param {Number} prefabIndex Index of the prefab in the buffer geometry. * @param {Array} data Array of data. Length should be equal to item size of the attribute. */ PrefabBufferGeometry.prototype.setPrefabData = function (attribute, prefabIndex, data) { attribute = typeof attribute === 'string' ? this.attributes[attribute] : attribute; var offset = prefabIndex * this.prefabVertexCount * attribute.itemSize; for (var i = 0; i < this.prefabVertexCount; i++) { for (var j = 0; j < attribute.itemSize; j++) { attribute.array[offset++] = data[j]; } } }; /** * A BufferGeometry where a 'prefab' geometry array is repeated a number of times. * * @param {Array} prefabs An array with Geometry instances to repeat. * @param {Number} repeatCount The number of times to repeat the array of Geometries. * @constructor */ function MultiPrefabBufferGeometry(prefabs, repeatCount) { three.BufferGeometry.call(this); if (Array.isArray(prefabs)) { this.prefabGeometries = prefabs; } else { this.prefabGeometries = [prefabs]; } this.prefabGeometriesCount = this.prefabGeometries.length; /** * Number of prefabs. * @type {Number} */ this.prefabCount = repeatCount * this.prefabGeometriesCount; /** * How often the prefab array is repeated. * @type {Number} */ this.repeatCount = repeatCount; /** * Array of vertex counts per prefab. * @type {Array} */ this.prefabVertexCounts = this.prefabGeometries.map(function (p) { return p.isBufferGeometry ? p.attributes.position.count : p.vertices.length; }); /** * Total number of vertices for one repetition of the prefabs * @type {number} */ this.repeatVertexCount = this.prefabVertexCounts.reduce(function (r, v) { return r + v; }, 0); this.bufferIndices(); this.bufferPositions(); } MultiPrefabBufferGeometry.prototype = Object.create(three.BufferGeometry.prototype); MultiPrefabBufferGeometry.prototype.constructor = MultiPrefabBufferGeometry; MultiPrefabBufferGeometry.prototype.bufferIndices = function () { var repeatIndexCount = 0; this.prefabIndices = this.prefabGeometries.map(function (geometry) { var indices = []; if (geometry.isBufferGeometry) { if (geometry.index) { indices = geometry.index.array; } else { for (var i = 0; i < geometry.attributes.position.count; i++) { indices.push(i); } } } else { for (var _i = 0; _i < geometry.faces.length; _i++) { var face = geometry.faces[_i]; indices.push(face.a, face.b, face.c); } } repeatIndexCount += indices.length; return indices; }); var indexBuffer = new Uint32Array(repeatIndexCount * this.repeatCount); var indexOffset = 0; var prefabOffset = 0; for (var i = 0; i < this.prefabCount; i++) { var index = i % this.prefabGeometriesCount; var indices = this.prefabIndices[index]; var vertexCount = this.prefabVertexCounts[index]; for (var j = 0; j < indices.length; j++) { indexBuffer[indexOffset++] = indices[j] + prefabOffset; } prefabOffset += vertexCount; } this.setIndex(new three.BufferAttribute(indexBuffer, 1)); }; MultiPrefabBufferGeometry.prototype.bufferPositions = function () { var _this = this; var positionBuffer = this.createAttribute('position', 3).array; var prefabPositions = this.prefabGeometries.map(function (geometry, i) { var positions = void 0; if (geometry.isBufferGeometry) { positions = geometry.attributes.position.array; } else { var vertexCount = _this.prefabVertexCounts[i]; positions = []; for (var j = 0, offset = 0; j < vertexCount; j++) { var prefabVertex = geometry.vertices[j]; positions[offset++] = prefabVertex.x; positions[offset++] = prefabVertex.y; positions[offset++] = prefabVertex.z; } } return positions; }); for (var i = 0, offset = 0; i < this.prefabCount; i++) { var index = i % this.prefabGeometries.length; var vertexCount = this.prefabVertexCounts[index]; var positions = prefabPositions[index]; for (var j = 0; j < vertexCount; j++) { positionBuffer[offset++] = positions[j * 3]; positionBuffer[offset++] = positions[j * 3 + 1]; positionBuffer[offset++] = positions[j * 3 + 2]; } } }; /** * Creates a BufferAttribute with UV coordinates. */ MultiPrefabBufferGeometry.prototype.bufferUvs = function () { var _this2 = this; var uvBuffer = this.createAttribute('uv', 2).array; var prefabUvs = this.prefabGeometries.map(function (geometry, i) { var uvs = void 0; if (geometry.isBufferGeometry) { if (!geometry.attributes.uv) { console.error('No UV found in prefab geometry', geometry); } uvs = geometry.attributes.uv.array; } else { var prefabFaceCount = _this2.prefabIndices[i].length / 3; var uvObjects = []; for (var j = 0; j < prefabFaceCount; j++) { var face = geometry.faces[j]; var uv = geometry.faceVertexUvs[0][j]; uvObjects[face.a] = uv[0]; uvObjects[face.b] = uv[1]; uvObjects[face.c] = uv[2]; } uvs = []; for (var k = 0; k < uvObjects.length; k++) { uvs[k * 2] = uvObjects[k].x; uvs[k * 2 + 1] = uvObjects[k].y; } } return uvs; }); for (var i = 0, offset = 0; i < this.prefabCount; i++) { var index = i % this.prefabGeometries.length; var vertexCount = this.prefabVertexCounts[index]; var uvs = prefabUvs[index]; for (var j = 0; j < vertexCount; j++) { uvBuffer[offset++] = uvs[j * 2]; uvBuffer[offset++] = uvs[j * 2 + 1]; } } }; /** * Creates a BufferAttribute on this geometry instance. * * @param {String} name Name of the attribute. * @param {Number} itemSize Number of floats per vertex (typically 1, 2, 3 or 4). * @param {function=} factory Function that will be called for each prefab upon creation. Accepts 3 arguments: data[], index and prefabCount. Calls setPrefabData. * * @returns {BufferAttribute} */ MultiPrefabBufferGeometry.prototype.createAttribute = function (name, itemSize, factory) { var buffer = new Float32Array(this.repeatCount * this.repeatVertexCount * itemSize); var attribute = new three.BufferAttribute(buffer, itemSize); this.addAttribute(name, attribute); if (factory) { var data = []; for (var i = 0; i < this.prefabCount; i++) { factory(data, i, this.prefabCount); this.setPrefabData(attribute, i, data); } } return attribute; }; /** * Sets data for all vertices of a prefab at a given index. * Usually called in a loop. * * @param {String|BufferAttribute} attribute The attribute or attribute name where the data is to be stored. * @param {Number} prefabIndex Index of the prefab in the buffer geometry. * @param {Array} data Array of data. Length should be equal to item size of the attribute. */ MultiPrefabBufferGeometry.prototype.setPrefabData = function (attribute, prefabIndex, data) { attribute = typeof attribute === 'string' ? this.attributes[attribute] : attribute; var prefabGeometryIndex = prefabIndex % this.prefabGeometriesCount; var prefabGeometryVertexCount = this.prefabVertexCounts[prefabGeometryIndex]; var whole = (prefabIndex / this.prefabGeometriesCount | 0) * this.prefabGeometriesCount; var wholeOffset = whole * this.repeatVertexCount; var part = prefabIndex - whole; var partOffset = 0; var i = 0; while (i < part) { partOffset += this.prefabVertexCounts[i++]; } var offset = (wholeOffset + partOffset) * attribute.itemSize; for (var _i2 = 0; _i2 < prefabGeometryVertexCount; _i2++) { for (var j = 0; j < attribute.itemSize; j++) { attribute.array[offset++] = data[j]; } } }; /** * Collection of utility functions. * @namespace */ var Utils = { /** * Duplicates vertices so each face becomes separate. * Same as THREE.ExplodeModifier. * * @param {THREE.Geometry} geometry Geometry instance to modify. */ separateFaces: function separateFaces(geometry) { var vertices = []; for (var i = 0, il = geometry.faces.length; i < il; i++) { var n = vertices.length; var face = geometry.faces[i]; var a = face.a; var b = face.b; var c = face.c; var va = geometry.vertices[a]; var vb = geometry.vertices[b]; var vc = geometry.vertices[c]; vertices.push(va.clone()); vertices.push(vb.clone()); vertices.push(vc.clone()); face.a = n; face.b = n + 1; face.c = n + 2; } geometry.vertices = vertices; }, /** * Compute the centroid (center) of a THREE.Face3. * * @param {THREE.Geometry} geometry Geometry instance the face is in. * @param {THREE.Face3} face Face object from the THREE.Geometry.faces array * @param {THREE.Vector3=} v Optional vector to store result in. * @returns {THREE.Vector3} */ computeCentroid: function computeCentroid(geometry, face, v) { var a = geometry.vertices[face.a]; var b = geometry.vertices[face.b]; var c = geometry.vertices[face.c]; v = v || new three.Vector3(); v.x = (a.x + b.x + c.x) / 3; v.y = (a.y + b.y + c.y) / 3; v.z = (a.z + b.z + c.z) / 3; return v; }, /** * Get a random vector between box.min and box.max. * * @param {THREE.Box3} box THREE.Box3 instance. * @param {THREE.Vector3=} v Optional vector to store result in. * @returns {THREE.Vector3} */ randomInBox: function randomInBox(box, v) { v = v || new three.Vector3(); v.x = three.Math.randFloat(box.min.x, box.max.x); v.y = three.Math.randFloat(box.min.y, box.max.y); v.z = three.Math.randFloat(box.min.z, box.max.z); return v; }, /** * Get a random axis for quaternion rotation. * * @param {THREE.Vector3=} v Option vector to store result in. * @returns {THREE.Vector3} */ randomAxis: function randomAxis(v) { v = v || new three.Vector3(); v.x = three.Math.randFloatSpread(2.0); v.y = three.Math.randFloatSpread(2.0); v.z = three.Math.randFloatSpread(2.0); v.normalize(); return v; }, /** * Create a THREE.BAS.DepthAnimationMaterial for shadows from a THREE.SpotLight or THREE.DirectionalLight by copying relevant shader chunks. * Uniform values must be manually synced between the source material and the depth material. * * @see {@link http://three-bas-examples.surge.sh/examples/shadows/} * * @param {THREE.BAS.BaseAnimationMaterial} sourceMaterial Instance to get the shader chunks from. * @returns {THREE.BAS.DepthAnimationMaterial} */ createDepthAnimationMaterial: function createDepthAnimationMaterial(sourceMaterial) { return new DepthAnimationMaterial({ uniforms: sourceMaterial.uniforms, defines: sourceMaterial.defines, vertexFunctions: sourceMaterial.vertexFunctions, vertexParameters: sourceMaterial.vertexParameters, vertexInit: sourceMaterial.vertexInit, vertexPosition: sourceMaterial.vertexPosition }); }, /** * Create a THREE.BAS.DistanceAnimationMaterial for shadows from a THREE.PointLight by copying relevant shader chunks. * Uniform values must be manually synced between the source material and the distance material. * * @see {@link http://three-bas-examples.surge.sh/examples/shadows/} * * @param {THREE.BAS.BaseAnimationMaterial} sourceMaterial Instance to get the shader chunks from. * @returns {THREE.BAS.DistanceAnimationMaterial} */ createDistanceAnimationMaterial: function createDistanceAnimationMaterial(sourceMaterial) { return new DistanceAnimationMaterial({ uniforms: sourceMaterial.uniforms, defines: sourceMaterial.defines, vertexFunctions: sourceMaterial.vertexFunctions, vertexParameters: sourceMaterial.vertexParameters, vertexInit: sourceMaterial.vertexInit, vertexPosition: sourceMaterial.vertexPosition }); } }; /** * A THREE.BufferGeometry for animating individual faces of a THREE.Geometry. * * @param {THREE.Geometry} model The THREE.Geometry to base this geometry on. * @param {Object=} options * @param {Boolean=} options.computeCentroids If true, a centroids will be computed for each face and stored in THREE.BAS.ModelBufferGeometry.centroids. * @param {Boolean=} options.localizeFaces If true, the positions for each face will be stored relative to the centroid. This is useful if you want to rotate or scale faces around their center. * @constructor */ function ModelBufferGeometry(model, options) { three.BufferGeometry.call(this); /** * A reference to the geometry used to create this instance. * @type {THREE.Geometry} */ this.modelGeometry = model; /** * Number of faces of the model. * @type {Number} */ this.faceCount = this.modelGeometry.faces.length; /** * Number of vertices of the model. * @type {Number} */ this.vertexCount = this.modelGeometry.vertices.length; options = options || {}; options.computeCentroids && this.computeCentroids(); this.bufferIndices(); this.bufferPositions(options.localizeFaces); } ModelBufferGeometry.prototype = Object.create(three.BufferGeometry.prototype); ModelBufferGeometry.prototype.constructor = ModelBufferGeometry; /** * Computes a centroid for each face and stores it in THREE.BAS.ModelBufferGeometry.centroids. */ ModelBufferGeometry.prototype.computeCentroids = function () { /** * An array of centroids corresponding to the faces of the model. * * @type {Array} */ this.centroids = []; for (var i = 0; i < this.faceCount; i++) { this.centroids[i] = Utils.computeCentroid(this.modelGeometry, this.modelGeometry.faces[i]); } }; ModelBufferGeometry.prototype.bufferIndices = function () { var indexBuffer = new Uint32Array(this.faceCount * 3); this.setIndex(new three.BufferAttribute(indexBuffer, 1)); for (var i = 0, offset = 0; i < this.faceCount; i++, offset += 3) { var face = this.modelGeometry.faces[i]; indexBuffer[offset] = face.a; indexBuffer[offset + 1] = face.b; indexBuffer[offset + 2] = face.c; } }; ModelBufferGeometry.prototype.bufferPositions = function (localizeFaces) { var positionBuffer = this.createAttribute('position', 3).array; var i = void 0, offset = void 0; if (localizeFaces === true) { for (i = 0; i < this.faceCount; i++) { var face = this.modelGeometry.faces[i]; var centroid = this.centroids ? this.centroids[i] : Utils.computeCentroid(this.modelGeometry, face); var a = this.modelGeometry.vertices[face.a]; var b = this.modelGeometry.vertices[face.b]; var c = this.modelGeometry.vertices[face.c]; positionBuffer[face.a * 3] = a.x - centroid.x; positionBuffer[face.a * 3 + 1] = a.y - centroid.y; positionBuffer[face.a * 3 + 2] = a.z - centroid.z; positionBuffer[face.b * 3] = b.x - centroid.x; positionBuffer[face.b * 3 + 1] = b.y - centroid.y; positionBuffer[face.b * 3 + 2] = b.z - centroid.z; positionBuffer[face.c * 3] = c.x - centroid.x; positionBuffer[face.c * 3 + 1] = c.y - centroid.y; positionBuffer[face.c * 3 + 2] = c.z - centroid.z; } } else { for (i = 0, offset = 0; i < this.vertexCount; i++, offset += 3) { var vertex = this.modelGeometry.vertices[i]; positionBuffer[offset] = vertex.x; positionBuffer[offset + 1] = vertex.y; positionBuffer[offset + 2] = vertex.z; } } }; /** * Creates a THREE.BufferAttribute with UV coordinates. */ ModelBufferGeometry.prototype.bufferUVs = function () { var uvBuffer = this.createAttribute('uv', 2).array; for (var i = 0; i < this.faceCount; i++) { var face = this.modelGeometry.faces[i]; var uv = void 0; uv = this.modelGeometry.faceVertexUvs[0][i][0]; uvBuffer[face.a * 2] = uv.x; uvBuffer[face.a * 2 + 1] = uv.y; uv = this.modelGeometry.faceVertexUvs[0][i][1]; uvBuffer[face.b * 2] = uv.x; uvBuffer[face.b * 2 + 1] = uv.y; uv = this.modelGeometry.faceVertexUvs[0][i][2]; uvBuffer[face.c * 2] = uv.x; uvBuffer[face.c * 2 + 1] = uv.y; } }; /** * Creates two THREE.BufferAttributes: skinIndex and skinWeight. Both are required for skinning. */ ModelBufferGeometry.prototype.bufferSkinning = function () { var skinIndexBuffer = this.createAttribute('skinIndex', 4).array; var skinWeightBuffer = this.createAttribute('skinWeight', 4).array; for (var i = 0; i < this.vertexCount; i++) { var skinIndex = this.modelGeometry.skinIndices[i]; var skinWeight = this.modelGeometry.skinWeights[i]; skinIndexBuffer[i * 4] = skinIndex.x; skinIndexBuffer[i * 4 + 1] = skinIndex.y; skinIndexBuffer[i * 4 + 2] = skinIndex.z; skinIndexBuffer[i * 4 + 3] = skinIndex.w; skinWeightBuffer[i * 4] = skinWeight.x; skinWeightBuffer[i * 4 + 1] = skinWeight.y; skinWeightBuffer[i * 4 + 2] = skinWeight.z; skinWeightBuffer[i * 4 + 3] = skinWeight.w; } }; /** * Creates a THREE.BufferAttribute on this geometry instance. * * @param {String} name Name of the attribute. * @param {int} itemSize Number of floats per vertex (typically 1, 2, 3 or 4). * @param {function=} factory Function that will be called for each face upon creation. Accepts 3 arguments: data[], index and faceCount. Calls setFaceData. * * @returns {BufferAttribute} */ ModelBufferGeometry.prototype.createAttribute = function (name, itemSize, factory) { var buffer = new Float32Array(this.vertexCount * itemSize); var attribute = new three.BufferAttribute(buffer, itemSize); this.addAttribute(name, attribute); if (factory) { var data = []; for (var i = 0; i < this.faceCount; i++) { factory(data, i, this.faceCount); this.setFaceData(attribute, i, data); } } return attribute; }; /** * Sets data for all vertices of a face at a given index. * Usually called in a loop. * * @param {String|THREE.BufferAttribute} attribute The attribute or attribute name where the data is to be stored. * @param {int} faceIndex Index of the face in the buffer geometry. * @param {Array} data Array of data. Length should be equal to item size of the attribute. */ ModelBufferGeometry.prototype.setFaceData = function (attribute, faceIndex, data) { attribute = typeof attribute === 'string' ? this.attributes[attribute] : attribute; var offset = faceIndex * 3 * attribute.itemSize; for (var i = 0; i < 3; i++) { for (var j = 0; j < attribute.itemSize; j++) { attribute.array[offset++] = data[j]; } } }; /** * A THREE.BufferGeometry consists of points. * @param {Number} count The number of points. * @constructor */ function PointBufferGeometry(count) { three.BufferGeometry.call(this); /** * Number of points. * @type {Number} */ this.pointCount = count; this.bufferPositions(); } PointBufferGeometry.prototype = Object.create(three.BufferGeometry.prototype); PointBufferGeometry.prototype.constructor = PointBufferGeometry; PointBufferGeometry.prototype.bufferPositions = function () { this.createAttribute('position', 3); }; /** * Creates a THREE.BufferAttribute on this geometry instance. * * @param {String} name Name of the attribute. * @param {Number} itemSize Number of floats per vertex (typically 1, 2, 3 or 4). * @param {function=} factory Function that will be called for each point upon creation. Accepts 3 arguments: data[], index and prefabCount. Calls setPointData. * * @returns {THREE.BufferAttribute} */ PointBufferGeometry.prototype.createAttribute = function (name, itemSize, factory) { var buffer = new Float32Array(this.pointCount * itemSize); var attribute = new three.BufferAttribute(buffer, itemSize); this.addAttribute(name, attribute); if (factory) { var data = []; for (var i = 0; i < this.pointCount; i++) { factory(data, i, this.pointCount); this.setPointData(attribute, i, data); } } return attribute; }; PointBufferGeometry.prototype.setPointData = function (attribute, pointIndex, data) { attribute = typeof attribute === 'string' ? this.attributes[attribute] : attribute; var offset = pointIndex * attribute.itemSize; for (var j = 0; j < attribute.itemSize; j++) { attribute.array[offset++] = data[j]; } }; var catmull_rom_spline = "vec4 catmullRomSpline(vec4 p0, vec4 p1, vec4 p2, vec4 p3, float t, vec2 c) {\r\n vec4 v0 = (p2 - p0) * c.x;\r\n vec4 v1 = (p3 - p1) * c.y;\r\n float t2 = t * t;\r\n float t3 = t * t * t;\r\n\r\n return vec4((2.0 * p1 - 2.0 * p2 + v0 + v1) * t3 + (-3.0 * p1 + 3.0 * p2 - 2.0 * v0 - v1) * t2 + v0 * t + p1);\r\n}\r\nvec4 catmullRomSpline(vec4 p0, vec4 p1, vec4 p2, vec4 p3, float t) {\r\n return catmullRomSpline(p0, p1, p2, p3, t, vec2(0.5, 0.5));\r\n}\r\n\r\nvec3 catmullRomSpline(vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t, vec2 c) {\r\n vec3 v0 = (p2 - p0) * c.x;\r\n vec3 v1 = (p3 - p1) * c.y;\r\n float t2 = t * t;\r\n float t3 = t * t * t;\r\n\r\n return vec3((2.0 * p1 - 2.0 * p2 + v0 + v1) * t3 + (-3.0 * p1 + 3.0 * p2 - 2.0 * v0 - v1) * t2 + v0 * t + p1);\r\n}\r\nvec3 catmullRomSpline(vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t) {\r\n return catmullRomSpline(p0, p1, p2, p3, t, vec2(0.5, 0.5));\r\n}\r\n\r\nvec2 catmullRomSpline(vec2 p0, vec2 p1, vec2 p2, vec2 p3, float t, vec2 c) {\r\n vec2 v0 = (p2 - p0) * c.x;\r\n vec2 v1 = (p3 - p1) * c.y;\r\n float t2 = t * t;\r\n float t3 = t * t * t;\r\n\r\n return vec2((2.0 * p1 - 2.0 * p2 + v0 + v1) * t3 + (-3.0 * p1 + 3.0 * p2 - 2.0 * v0 - v1) * t2 + v0 * t + p1);\r\n}\r\nvec2 catmullRomSpline(vec2 p0, vec2 p1, vec2 p2, vec2 p3, float t) {\r\n return catmullRomSpline(p0, p1, p2, p3, t, vec2(0.5, 0.5));\r\n}\r\n\r\nfloat catmullRomSpline(float p0, float p1, float p2, float p3, float t, vec2 c) {\r\n float v0 = (p2 - p0) * c.x;\r\n float v1 = (p3 - p1) * c.y;\r\n float t2 = t * t;\r\n float t3 = t * t * t;\r\n\r\n return float((2.0 * p1 - 2.0 * p2 + v0 + v1) * t3 + (-3.0 * p1 + 3.0 * p2 - 2.0 * v0 - v1) * t2 + v0 * t + p1);\r\n}\r\nfloat catmullRomSpline(float p0, float p1, float p2, float p3, float t) {\r\n return catmullRomSpline(p0, p1, p2, p3, t, vec2(0.5, 0.5));\r\n}\r\n\r\nivec4 getCatmullRomSplineIndices(float l, float p) {\r\n float index = floor(p);\r\n int i0 = int(max(0.0, index - 1.0));\r\n int i1 = int(index);\r\n int i2 = int(min(index + 1.0, l));\r\n int i3 = int(min(index + 2.0, l));\r\n\r\n return ivec4(i0, i1, i2, i3);\r\n}\r\n\r\nivec4 getCatmullRomSplineIndicesClosed(float l, float p) {\r\n float index = floor(p);\r\n int i0 = int(index == 0.0 ? l : index - 1.0);\r\n int i1 = int(index);\r\n int i2 = int(mod(index + 1.0, l));\r\n int i3 = int(mod(index + 2.0, l));\r\n\r\n return ivec4(i0, i1, i2, i3);\r\n}\r\n"; var cubic_bezier = "vec3 cubicBezier(vec3 p0, vec3 c0, vec3 c1, vec3 p1, float t) {\r\n float tn = 1.0 - t;\r\n\r\n return tn * tn * tn * p0 + 3.0 * tn * tn * t * c0 + 3.0 * tn * t * t * c1 + t * t * t * p1;\r\n}\r\n\r\nvec2 cubicBezier(vec2 p0, vec2 c0, vec2 c1, vec2 p1, float t) {\r\n float tn = 1.0 - t;\r\n\r\n return tn * tn * tn * p0 + 3.0 * tn * tn * t * c0 + 3.0 * tn * t * t * c1 + t * t * t * p1;\r\n}\r\n"; var ease_back_in = "float easeBackIn(float p, float amplitude) {\r\n return p * p * ((amplitude + 1.0) * p - amplitude);\r\n}\r\n\r\nfloat easeBackIn(float p) {\r\n return easeBackIn(p, 1.70158);\r\n}\r\n\r\nfloat easeBackIn(float t, float b, float c, float d, float amplitude) {\r\n return b + easeBackIn(t / d, amplitude) * c;\r\n}\r\n\r\nfloat easeBackIn(float t, float b, float c, float d) {\r\n return b + easeBackIn(t / d) * c;\r\n}\r\n"; var ease_back_in_out = "float easeBackInOut(float p, float amplitude) {\r\n amplitude *= 1.525;\r\n\r\n return ((p *= 2.0) < 1.0) ? 0.5 * p * p * ((amplitude + 1.0) * p - amplitude) : 0.5 * ((p -= 2.0) * p * ((amplitude + 1.0) * p + amplitude) + 2.0);\r\n}\r\n\r\nfloat easeBackInOut(float p) {\r\n return easeBackInOut(p, 1.70158);\r\n}\r\n\r\nfloat easeBackInOut(float t, float b, float c, float d, float amplitude) {\r\n return b + easeBackInOut(t / d, amplitude) * c;\r\n}\r\n\r\nfloat easeBackInOut(float t, float b, float c, float d) {\r\n return b + easeBackInOut(t / d) * c;\r\n}\r\n"; var ease_back_out = "float easeBackOut(float p, float amplitude) {\r\n return ((p = p - 1.0) * p * ((amplitude + 1.0) * p + amplitude) + 1.0);\r\n}\r\n\r\nfloat easeBackOut(float p) {\r\n return easeBackOut(p, 1.70158);\r\n}\r\n\r\nfloat easeBackOut(float t, float b, float c, float d, float amplitude) {\r\n return b + easeBackOut(t / d, amplitude) * c;\r\n}\r\n\r\nfloat easeBackOut(float t, float b, float c, float d) {\r\n return b + easeBackOut(t / d) * c;\r\n}\r\n"; var ease_bezier = "float easeBezier(float p, vec4 curve) {\r\n float ip = 1.0 - p;\r\n return (3.0 * ip * ip * p * curve.xy + 3.0 * ip * p * p * curve.zw + p * p * p).y;\r\n}\r\n\r\nfloat easeBezier(float t, float b, float c, float d, vec4 curve) {\r\n return b + easeBezier(t / d, curve) * c;\r\n}\r\n"; var ease_bounce_in = "float easeBounceIn(float p) {\r\n if ((p = 1.0 - p) < 1.0 / 2.75) {\r\n return 1.0 - (7.5625 * p * p);\r\n } else if (p < 2.0 / 2.75) {\r\n return 1.0 - (7.5625 * (p -= 1.5 / 2.75) * p + 0.75);\r\n } else if (p < 2.5 / 2.75) {\r\n return 1.0 - (7.5625 * (p -= 2.25 / 2.75) * p + 0.9375);\r\n }\r\n return 1.0 - (7.5625 * (p -= 2.625 / 2.75) * p + 0.984375);\r\n}\r\n\r\nfloat easeBounceIn(float t, float b, float c, float d) {\r\n return b + easeBounceIn(t / d) * c;\r\n}\r\n"; var ease_bounce_in_out = "float easeBounceInOut(float p) {\r\n bool invert = (p < 0.5);\r\n\r\n p = invert ? (1.0 - (p * 2.0)) : ((p * 2.0) - 1.0);\r\n\r\n if (p < 1.0 / 2.75) {\r\n p = 7.5625 * p * p;\r\n } else if (p < 2.0 / 2.75) {\r\n p = 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;\r\n } else if (p < 2.5 / 2.75) {\r\n p = 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;\r\n } else {\r\n p = 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;\r\n }\r\n\r\n return invert ? (1.0 - p) * 0.5 : p * 0.5 + 0.5;\r\n}\r\n\r\nfloat easeBounceInOut(float t, float b, float c, float d) {\r\n return b + easeBounceInOut(t / d) * c;\r\n}\r\n"; var ease_bounce_out = "float easeBounceOut(float p) {\r\n if (p < 1.0 / 2.75) {\r\n return 7.5625 * p * p;\r\n } else if (p < 2.0 / 2.75) {\r\n return 7.5625 * (p -= 1.5 / 2.75) * p + 0.75;\r\n } else if (p < 2.5 / 2.75) {\r\n return 7.5625 * (p -= 2.25 / 2.75) * p + 0.9375;\r\n }\r\n return 7.5625 * (p -= 2.625 / 2.75) * p + 0.984375;\r\n}\r\n\r\nfloat easeBounceOut(float t, float b, float c, float d) {\r\n return b + easeBounceOut(t / d) * c;\r\n}\r\n"; var ease_circ_in = "float easeCircIn(float p) {\r\n return -(sqrt(1.0 - p * p) - 1.0);\r\n}\r\n\r\nfloat easeCircIn(float t, float b, float c, float d) {\r\n return b + easeCircIn(t / d) * c;\r\n}\r\n"; var ease_circ_in_out = "float easeCircInOut(float p) {\r\n return ((p *= 2.0) < 1.0) ? -0.5 * (sqrt(1.0 - p * p) - 1.0) : 0.5 * (sqrt(1.0 - (p -= 2.0) * p) + 1.0);\r\n}\r\n\r\nfloat easeCircInOut(float t, float b, float c, float d) {\r\n return b + easeCircInOut(t / d) * c;\r\n}\r\n"; var ease_circ_out = "float easeCircOut(float p) {\r\n return sqrt(1.0 - (p = p - 1.0) * p);\r\n}\r\n\r\nfloat easeCircOut(float t, float b, float c, float d) {\r\n return b + easeCircOut(t / d) * c;\r\n}\r\n"; var ease_cubic_in = "float easeCubicIn(float t) {\r\n return t * t * t;\r\n}\r\n\r\nfloat easeCubicIn(float t, float b, float c, float d) {\r\n return b + easeCubicIn(t / d) * c;\r\n}\r\n"; var ease_cubic_in_out = "float easeCubicInOut(float t) {\r\n return (t /= 0.5) < 1.0 ? 0.5 * t * t * t : 0.5 * ((t-=2.0) * t * t + 2.0);\r\n}\r\n\r\nfloat easeCubicInOut(float t, float b, float c, float d) {\r\n return b + easeCubicInOut(t / d) * c;\r\n}\r\n"; var ease_cubic_out = "float easeCubicOut(float t) {\r\n float f = t - 1.0;\r\n return f * f * f + 1.0;\r\n}\r\n\r\nfloat easeCubicOut(float t, float b, float c, float d) {\r\n return b + easeCubicOut(t / d) * c;\r\n}\r\n"; var ease_elastic_in = "float easeElasticIn(float p, float amplitude, float period) {\r\n float p1 = max(amplitude, 1.0);\r\n float p2 = period / min(amplitude, 1.0);\r\n float p3 = p2 / PI2 * (asin(1.0 / p1));\r\n\r\n return -(p1 * pow(2.0, 10.0 * (p -= 1.0)) * sin((p - p3) * PI2 / p2));\r\n}\r\n\r\nfloat easeElasticIn(float p) {\r\n return easeElasticIn(p, 1.0, 0.3);\r\n}\r\n\r\nfloat easeElasticIn(float t, float b, float c, float d, float amplitude, float period) {\r\n return b + easeElasticIn(t / d, amplitude, period) * c;\r\n}\r\n\r\nfloat easeElasticIn(float t, float b, float c, float d) {\r\n return b + easeElasticIn(t / d) * c;\r\n}\r\n"; var ease_elastic_in_out = "float easeElasticInOut(float p, float amplitude, float period) {\r\n float p1 = max(amplitude, 1.0);\r\n float p2 = period / min(amplitude, 1.0);\r\n float p3 = p2 / PI2 * (asin(1.0 / p1));\r\n\r\n return ((p *= 2.0) < 1.0) ? -0.5 * (p1 * pow(2.0, 10.0 * (p -= 1.0)) * sin((p - p3) * PI2 / p2)) : p1 * pow(2.0, -10.0 * (p -= 1.0)) * sin((p - p3) * PI2 / p2) * 0.5 + 1.0;\r\n}\r\n\r\nfloat easeElasticInOut(float p) {\r\n return easeElasticInOut(p, 1.0, 0.3);\r\n}\r\n\r\nfloat easeElasticInOut(float t, float b, float c, float d, float amplitude, float period) {\r\n return b + easeElasticInOut(t / d, amplitude, period) * c;\r\n}\r\n\r\nfloat easeElasticInOut(float t, float b, float c, float d) {\r\n return b + easeElasticInOut(t / d) * c;\r\n}\r\n"; var ease_elastic_out = "float easeElasticOut(float p, float amplitude, float period) {\r\n float p1 = max(amplitude, 1.0);\r\n float p2 = period / min(amplitude, 1.0);\r\n float p3 = p2 / PI2 * (asin(1.0 / p1));\r\n\r\n return p1 * pow(2.0, -10.0 * p) * sin((p - p3) * PI2 / p2) + 1.0;\r\n}\r\n\r\nfloat easeElasticOut(float p) {\r\n return easeElasticOut(p, 1.0, 0.3);\r\n}\r\n\r\nfloat easeElasticOut(float t, float b, float c, float d, float amplitude, float period) {\r\n return b + easeElasticOut(t / d, amplitude, period) * c;\r\n}\r\n\r\nfloat easeElasticOut(float t, float b, float c, float d) {\r\n return b + easeElasticOut(t / d) * c;\r\n}\r\n"; var ease_expo_in = "float easeExpoIn(float p) {\r\n return pow(2.0, 10.0 * (p - 1.0));\r\n}\r\n\r\nfloat easeExpoIn(float t, float b, float c, float d) {\r\n return b + easeExpoIn(t / d) * c;\r\n}\r\n"; var ease_expo_in_out = "float easeExpoInOut(float p) {\r\n return ((p *= 2.0) < 1.0) ? 0.5 * pow(2.0, 10.0 * (p - 1.0)) : 0.5 * (2.0 - pow(2.0, -10.0 * (p - 1.0)));\r\n}\r\n\r\nfloat easeExpoInOut(float t, float b, float c, float d) {\r\n return b + easeExpoInOut(t / d) * c;\r\n}\r\n"; var ease_expo_out = "float easeExpoOut(float p) {\r\n return 1.0 - pow(2.0, -10.0 * p);\r\n}\r\n\r\nfloat easeExpoOut(float t, float b, float c, float d) {\r\n return b + easeExpoOut(t / d) * c;\r\n}\r\n"; var ease_quad_in = "float easeQuadIn(float t) {\r\n return t * t;\r\n}\r\n\r\nfloat easeQuadIn(float t, float b, float c, float d) {\r\n return b + easeQuadIn(t / d) * c;\r\n}\r\n"; var ease_quad_in_out = "float easeQuadInOut(float t) {\r\n float p = 2.0 * t * t;\r\n return t < 0.5 ? p : -p + (4.0 * t) - 1.0;\r\n}\r\n\r\nfloat easeQuadInOut(float t, float b, float c, float d) {\r\n return b + easeQuadInOut(t / d) * c;\r\n}\r\n"; var ease_quad_out = "float easeQuadOut(float t) {\r\n return -t * (t - 2.0);\r\n}\r\n\r\nfloat easeQuadOut(float t, float b, float c, float d) {\r\n return b + easeQuadOut(t / d) * c;\r\n}\r\n"; var ease_quart_in = "float easeQuartIn(float t) {\r\n return t * t * t * t;\r\n}\r\n\r\nfloat easeQuartIn(float t, float b, float c, float d) {\r\n return b + easeQuartIn(t / d) * c;\r\n}\r\n"; var ease_quart_in_out = "float easeQuartInOut(float t) {\r\n return t < 0.5 ? 8.0 * pow(t, 4.0) : -8.0 * pow(t - 1.0, 4.0) + 1.0;\r\n}\r\n\r\nfloat easeQuartInOut(float t, float b, float c, float d) {\r\n return b + easeQuartInOut(t / d) * c;\r\n}\r\n"; var ease_quart_out = "float easeQuartOut(float t) {\r\n return 1.0 - pow(1.0 - t, 4.0);\r\n}\r\n\r\nfloat easeQuartOut(float t, float b, float c, float d) {\r\n return b + easeQuartOut(t / d) * c;\r\n}\r\n"; var ease_quint_in = "float easeQuintIn(float t) {\r\n return pow(t, 5.0);\r\n}\r\n\r\nfloat easeQuintIn(float t, float b, float c, float d) {\r\n return b + easeQuintIn(t / d) * c;\r\n}\r\n"; var ease_quint_in_out = "float easeQuintInOut(float t) {\r\n return (t /= 0.5) < 1.0 ? 0.5 * t * t * t * t * t : 0.5 * ((t -= 2.0) * t * t * t * t + 2.0);\r\n}\r\n\r\nfloat easeQuintInOut(float t, float b, float c, float d) {\r\n return b + easeQuintInOut(t / d) * c;\r\n}\r\n"; var ease_quint_out = "float easeQuintOut(float t) {\r\n return (t -= 1.0) * t * t * t * t + 1.0;\r\n}\r\n\r\nfloat easeQuintOut(float t, float b, float c, float d) {\r\n return b + easeQuintOut(t / d) * c;\r\n}\r\n"; var ease_sine_in = "float easeSineIn(float p) {\r\n return -cos(p * 1.57079632679) + 1.0;\r\n}\r\n\r\nfloat easeSineIn(float t, float b, float c, float d) {\r\n return b + easeSineIn(t / d) * c;\r\n}\r\n"; var ease_sine_in_out = "float easeSineInOut(float p) {\r\n return -0.5 * (cos(PI * p) - 1.0);\r\n}\r\n\r\nfloat easeSineInOut(float t, float b, float c, float d) {\r\n return b + easeSineInOut(t / d) * c;\r\n}\r\n"; var ease_sine_out = "float easeSineOut(float p) {\r\n return sin(p * 1.57079632679);\r\n}\r\n\r\nfloat easeSineOut(float t, float b, float c, float d) {\r\n return b + easeSineOut(t / d) * c;\r\n}\r\n"; var quadratic_bezier = "vec3 quadraticBezier(vec3 p0, vec3 c0, vec3 p1, float t) {\r\n float tn = 1.0 - t;\r\n\r\n return tn * tn * p0 + 2.0 * tn * t * c0 + t * t * p1;\r\n}\r\n\r\nvec2 quadraticBezier(vec2 p0, vec2 c0, vec2 p1, float t) {\r\n float tn = 1.0 - t;\r\n\r\n return tn * tn * p0 + 2.0 * tn * t * c0 + t * t * p1;\r\n}"; var quaternion_rotation = "vec3 rotateVector(vec4 q, vec3 v) {\r\n return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v);\r\n}\r\n\r\nvec4 quatFromAxisAngle(vec3 axis, float angle) {\r\n float halfAngle = angle * 0.5;\r\n return vec4(axis.xyz * sin(halfAngle), cos(halfAngle));\r\n}\r\n"; var quaternion_slerp = "vec4 quatSlerp(vec4 q0, vec4 q1, float t) {\r\n float s = 1.0 - t;\r\n float c = dot(q0, q1);\r\n float dir = -1.0; //c >= 0.0 ? 1.0 : -1.0;\r\n float sqrSn = 1.0 - c * c;\r\n\r\n if (sqrSn > 2.220446049250313e-16) {\r\n float sn = sqrt(sqrSn);\r\n float len = atan(sn, c * dir);\r\n\r\n s = sin(s * len) / sn;\r\n t = sin(t * len) / sn;\r\n }\r\n\r\n float tDir = t * dir;\r\n\r\n return normalize(q0 * s + q1 * tDir);\r\n}\r\n"; // generated by scripts/build_shader_chunks.js var ShaderChunk = { catmull_rom_spline: catmull_rom_spline, cubic_bezier: cubic_bezier, ease_back_in: ease_back_in, ease_back_in_out: ease_back_in_out, ease_back_out: ease_back_out, ease_bezier: ease_bezier, ease_bounce_in: ease_bounce_in, ease_bounce_in_out: ease_bounce_in_out, ease_bounce_out: ease_bounce_out, ease_circ_in: ease_circ_in, ease_circ_in_out: ease_circ_in_out, ease_circ_out: ease_circ_out, ease_cubic_in: ease_cubic_in, ease_cubic_in_out: ease_cubic_in_out, ease_cubic_out: ease_cubic_out, ease_elastic_in: ease_elastic_in, ease_elastic_in_out: ease_elastic_in_out, ease_elastic_out: ease_elastic_out, ease_expo_in: ease_expo_in, ease_expo_in_out: ease_expo_in_out, ease_expo_out: ease_expo_out, ease_quad_in: ease_quad_in, ease_quad_in_out: ease_quad_in_out, ease_quad_out: ease_quad_out, ease_quart_in: ease_quart_in, ease_quart_in_out: ease_quart_in_out, ease_quart_out: ease_quart_out, ease_quint_in: ease_quint_in, ease_quint_in_out: ease_quint_in_out, ease_quint_out: ease_quint_out, ease_sine_in: ease_sine_in, ease_sine_in_out: ease_sine_in_out, ease_sine_out: ease_sine_out, quadratic_bezier: quadratic_bezier, quaternion_rotation: quaternion_rotation, quaternion_slerp: quaternion_slerp }; /** * A timeline transition segment. An instance of this class is created internally when calling {@link THREE.BAS.Timeline.add}, so you should not use this class directly. * The instance is also passed the the compiler function if you register a transition through {@link THREE.BAS.Timeline.register}. There you can use the public properties of the segment to compile the glsl string. * @param {string} key A string key generated by the timeline to which this segment belongs. Keys are unique. * @param {number} start Start time of this segment in a timeline in seconds. * @param {number} duration Duration of this segment in seconds. * @param {object} transition Object describing the transition. * @param {function} compiler A reference to the compiler function from a transition definition. * @constructor */ function TimelineSegment(key, start, duration, transition, compiler) { this.key = key; this.start = start; this.duration = duration; this.transition = transition; this.compiler = compiler; this.trail = 0; } TimelineSegment.prototype.compile = function () { return this.compiler(this); }; Object.defineProperty(TimelineSegment.prototype, 'end', { get: function get() { return this.start + this.duration; } }); /** * A utility class to create an animation timeline which can be baked into a (vertex) shader. * By default the timeline supports translation, scale and rotation. This can be extended or overridden. * @constructor */ function Timeline() { /** * The total duration of the timeline in seconds. * @type {number} */ this.duration = 0; /** * The name of the value that segments will use to read the time. Defaults to 'tTime'. * @type {string} */ this.timeKey = 'tTime'; this.segments = {}; this.__key = 0; } // static definitions map Timeline.segmentDefinitions = {}; /** * Registers a transition definition for use with {@link THREE.BAS.Timeline.add}. * @param {String} key Name of the transition. Defaults include 'scale', 'rotate' and 'translate'. * @param {Object} definition * @param {Function} definition.compiler A function that generates a glsl string for a transition segment. Accepts a THREE.BAS.TimelineSegment as the sole argument. * @param {*} definition.defaultFrom The initial value for a transform.from. For example, the defaultFrom for a translation is THREE.Vector3(0, 0, 0). * @static */ Timeline.register = function (key, definition) { Timeline.segmentDefinitions[key] = definition; return definition; }; /** * Add a transition to the timeline. * @param {number} duration Duration in seconds * @param {object} transitions An object containing one or several transitions. The keys should match transform definitions. * The transition object for each key will be passed to the matching definition's compiler. It can have arbitrary properties, but the Timeline expects at least a 'to', 'from' and an optional 'ease'. * @param {number|string} [positionOffset] Position in the timeline. Defaults to the end of the timeline. If a number is provided, the transition will be inserted at that time in seconds. Strings ('+=x' or '-=x') can be used for a value relative to the end of timeline. */ Timeline.prototype.add = function (duration, transitions, positionOffset) { // stop rollup from complaining about eval var _eval = eval; var start = this.duration; if (positionOffset !== undefined) { if (typeof positionOffset === 'number') { start = positionOffset; } else if (typeof positionOffset === 'string') { _eval('start' + positionOffset); } this.duration = Math.max(this.duration, start + duration); } else { this.duration += duration; } var keys = Object.keys(transitions), key = void 0; for (var i = 0; i < keys.length; i++) { key = keys[i]; this.processTransition(key, transitions[key], start, duration); } }; Timeline.prototype.processTransition = function (key, transition, start, duration) { var definition = Timeline.segmentDefinitions[key]; var segments = this.segments[key]; if (!segments) segments = this.segments[key] = []; if (transition.from === undefined) { if (segments.length === 0) { transition.from = definition.defaultFrom; } else { transition.from = segments[segments.length - 1].transition.to; } } segments.push(new TimelineSegment((this.__key++).toString(), start, duration, transition, definition.compiler)); }; /** * Compiles the timeline into a glsl string array that can be injected into a (vertex) shader. * @returns {Array} */ Timeline.prototype.compile = function () { var c = []; var keys = Object.keys(this.segments); var segments = void 0; for (var i = 0; i < keys.length; i++) { segments = this.segments[keys[i]]; this.fillGaps(segments); segments.forEach(function (s) { c.push(s.compile()); }); } return c; }; Timeline.prototype.fillGaps = function (segments) { if (segments.length === 0) return; var s0 = void 0, s1 = void 0; for (var i = 0; i < segments.length - 1; i++) { s0 = segments[i]; s1 = segments[i + 1]; s0.trail = s1.start - s0.end; } // pad last segment until end of timeline s0 = segments[segments.length - 1]; s0.trail = this.duration - s0.end; }; /** * Get a compiled glsl string with calls to transform functions for a given key. * The order in which these transitions are applied matters because they all operate on the same value. * @param {string} key A key matching a transform definition. * @returns {string} */ Timeline.prototype.getTransformCalls = function (key) { var t = this.timeKey; return this.segments[key] ? this.segments[key].map(function (s) { return 'applyTransform' + s.key + '(' + t + ', transformed);'; }).join('\n') : ''; }; var TimelineChunks = { vec3: function vec3(n, v, p) { var x = (v.x || 0).toPrecision(p); var y = (v.y || 0).toPrecision(p); var z = (v.z || 0).toPrecision(p); return "vec3 " + n + " = vec3(" + x + ", " + y + ", " + z + ");"; }, vec4: function vec4(n, v, p) { var x = (v.x || 0).toPrecision(p); var y = (v.y || 0).toPrecision(p); var z = (v.z || 0).toPrecision(p); var w = (v.w || 0).toPrecision(p); return "vec4 " + n + " = vec4(" + x + ", " + y + ", " + z + ", " + w + ");"; }, delayDuration: function delayDuration(segment) { return "\n float cDelay" + segment.key + " = " + segment.start.toPrecision(4) + ";\n float cDuration" + segment.key + " = " + segment.duration.toPrecision(4) + ";\n "; }, progress: function progress(segment) { // zero duration segments should always render complete if (segment.duration === 0) { return "float progress = 1.0;"; } else { return "\n float progress = clamp(time - cDelay" + segment.key + ", 0.0, cDuration" + segment.key + ") / cDuration" + segment.key + ";\n " + (segment.transition.ease ? "progress = " + segment.transition.ease + "(progress" + (segment.transition.easeParams ? ", " + segment.transition.easeParams.map(function (v) { return v.toPrecision(4); }).join(", ") : "") + ");" : "") + "\n "; } }, renderCheck: function renderCheck(segment) { var startTime = segment.start.toPrecision(4); var endTime = (segment.end + segment.trail).toPrecision(4); return "if (time < " + startTime + " || time > " + endTime + ") return;"; } }; var TranslationSegment = { compiler: function compiler(segment) { return '\n ' + TimelineChunks.delayDuration(segment) + '\n ' + TimelineChunks.vec3('cTranslateFrom' + segment.key, segment.transition.from, 2) + '\n ' + TimelineChunks.vec3('cTranslateTo' + segment.key, segment.transition.to, 2) + '\n \n void applyTransform' + segment.key + '(float time, inout vec3 v) {\n \n ' + TimelineChunks.renderCheck(segment) + '\n ' + TimelineChunks.progress(segment) + '\n \n v += mix(cTranslateFrom' + segment.key + ', cTranslateTo' + segment.key + ', progress);\n }\n '; }, defaultFrom: new three.Vector3(0, 0, 0) }; Timeline.register('translate', TranslationSegment); var ScaleSegment = { compiler: function compiler(segment) { var origin = segment.transition.origin; return '\n ' + TimelineChunks.delayDuration(segment) + '\n ' + TimelineChunks.vec3('cScaleFrom' + segment.key, segment.transition.from, 2) + '\n ' + TimelineChunks.vec3('cScaleTo' + segment.key, segment.transition.to, 2) + '\n ' + (origin ? TimelineChunks.vec3('cOrigin' + segment.key, origin, 2) : '') + '\n \n void applyTransform' + segment.key + '(float time, inout vec3 v) {\n \n ' + TimelineChunks.renderCheck(segment) + '\n ' + TimelineChunks.progress(segment) + '\n \n ' + (origin ? 'v -= cOrigin' + segment.key + ';' : '') + '\n v *= mix(cScaleFrom' + segment.key + ', cScaleTo' + segment.key + ', progress);\n ' + (origin ? 'v += cOrigin' + segment.key + ';' : '') + '\n }\n '; }, defaultFrom: new three.Vector3(1, 1, 1) }; Timeline.register('scale', ScaleSegment); var RotationSegment = { compiler: function compiler(segment) { var fromAxisAngle = new three.Vector4(segment.transition.from.axis.x, segment.transition.from.axis.y, segment.transition.from.axis.z, segment.transition.from.angle); var toAxis = segment.transition.to.axis || segment.transition.from.axis; var toAxisAngle = new three.Vector4(toAxis.x, toAxis.y, toAxis.z, segment.transition.to.angle); var origin = segment.transition.origin; return '\n ' + TimelineChunks.delayDuration(segment) + '\n ' + TimelineChunks.vec4('cRotationFrom' + segment.key, fromAxisAngle, 8) + '\n ' + TimelineChunks.vec4('cRotationTo' + segment.key, toAxisAngle, 8) + '\n ' + (origin ? TimelineChunks.vec3('cOrigin' + segment.key, origin, 2) : '') + '\n \n void applyTransform' + segment.key + '(float time, inout vec3 v) {\n ' + TimelineChunks.renderCheck(segment) + '\n ' + TimelineChunks.progress(segment) + '\n\n ' + (origin ? 'v -= cOrigin' + segment.key + ';' : '') + '\n vec3 axis = normalize(mix(cRotationFrom' + segment.key + '.xyz, cRotationTo' + segment.key + '.xyz, progress));\n float angle = mix(cRotationFrom' + segment.key + '.w, cRotationTo' + segment.key + '.w, progress);\n vec4 q = quatFromAxisAngle(axis, angle);\n v = rotateVector(q, v);\n ' + (origin ? 'v += cOrigin' + segment.key + ';' : '') + '\n }\n '; }, defaultFrom: { axis: new three.Vector3(), angle: 0 } }; Timeline.register('rotate', RotationSegment); exports.BasicAnimationMaterial = BasicAnimationMaterial; exports.LambertAnimationMaterial = LambertAnimationMaterial; exports.PhongAnimationMaterial = PhongAnimationMaterial; exports.StandardAnimationMaterial = StandardAnimationMaterial; exports.PointsAnimationMaterial = PointsAnimationMaterial; exports.DepthAnimationMaterial = DepthAnimationMaterial; exports.DistanceAnimationMaterial = DistanceAnimationMaterial; exports.PrefabBufferGeometry = PrefabBufferGeometry; exports.MultiPrefabBufferGeometry = MultiPrefabBufferGeometry; exports.ModelBufferGeometry = ModelBufferGeometry; exports.PointBufferGeometry = PointBufferGeometry; exports.ShaderChunk = ShaderChunk; exports.Timeline = Timeline; exports.TimelineSegment = TimelineSegment; exports.TimelineChunks = TimelineChunks; exports.TranslationSegment = TranslationSegment; exports.ScaleSegment = ScaleSegment; exports.RotationSegment = RotationSegment; exports.Utils = Utils; Object.defineProperty(exports, '__esModule', { value: true }); })));